// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\r
// SPDX-License-Identifier: Apache-2.0
using System.Linq;
using System.Threading.Tasks;
using AWS.Deploy.CLI.Commands;
using AWS.Deploy.CLI.ServerMode.Controllers;
using AWS.Deploy.CLI.ServerMode.Models;
using AWS.Deploy.Orchestration;
using Microsoft.AspNetCore.Mvc;
using Xunit;
using Moq;
using AWS.Deploy.Common.IO;
using AWS.Deploy.Common.DeploymentManifest;
using AWS.Deploy.Orchestration.LocalUserSettings;
using AWS.Deploy.CLI.Utilities;
using AWS.Deploy.Common;
using AWS.Deploy.CLI.UnitTests.Utilities;
using System.Collections.Generic;
using System.IO;
using AWS.Deploy.Common.Recipes;
using DeploymentTypes = AWS.Deploy.CLI.ServerMode.Models.DeploymentTypes;
using System;
using AWS.Deploy.Common.Recipes.Validation;
using AWS.Deploy.Recipes;
namespace AWS.Deploy.CLI.UnitTests
{
public class ServerModeTests
{
///
/// This test is to make sure the CLI is using at least version 5.0.0 of System.Text.Json. If we use verisons less then
/// 5.0.0 types that do not have a parameterless constructor will fail to deserialize. This affects the server mode model types.
/// The unit and integ test project force a newer version of System.Text.Json then would be used by default in the CLI masking the issue.
///
[Fact]
public void EnsureMinimumSystemTextJsonVersion()
{
var assembly = typeof(ServerModeCommand).Assembly;
var jsonAssemblyName = assembly.GetReferencedAssemblies().FirstOrDefault(x => string.Equals("System.Text.Json", x.Name, StringComparison.OrdinalIgnoreCase));
Assert.True(jsonAssemblyName.Version >= Version.Parse("5.0.0"));
}
[Fact]
public async Task TcpPortIsInUseTest()
{
var serverModeCommand1 = new ServerModeCommand(new TestToolInteractiveServiceImpl(), 1234, null, true);
var serverModeCommand2 = new ServerModeCommand(new TestToolInteractiveServiceImpl(), 1234, null, true);
var serverModeTask1 = serverModeCommand1.ExecuteAsync();
var serverModeTask2 = serverModeCommand2.ExecuteAsync();
await Task.WhenAny(serverModeTask1, serverModeTask2);
Assert.False(serverModeTask1.IsCompleted);
Assert.True(serverModeTask2.IsCompleted);
Assert.True(serverModeTask2.IsFaulted);
Assert.NotNull(serverModeTask2.Exception);
Assert.Single(serverModeTask2.Exception.InnerExceptions);
Assert.IsType(serverModeTask2.Exception.InnerException);
}
[Theory]
[InlineData("")]
[InlineData("InvalidId")]
public async Task RecipeController_GetRecipe_EmptyId(string recipeId)
{
var directoryManager = new DirectoryManager();
var fileManager = new FileManager();
var deploymentManifestEngine = new DeploymentManifestEngine(directoryManager, fileManager);
var consoleInteractiveServiceImpl = new ConsoleInteractiveServiceImpl();
var consoleOrchestratorLogger = new ConsoleOrchestratorLogger(consoleInteractiveServiceImpl);
var serviceProvider = new Mock();
var validatorFactory = new ValidatorFactory(serviceProvider.Object);
var optionSettingHandler = new OptionSettingHandler(validatorFactory);
var recipeHandler = new RecipeHandler(deploymentManifestEngine, consoleOrchestratorLogger, directoryManager, fileManager, optionSettingHandler, validatorFactory);
var projectDefinitionParser = new ProjectDefinitionParser(fileManager, directoryManager);
var recipeController = new RecipeController(recipeHandler, projectDefinitionParser);
var response = await recipeController.GetRecipe(recipeId);
Assert.IsType(response);
}
[Fact]
public async Task RecipeController_GetRecipe_HappyPath()
{
var directoryManager = new DirectoryManager();
var fileManager = new FileManager();
var deploymentManifestEngine = new DeploymentManifestEngine(directoryManager, fileManager);
var consoleInteractiveServiceImpl = new ConsoleInteractiveServiceImpl();
var consoleOrchestratorLogger = new ConsoleOrchestratorLogger(consoleInteractiveServiceImpl);
var projectDefinitionParser = new ProjectDefinitionParser(fileManager, directoryManager);
var serviceProvider = new Mock();
var validatorFactory = new ValidatorFactory(serviceProvider.Object);
var optionSettingHandler = new OptionSettingHandler(validatorFactory);
var recipeHandler = new RecipeHandler(deploymentManifestEngine, consoleOrchestratorLogger, directoryManager, fileManager, optionSettingHandler, validatorFactory);
var recipeController = new RecipeController(recipeHandler, projectDefinitionParser);
var recipeDefinitions = await recipeHandler.GetRecipeDefinitions(null);
var recipe = recipeDefinitions.First();
var response = await recipeController.GetRecipe(recipe.Id);
var result = Assert.IsType(response);
var resultRecipe = Assert.IsType(result.Value);
Assert.Equal(recipe.Id, resultRecipe.Id);
}
[Fact]
public async Task RecipeController_GetRecipe_WithProjectPath()
{
var directoryManager = new DirectoryManager();
var fileManager = new FileManager();
var projectDefinitionParser = new ProjectDefinitionParser(fileManager, directoryManager);
var deploymentManifestEngine = new Mock();
var serviceProvider = new Mock();
var validatorFactory = new ValidatorFactory(serviceProvider.Object);
var optionSettingHandler = new OptionSettingHandler(validatorFactory);
var customLocatorCalls = 0;
var sourceProjectDirectory = SystemIOUtilities.ResolvePath("WebAppWithDockerFile");
deploymentManifestEngine
.Setup(x => x.GetRecipeDefinitionPaths(It.IsAny()))
.Callback((csProjectPath) =>
{
customLocatorCalls++;
Assert.Equal(new DirectoryInfo(sourceProjectDirectory).FullName, Directory.GetParent(csProjectPath).FullName);
})
.ReturnsAsync(new List());
var orchestratorInteractiveService = new TestToolOrchestratorInteractiveService();
var recipeHandler = new RecipeHandler(deploymentManifestEngine.Object, orchestratorInteractiveService, directoryManager, fileManager, optionSettingHandler, validatorFactory);
var projectDefinition = await projectDefinitionParser.Parse(sourceProjectDirectory);
var recipePaths = new HashSet { RecipeLocator.FindRecipeDefinitionsPath() };
var customRecipePaths = await recipeHandler.LocateCustomRecipePaths(projectDefinition);
var recipeDefinitions = await recipeHandler.GetRecipeDefinitions(recipeDefinitionPaths: recipePaths.Union(customRecipePaths).ToList());
var recipe = recipeDefinitions.First();
Assert.NotEqual(0, customLocatorCalls);
customLocatorCalls = 0;
var recipeController = new RecipeController(recipeHandler, projectDefinitionParser);
var response = await recipeController.GetRecipe(recipe.Id, sourceProjectDirectory);
Assert.NotEqual(0, customLocatorCalls);
var result = Assert.IsType(response);
var resultRecipe = Assert.IsType(result.Value);
Assert.Equal(recipe.Id, resultRecipe.Id);
}
[Theory]
[InlineData(CloudApplicationResourceType.CloudFormationStack, DeploymentTypes.CloudFormationStack)]
[InlineData(CloudApplicationResourceType.BeanstalkEnvironment, DeploymentTypes.BeanstalkEnvironment)]
public void ExistingDeploymentSummary_ContainsCorrectDeploymentType(CloudApplicationResourceType resourceType, DeploymentTypes expectedDeploymentType)
{
var existingDeploymentSummary = new ExistingDeploymentSummary(
"name",
"baseRecipeId",
"recipeId",
"recipeName",
new List(),
false,
"shortDescription",
"description",
"targetService",
System.DateTime.Now,
true,
resourceType,
"uniqueId");
Assert.Equal(expectedDeploymentType, existingDeploymentSummary.DeploymentType);
}
[Theory]
[InlineData(Deploy.Common.Recipes.DeploymentTypes.CdkProject, DeploymentTypes.CloudFormationStack)]
[InlineData(Deploy.Common.Recipes.DeploymentTypes.BeanstalkEnvironment, DeploymentTypes.BeanstalkEnvironment)]
public void RecommendationSummary_ContainsCorrectDeploymentType(Deploy.Common.Recipes.DeploymentTypes deploymentType, DeploymentTypes expectedDeploymentType)
{
var recommendationSummary = new RecommendationSummary(
"baseRecipeId",
"recipeId",
"name",
new List(),
false,
"shortDescription",
"description",
"targetService",
deploymentType);
Assert.Equal(expectedDeploymentType, recommendationSummary.DeploymentType);
}
}
}