diff --git a/TransactionProcessor.Aggregates/TransactionProcessor.Aggregates.csproj b/TransactionProcessor.Aggregates/TransactionProcessor.Aggregates.csproj index c0ca0dec..8d10c00c 100644 --- a/TransactionProcessor.Aggregates/TransactionProcessor.Aggregates.csproj +++ b/TransactionProcessor.Aggregates/TransactionProcessor.Aggregates.csproj @@ -8,7 +8,7 @@ - + diff --git a/TransactionProcessor.BusinessLogic/TransactionProcessor.BusinessLogic.csproj b/TransactionProcessor.BusinessLogic/TransactionProcessor.BusinessLogic.csproj index 6b95d77c..7b6b2d8a 100644 --- a/TransactionProcessor.BusinessLogic/TransactionProcessor.BusinessLogic.csproj +++ b/TransactionProcessor.BusinessLogic/TransactionProcessor.BusinessLogic.csproj @@ -6,15 +6,15 @@ - + - - + + diff --git a/TransactionProcessor.Client/TransactionProcessor.Client.csproj b/TransactionProcessor.Client/TransactionProcessor.Client.csproj index c30ae1f4..afb7698a 100644 --- a/TransactionProcessor.Client/TransactionProcessor.Client.csproj +++ b/TransactionProcessor.Client/TransactionProcessor.Client.csproj @@ -6,8 +6,8 @@ - - + + diff --git a/TransactionProcessor.Database/TransactionProcessor.Database.csproj b/TransactionProcessor.Database/TransactionProcessor.Database.csproj index c449268c..0fd2cd9b 100644 --- a/TransactionProcessor.Database/TransactionProcessor.Database.csproj +++ b/TransactionProcessor.Database/TransactionProcessor.Database.csproj @@ -18,9 +18,9 @@ - + - + diff --git a/TransactionProcessor.DatabaseTests/BaseTest.cs b/TransactionProcessor.DatabaseTests/BaseTest.cs index ed6ca128..56b9cb45 100644 --- a/TransactionProcessor.DatabaseTests/BaseTest.cs +++ b/TransactionProcessor.DatabaseTests/BaseTest.cs @@ -17,6 +17,7 @@ using System.Net.Http.Headers; using System.Text; using System.Threading.Tasks; +using Shared.IntegrationTesting.Ductus; using TransactionProcessor.Database.Contexts; using TransactionProcessor.Repository; using Xunit.Abstractions; diff --git a/TransactionProcessor.DatabaseTests/TransactionProcessor.DatabaseTests.csproj b/TransactionProcessor.DatabaseTests/TransactionProcessor.DatabaseTests.csproj index 587cf3aa..059a1ece 100644 --- a/TransactionProcessor.DatabaseTests/TransactionProcessor.DatabaseTests.csproj +++ b/TransactionProcessor.DatabaseTests/TransactionProcessor.DatabaseTests.csproj @@ -13,7 +13,7 @@ all runtime; build; native; contentfiles; analyzers; buildtransitive - + @@ -21,8 +21,7 @@ all runtime; build; native; contentfiles; analyzers; buildtransitive - - + diff --git a/TransactionProcessor.DomainEvents/TransactionProcessor.DomainEvents.csproj b/TransactionProcessor.DomainEvents/TransactionProcessor.DomainEvents.csproj index e5e75941..a2ecf987 100644 --- a/TransactionProcessor.DomainEvents/TransactionProcessor.DomainEvents.csproj +++ b/TransactionProcessor.DomainEvents/TransactionProcessor.DomainEvents.csproj @@ -6,6 +6,6 @@ enable - + diff --git a/TransactionProcessor.IntegrationTesting.Helpers/TransactionProcessor.IntegrationTesting.Helpers.csproj b/TransactionProcessor.IntegrationTesting.Helpers/TransactionProcessor.IntegrationTesting.Helpers.csproj index 3686b55c..661e3428 100644 --- a/TransactionProcessor.IntegrationTesting.Helpers/TransactionProcessor.IntegrationTesting.Helpers.csproj +++ b/TransactionProcessor.IntegrationTesting.Helpers/TransactionProcessor.IntegrationTesting.Helpers.csproj @@ -7,11 +7,11 @@ - - + + - + diff --git a/TransactionProcessor.IntegrationTests/Common/DockerHelper.cs b/TransactionProcessor.IntegrationTests/Common/DockerHelper.cs index cc73ccc6..14757b56 100644 --- a/TransactionProcessor.IntegrationTests/Common/DockerHelper.cs +++ b/TransactionProcessor.IntegrationTests/Common/DockerHelper.cs @@ -1,28 +1,128 @@ -using TransactionProcessor.Database.Contexts; +using Ductus.FluentDocker.Model.Containers; +using Ductus.FluentDocker.Services; +using Shared.IntegrationTesting.TestContainers; +using SimpleResults; +using TransactionProcessor.Database.Contexts; namespace TransactionProcessor.IntegrationTests.Common { - using System; - using System.Collections.Generic; - using System.Net.Http; - using System.Text; - using System.Threading; - using System.Threading.Tasks; using Client; using Ductus.FluentDocker.Builders; + using Ductus.FluentDocker.Executors; + using Ductus.FluentDocker.Services.Extensions; using EventStore.Client; using global::Shared.IntegrationTesting; using Newtonsoft.Json; using SecurityService.Client; using Shouldly; + using System; + using System.Collections.Generic; + using System.Linq; + using System.Net.Http; + using System.Text; + using System.Threading; + using System.Threading.Tasks; using Retry = IntegrationTests.Retry; /// /// /// /// - public class DockerHelper : global::Shared.IntegrationTesting.DockerHelper + public class DockerHelper : global::Shared.IntegrationTesting.TestContainers.DockerHelper { + + /*public override INetworkService SetupTestNetwork(String networkName = null, + Boolean reuseIfExists = false) + { + networkName = String.IsNullOrEmpty(networkName) ? $"testnw{this.TestId:N}" : networkName; + //SimpleResults.Result engineType = BaseDockerHelper.GetDockerEnginePlatform(); + //Console.WriteLine($"Engine Type is {engineType.Data}"); + + // Build a network + NetworkBuilder networkService = new Builder().UseNetwork(networkName).ReuseIfExist(); + + return networkService.Build(); + } + + public override async Task SetupSqlServerContainer(INetworkService networkService) + { + if (this.SqlCredentials == default) + throw new ArgumentNullException("Sql Credentials have not been set"); + + IContainerService databaseServerContainer = await this.StartContainerX(this.ConfigureSqlContainer, + new List{ + networkService + }, + DockerServices.SqlServer); + + return databaseServerContainer; + }*/ + /* + protected async Task StartContainerX(Func buildContainerFunc, List networkServices, DockerServices dockerService) + { + if ((this.RequiredDockerServices & dockerService) != dockerService) + { + return default; + } + + //ConsoleStream consoleLogs = null; + try { + Result dockerEnginePlatform = await BaseDockerHelper.GetDockerEnginePlatform(); + Console.WriteLine($"Engine Type is {dockerEnginePlatform.Data}"); + + this.Trace($"{dockerService} about to call builder func"); + ContainerBuilder containerBuilder = buildContainerFunc(); + + this.Trace($"{dockerService} about to call build"); + IContainerService builtContainer = containerBuilder.Build(); + + this.Trace($"{dockerService} about to attach logs"); + //consoleLogs = builtContainer.Logs(true); + + this.Trace($"{dockerService} about to call Start"); + IContainerService startedContainer = builtContainer.Start(); + if (startedContainer == null) + throw new Exception($"{dockerService} startedContainer is null"); + this.Trace($"{dockerService} after call to Start"); + if (networkServices == null || networkServices.Count == 0) { + this.Trace($"{dockerService} No network services to attach"); + } + else{ + foreach (INetworkService networkService in networkServices) { + this.Trace($"{dockerService} about to attach network service"); + if (networkService == null) + throw new ArgumentNullException("networkService is null"); + + networkService.Attach(startedContainer, false); + } + } + + this.Trace($"{dockerService} Container Started"); + this.Containers.Add((dockerService, startedContainer)); + + await DoSqlServerHealthCheck(startedContainer); + + this.Trace($"Container [{buildContainerFunc.Method.Name}] started"); + + return startedContainer; + } + catch (Exception ex) + { + //if (consoleLogs != null) + //{ + // while (!consoleLogs.IsFinished) + // { + // String s = consoleLogs.TryRead(10000); + // this.Trace(s); + // } + //} + + this.Error($"Error starting container [{buildContainerFunc.Method.Name}]", ex); + throw; + } + } + */ + #region Fields public static String TestBankAccountNumber = "12345678"; @@ -85,7 +185,7 @@ await Retry.For(async () => responseMessage.IsSuccessStatusCode.ShouldBeTrue(); }); } - + /* public override ContainerBuilder SetupTransactionProcessorContainer(){ List variables = new List(); @@ -95,7 +195,7 @@ public override ContainerBuilder SetupTransactionProcessorContainer(){ //this.SetAdditionalVariables(ContainerType.FileProcessor, variables); return base.SetupTransactionProcessorContainer(); - } + }*/ public override async Task CreateSubscriptions(){ List<(String streamName, String groupName, Int32 maxRetries)> subscriptions = new(); @@ -109,7 +209,7 @@ public override async Task CreateSubscriptions(){ } } - public override ContainerBuilder SetupSecurityServiceContainer() + /*public override ContainerBuilder SetupSecurityServiceContainer() { this.Trace("About to Start Security Container"); @@ -157,7 +257,7 @@ public override ContainerBuilder SetupSecurityServiceContainer() // Now build and return the container return securityServiceContainer; - } + }*/ /// /// Starts the containers for scenario run. @@ -204,23 +304,64 @@ public override async Task StopContainersForScenarioRun(DockerServices dockerSer await base.StopContainersForScenarioRun(dockerServices); } - - private async Task RemoveEstateReadModel() + + /*public async Task StopContainersForScenarioRunX(DockerServices sharedDockerServices) { - List estateIdList = this.TestingContext.GetAllEstateIds(); + if (this.Containers.Any()) + { + this.Containers.Reverse(); + + foreach ((DockerServices, IContainerService) containerService in this.Containers) + { + + if ((sharedDockerServices & containerService.Item1) == containerService.Item1) + { + continue; + } + + this.Trace($"Stopping container [{containerService.Item2.Name}]"); + if (containerService.Item2.Name.Contains("eventstore")) + { + CopyEventStoreLogs(containerService.Item2); + } + + containerService.Item2.Stop(); + containerService.Item2.Remove(true); + this.Trace($"Container [{containerService.Item2.Name}] stopped"); + } + } - foreach (Guid estateId in estateIdList) + if (this.TestNetworks.Any()) { - String databaseName = $"EstateReportingReadModel{estateId}"; - - await Retry.For(async () => - { - // Build the connection string (to master) - String connectionString = Setup.GetLocalConnectionString(databaseName); - EstateManagementContext context = new EstateManagementContext(connectionString); - await context.Database.EnsureDeletedAsync(CancellationToken.None); - }); + foreach (INetworkService networkService in this.TestNetworks) + { + this.Trace($"Teardown network {networkService.Name}"); + var cfg = networkService.GetConfiguration(true); + if (!cfg.Containers.Any()) + { + networkService.Stop(); + networkService.Remove(true); + } + } } + */ + + private async Task RemoveEstateReadModel() + { + //List estateIdList = this.TestingContext.GetAllEstateIds(); + + //foreach (Guid estateId in estateIdList) + //{ + // String databaseName = $"EstateReportingReadModel{estateId}"; + + // await Retry.For(async () => + // { + // // Build the connection string (to master) + // String connectionString = Setup.GetLocalConnectionString(databaseName); + // EstateManagementContext context = new EstateManagementContext(connectionString); + // await context.Database.EnsureDeletedAsync(CancellationToken.None); + // }); + //} } protected override List GetRequiredProjections() diff --git a/TransactionProcessor.IntegrationTests/Common/GenericSteps.cs b/TransactionProcessor.IntegrationTests/Common/GenericSteps.cs index b00f94af..377ddefc 100644 --- a/TransactionProcessor.IntegrationTests/Common/GenericSteps.cs +++ b/TransactionProcessor.IntegrationTests/Common/GenericSteps.cs @@ -1,12 +1,20 @@ -using System; +using Ductus.FluentDocker.Commands; +using SimpleResults; +using System; +using Ductus.FluentDocker.Model; +using Ductus.FluentDocker.Model.Containers; +using Newtonsoft.Json; +using Shared.IntegrationTesting.TestContainers; namespace TransactionProcessor.IntegrationTests.Common { - using System.Threading.Tasks; + using Ductus.FluentDocker.Services; using global::Shared.IntegrationTesting; using global::Shared.Logger; + using Microsoft.Extensions.Hosting; using NLog; using Reqnroll; + using System.Threading.Tasks; [Binding] [Scope(Tag = "base")] @@ -22,7 +30,7 @@ public GenericSteps(ScenarioContext scenarioContext, this.ScenarioContext = scenarioContext; this.TestingContext = testingContext; } - + [BeforeScenario] public async Task StartSystem() { @@ -32,24 +40,21 @@ public async Task StartSystem() logger.Initialise(LogManager.GetLogger(scenarioName), scenarioName); LogManager.AddHiddenAssembly(typeof(NlogLogger).Assembly); - DockerServices dockerServices = DockerServices.CallbackHandler | DockerServices.EventStore | - DockerServices.FileProcessor | DockerServices.MessagingService | DockerServices.SecurityService | - DockerServices.SqlServer | DockerServices.TestHost | DockerServices.TransactionProcessor | + DockerServices dockerServices = DockerServices.SqlServer | DockerServices.EventStore | DockerServices.MessagingService | DockerServices.SecurityService | + DockerServices.CallbackHandler | DockerServices.FileProcessor | + DockerServices.TestHost | DockerServices.TransactionProcessor | DockerServices.TransactionProcessorAcl; + this.TestingContext.DockerHelper = new DockerHelper(); this.TestingContext.DockerHelper.Logger = logger; this.TestingContext.Logger = logger; this.TestingContext.DockerHelper.RequiredDockerServices = dockerServices; - this.TestingContext.Logger.LogInformation("About to Start Global Setup"); + this.TestingContext.Logger.LogInformation($"About to Start Global Setup"); - await Setup.GlobalSetup(this.TestingContext.DockerHelper); + this.TestingContext.DockerHelper.SetImageDetails(ContainerType.SqlServer, ("mcr.microsoft.com/mssql/server:2019-latest", true)); - this.TestingContext.DockerHelper.SqlServerContainer = Setup.DatabaseServerContainer; - this.TestingContext.DockerHelper.SqlServerNetwork = Setup.DatabaseServerNetwork; - this.TestingContext.DockerHelper.DockerCredentials = Setup.DockerCredentials; - this.TestingContext.DockerHelper.SqlCredentials = Setup.SqlCredentials; - this.TestingContext.DockerHelper.SqlServerContainerName = "sharedsqlserver"; + await Setup.GlobalSetup(this.TestingContext.DockerHelper); this.TestingContext.DockerHelper.SetImageDetails(ContainerType.TransactionProcessor, ("transactionprocessor", false)); @@ -62,7 +67,7 @@ public async Task StartSystem() [AfterScenario] public async Task StopSystem(){ - DockerServices sharedDockerServices = DockerServices.SqlServer; + DockerServices sharedDockerServices = DockerServices.None; this.TestingContext.Logger.LogInformation("About to Stop Containers for Scenario Run"); await this.TestingContext.DockerHelper.StopContainersForScenarioRun(sharedDockerServices).ConfigureAwait(false); diff --git a/TransactionProcessor.IntegrationTests/Common/Setup.cs b/TransactionProcessor.IntegrationTests/Common/Setup.cs index 42c88b4b..d5f87cf9 100644 --- a/TransactionProcessor.IntegrationTests/Common/Setup.cs +++ b/TransactionProcessor.IntegrationTests/Common/Setup.cs @@ -1,50 +1,39 @@ using System; +using DotNet.Testcontainers.Containers; +using DotNet.Testcontainers.Networks; namespace TransactionProcessor.IntegrationTests.Common { - using System.Threading.Tasks; using Ductus.FluentDocker.Services; using Ductus.FluentDocker.Services.Extensions; + using global::Shared.IntegrationTesting; using Reqnroll; using Shouldly; + using System.Threading.Tasks; [Binding] public class Setup { - public static IContainerService DatabaseServerContainer; - public static INetworkService DatabaseServerNetwork; public static (String usename, String password) SqlCredentials = ("sa", "thisisalongpassword123!"); public static (String url, String username, String password) DockerCredentials = ("https://www.docker.com", "stuartferguson", "Sc0tland"); - static object padLock = new object(); // Object to lock on - + public static async Task GlobalSetup(DockerHelper dockerHelper) { ShouldlyConfiguration.DefaultTaskTimeout = TimeSpan.FromMinutes(1); - dockerHelper.SqlCredentials = Setup.SqlCredentials; - dockerHelper.DockerCredentials = Setup.DockerCredentials; - dockerHelper.SqlServerContainerName = "sharedsqlserver"; - - lock (Setup.padLock) - { - Setup.DatabaseServerNetwork = dockerHelper.SetupTestNetwork("sharednetwork"); - - dockerHelper.Logger.LogInformation("in start SetupSqlServerContainer"); - Setup.DatabaseServerContainer = dockerHelper.SetupSqlServerContainer(Setup.DatabaseServerNetwork).Result; - } } - public static String GetConnectionString(String databaseName) - { - return $"server={Setup.DatabaseServerContainer.Name};database={databaseName};user id={Setup.SqlCredentials.usename};password={Setup.SqlCredentials.password}"; - } + //public static String GetConnectionString(String databaseName) + //{ + // return $"server={Setup.DatabaseServerContainer.Name};database={databaseName};user id={Setup.SqlCredentials.usename};password={Setup.SqlCredentials.password}"; + //} - public static String GetLocalConnectionString(String databaseName) - { - Int32 databaseHostPort = Setup.DatabaseServerContainer.ToHostExposedEndpoint("1433/tcp").Port; + //public static String GetLocalConnectionString(String databaseName) + //{ + // Int32 databaseHostPort = Setup.DatabaseServerContainer.GetMappedPublicPort(1433); - return $"server=localhost,{databaseHostPort};database={databaseName};user id={Setup.SqlCredentials.usename};password={Setup.SqlCredentials.password}"; - } + // return $"server=localhost,{databaseHostPort};database={databaseName};user id={Setup.SqlCredentials.usename};password={Setup.SqlCredentials.password}"; + //} } } diff --git a/TransactionProcessor.IntegrationTests/Features/LogonTransaction.feature.cs b/TransactionProcessor.IntegrationTests/Features/LogonTransaction.feature.cs index 6f3fb606..480b58e9 100644 --- a/TransactionProcessor.IntegrationTests/Features/LogonTransaction.feature.cs +++ b/TransactionProcessor.IntegrationTests/Features/LogonTransaction.feature.cs @@ -334,11 +334,9 @@ await testRunner.GivenAsync("I have a token to access the estate management and [global::NUnit.Framework.TestAttribute()] [global::NUnit.Framework.DescriptionAttribute("Logon Transactions")] - [global::NUnit.Framework.CategoryAttribute("PRTest")] public async global::System.Threading.Tasks.Task LogonTransactions() { - string[] tagsOfScenario = new string[] { - "PRTest"}; + string[] tagsOfScenario = ((string[])(null)); global::System.Collections.Specialized.OrderedDictionary argumentsOfScenario = new global::System.Collections.Specialized.OrderedDictionary(); string pickleIndex = "0"; global::Reqnroll.ScenarioInfo scenarioInfo = new global::Reqnroll.ScenarioInfo("Logon Transactions", null, tagsOfScenario, argumentsOfScenario, featureTags, pickleIndex); diff --git a/TransactionProcessor.IntegrationTests/Features/Operator.feature.cs b/TransactionProcessor.IntegrationTests/Features/Operator.feature.cs index f9131d7f..6ad1dee7 100644 --- a/TransactionProcessor.IntegrationTests/Features/Operator.feature.cs +++ b/TransactionProcessor.IntegrationTests/Features/Operator.feature.cs @@ -188,11 +188,9 @@ public void ScenarioInitialize(global::Reqnroll.ScenarioInfo scenarioInfo, globa [global::NUnit.Framework.TestAttribute()] [global::NUnit.Framework.DescriptionAttribute("Update Operator")] - [global::NUnit.Framework.CategoryAttribute("PRTest")] public async global::System.Threading.Tasks.Task UpdateOperator() { - string[] tagsOfScenario = new string[] { - "PRTest"}; + string[] tagsOfScenario = ((string[])(null)); global::System.Collections.Specialized.OrderedDictionary argumentsOfScenario = new global::System.Collections.Specialized.OrderedDictionary(); string pickleIndex = "0"; global::Reqnroll.ScenarioInfo scenarioInfo = new global::Reqnroll.ScenarioInfo("Update Operator", null, tagsOfScenario, argumentsOfScenario, featureTags, pickleIndex); diff --git a/TransactionProcessor.IntegrationTests/Features/ReconciliationFeature.feature.cs b/TransactionProcessor.IntegrationTests/Features/ReconciliationFeature.feature.cs index 4c974ee5..7fd72913 100644 --- a/TransactionProcessor.IntegrationTests/Features/ReconciliationFeature.feature.cs +++ b/TransactionProcessor.IntegrationTests/Features/ReconciliationFeature.feature.cs @@ -399,11 +399,9 @@ await testRunner.GivenAsync("I have a token to access the estate management and [global::NUnit.Framework.TestAttribute()] [global::NUnit.Framework.DescriptionAttribute("Reconciliation Transactions")] - [global::NUnit.Framework.CategoryAttribute("PRTest")] public async global::System.Threading.Tasks.Task ReconciliationTransactions() { - string[] tagsOfScenario = new string[] { - "PRTest"}; + string[] tagsOfScenario = ((string[])(null)); global::System.Collections.Specialized.OrderedDictionary argumentsOfScenario = new global::System.Collections.Specialized.OrderedDictionary(); string pickleIndex = "0"; global::Reqnroll.ScenarioInfo scenarioInfo = new global::Reqnroll.ScenarioInfo("Reconciliation Transactions", null, tagsOfScenario, argumentsOfScenario, featureTags, pickleIndex); diff --git a/TransactionProcessor.IntegrationTests/Features/RedeemVoucher.feature.cs b/TransactionProcessor.IntegrationTests/Features/RedeemVoucher.feature.cs index cc094c23..c19c99d8 100644 --- a/TransactionProcessor.IntegrationTests/Features/RedeemVoucher.feature.cs +++ b/TransactionProcessor.IntegrationTests/Features/RedeemVoucher.feature.cs @@ -354,11 +354,9 @@ await testRunner.GivenAsync("I have a token to access the estate management and [global::NUnit.Framework.TestAttribute()] [global::NUnit.Framework.DescriptionAttribute("Redeem Vouchers")] - [global::NUnit.Framework.CategoryAttribute("PRTest")] public async global::System.Threading.Tasks.Task RedeemVouchers() { - string[] tagsOfScenario = new string[] { - "PRTest"}; + string[] tagsOfScenario = ((string[])(null)); global::System.Collections.Specialized.OrderedDictionary argumentsOfScenario = new global::System.Collections.Specialized.OrderedDictionary(); string pickleIndex = "0"; global::Reqnroll.ScenarioInfo scenarioInfo = new global::Reqnroll.ScenarioInfo("Redeem Vouchers", null, tagsOfScenario, argumentsOfScenario, featureTags, pickleIndex); diff --git a/TransactionProcessor.IntegrationTests/Features/SaleTransactionFeature.feature.cs b/TransactionProcessor.IntegrationTests/Features/SaleTransactionFeature.feature.cs index a1816050..a2312a0b 100644 --- a/TransactionProcessor.IntegrationTests/Features/SaleTransactionFeature.feature.cs +++ b/TransactionProcessor.IntegrationTests/Features/SaleTransactionFeature.feature.cs @@ -670,11 +670,9 @@ await testRunner.GivenAsync("I have a token to access the estate management and [global::NUnit.Framework.TestAttribute()] [global::NUnit.Framework.DescriptionAttribute("Sale Transactions")] - [global::NUnit.Framework.CategoryAttribute("PRTest")] public async global::System.Threading.Tasks.Task SaleTransactions() { - string[] tagsOfScenario = new string[] { - "PRTest"}; + string[] tagsOfScenario = ((string[])(null)); global::System.Collections.Specialized.OrderedDictionary argumentsOfScenario = new global::System.Collections.Specialized.OrderedDictionary(); string pickleIndex = "0"; global::Reqnroll.ScenarioInfo scenarioInfo = new global::Reqnroll.ScenarioInfo("Sale Transactions", null, tagsOfScenario, argumentsOfScenario, featureTags, pickleIndex); diff --git a/TransactionProcessor.IntegrationTests/Features/Settlement.feature.cs b/TransactionProcessor.IntegrationTests/Features/Settlement.feature.cs index 84b36d47..fa63f710 100644 --- a/TransactionProcessor.IntegrationTests/Features/Settlement.feature.cs +++ b/TransactionProcessor.IntegrationTests/Features/Settlement.feature.cs @@ -714,11 +714,9 @@ await testRunner.GivenAsync("I have a token to access the estate management and [global::NUnit.Framework.TestAttribute()] [global::NUnit.Framework.DescriptionAttribute("Process Settlement")] - [global::NUnit.Framework.CategoryAttribute("PRTest")] public async global::System.Threading.Tasks.Task ProcessSettlement() { - string[] tagsOfScenario = new string[] { - "PRTest"}; + string[] tagsOfScenario = ((string[])(null)); global::System.Collections.Specialized.OrderedDictionary argumentsOfScenario = new global::System.Collections.Specialized.OrderedDictionary(); string pickleIndex = "1"; global::Reqnroll.ScenarioInfo scenarioInfo = new global::Reqnroll.ScenarioInfo("Process Settlement", null, tagsOfScenario, argumentsOfScenario, featureTags, pickleIndex); diff --git a/TransactionProcessor.IntegrationTests/Features/SettlementReporting.feature.cs b/TransactionProcessor.IntegrationTests/Features/SettlementReporting.feature.cs index 6b33ca79..c9d2453e 100644 --- a/TransactionProcessor.IntegrationTests/Features/SettlementReporting.feature.cs +++ b/TransactionProcessor.IntegrationTests/Features/SettlementReporting.feature.cs @@ -758,12 +758,10 @@ await testRunner.GivenAsync("I have a token to access the estate management and [global::NUnit.Framework.TestAttribute()] [global::NUnit.Framework.DescriptionAttribute("Get Settlements - Merchant Filter")] [global::NUnit.Framework.CategoryAttribute("settlement")] - [global::NUnit.Framework.CategoryAttribute("PRTest")] public async global::System.Threading.Tasks.Task GetSettlements_MerchantFilter() { string[] tagsOfScenario = new string[] { - "settlement", - "PRTest"}; + "settlement"}; global::System.Collections.Specialized.OrderedDictionary argumentsOfScenario = new global::System.Collections.Specialized.OrderedDictionary(); string pickleIndex = "0"; global::Reqnroll.ScenarioInfo scenarioInfo = new global::Reqnroll.ScenarioInfo("Get Settlements - Merchant Filter", null, tagsOfScenario, argumentsOfScenario, featureTags, pickleIndex); diff --git a/TransactionProcessor.IntegrationTests/TransactionProcessor.IntegrationTests.csproj b/TransactionProcessor.IntegrationTests/TransactionProcessor.IntegrationTests.csproj index 5a2f00ad..2f358634 100644 --- a/TransactionProcessor.IntegrationTests/TransactionProcessor.IntegrationTests.csproj +++ b/TransactionProcessor.IntegrationTests/TransactionProcessor.IntegrationTests.csproj @@ -7,8 +7,8 @@ - - + + @@ -16,7 +16,7 @@ - + diff --git a/TransactionProcessor.ProjectionEngine/TransactionProcessor.ProjectionEngine.csproj b/TransactionProcessor.ProjectionEngine/TransactionProcessor.ProjectionEngine.csproj index 3e9da336..f0f712f8 100644 --- a/TransactionProcessor.ProjectionEngine/TransactionProcessor.ProjectionEngine.csproj +++ b/TransactionProcessor.ProjectionEngine/TransactionProcessor.ProjectionEngine.csproj @@ -12,8 +12,8 @@ - - + + diff --git a/TransactionProcessor.Repository/TransactionProcessor.Repository.csproj b/TransactionProcessor.Repository/TransactionProcessor.Repository.csproj index bc82c1b1..95ee6e97 100644 --- a/TransactionProcessor.Repository/TransactionProcessor.Repository.csproj +++ b/TransactionProcessor.Repository/TransactionProcessor.Repository.csproj @@ -14,8 +14,8 @@ - - + + diff --git a/TransactionProcessor.Testing/TransactionProcessor.Testing.csproj b/TransactionProcessor.Testing/TransactionProcessor.Testing.csproj index 18b802dc..a43f6e75 100644 --- a/TransactionProcessor.Testing/TransactionProcessor.Testing.csproj +++ b/TransactionProcessor.Testing/TransactionProcessor.Testing.csproj @@ -6,7 +6,7 @@ - + diff --git a/TransactionProcessor.Tests/TransactionProcessor.Tests.csproj b/TransactionProcessor.Tests/TransactionProcessor.Tests.csproj index 87b2d859..6520cd3a 100644 --- a/TransactionProcessor.Tests/TransactionProcessor.Tests.csproj +++ b/TransactionProcessor.Tests/TransactionProcessor.Tests.csproj @@ -7,7 +7,7 @@ - + diff --git a/TransactionProcessor/TransactionProcessor.csproj b/TransactionProcessor/TransactionProcessor.csproj index 7815593f..880fb0a8 100644 --- a/TransactionProcessor/TransactionProcessor.csproj +++ b/TransactionProcessor/TransactionProcessor.csproj @@ -10,7 +10,7 @@ - + @@ -34,10 +34,10 @@ - - + + - + diff --git a/workload-install.ps1 b/workload-install.ps1 new file mode 100644 index 00000000..271841b6 --- /dev/null +++ b/workload-install.ps1 @@ -0,0 +1,332 @@ +# +# Copyright (c) Samsung Electronics. All rights reserved. +# Licensed under the MIT license. See LICENSE file in the project root for full license information. +# + +<# +.SYNOPSIS +Installs Tizen workload manifest. +.DESCRIPTION +Installs the WorkloadManifest.json and WorkloadManifest.targets files for Tizen to the dotnet sdk. +.PARAMETER Version +Use specific VERSION +.PARAMETER DotnetInstallDir +Dotnet SDK Location installed +#> + +[cmdletbinding()] +param( + [Alias('v')][string]$Version="", + [Alias('d')][string]$DotnetInstallDir="", + [Alias('t')][string]$DotnetTargetVersionBand="", + [Alias('u')][switch]$UpdateAllWorkloads +) + +Set-StrictMode -Version Latest +$ErrorActionPreference = "Stop" +$ProgressPreference = "SilentlyContinue" + +$ManifestBaseName = "Samsung.NET.Sdk.Tizen.Manifest" +$global:FallbackId = "" + +$LatestVersionMap = [ordered]@{ + "$ManifestBaseName-6.0.100" = "7.0.101"; + "$ManifestBaseName-6.0.200" = "7.0.100-preview.13.6"; + "$ManifestBaseName-6.0.300" = "8.0.133"; + "$ManifestBaseName-6.0.400" = "9.0.104"; + "$ManifestBaseName-7.0.100-preview.6" = "7.0.100-preview.6.14"; + "$ManifestBaseName-7.0.100-preview.7" = "7.0.100-preview.7.20"; + "$ManifestBaseName-7.0.100-rc.1" = "7.0.100-rc.1.22"; + "$ManifestBaseName-7.0.100-rc.2" = "7.0.100-rc.2.24"; + "$ManifestBaseName-7.0.100" = "7.0.103"; + "$ManifestBaseName-7.0.200" = "7.0.105"; + "$ManifestBaseName-7.0.300" = "7.0.120"; + "$ManifestBaseName-7.0.400" = "10.0.106"; + "$ManifestBaseName-8.0.100-alpha.1" = "7.0.104"; + "$ManifestBaseName-8.0.100-preview.2" = "7.0.106"; + "$ManifestBaseName-8.0.100-preview.3" = "7.0.107"; + "$ManifestBaseName-8.0.100-preview.4" = "7.0.108"; + "$ManifestBaseName-8.0.100-preview.5" = "7.0.110"; + "$ManifestBaseName-8.0.100-preview.6" = "7.0.121"; + "$ManifestBaseName-8.0.100-preview.7" = "7.0.122"; + "$ManifestBaseName-8.0.100-rc.1" = "7.0.124"; + "$ManifestBaseName-8.0.100-rc.2" = "7.0.125"; + "$ManifestBaseName-8.0.100-rtm" = "7.0.127"; + "$ManifestBaseName-8.0.100" = "8.0.144"; + "$ManifestBaseName-8.0.200" = "8.0.157"; + "$ManifestBaseName-8.0.300" = "8.0.156"; + "$ManifestBaseName-8.0.400" = "10.0.109"; + "$ManifestBaseName-9.0.100-alpha.1" = "8.0.134"; + "$ManifestBaseName-9.0.100-preview.1" = "8.0.135"; + "$ManifestBaseName-9.0.100-preview.2" = "8.0.137"; + "$ManifestBaseName-9.0.100" = "10.0.104"; + "$ManifestBaseName-9.0.200" = "10.0.110"; + "$ManifestBaseName-9.0.300" = "10.0.111"; +} + +function New-TemporaryDirectory { + $parent = [System.IO.Path]::GetTempPath() + $name = [System.IO.Path]::GetRandomFileName() + New-Item -ItemType Directory -Path (Join-Path $parent $name) +} + +function Ensure-Directory([string]$TestDir) { + Try { + New-Item -ItemType Directory -Path $TestDir -Force -ErrorAction stop | Out-Null + [io.file]::OpenWrite($(Join-Path -Path $TestDir -ChildPath ".test-write-access")).Close() + Remove-Item -Path $(Join-Path -Path $TestDir -ChildPath ".test-write-access") -Force + } + Catch [System.UnauthorizedAccessException] { + Write-Error "No permission to install. Try run with administrator mode." + } +} + +function Get-LatestVersion([string]$Id) { + $attempts=3 + $sleepInSeconds=3 + do + { + try + { + $Response = Invoke-WebRequest -Uri https://api.nuget.org/v3-flatcontainer/$($Id.ToLowerInvariant())/index.json -UseBasicParsing | ConvertFrom-Json + return $Response.versions | Select-Object -Last 1 + } + catch { + Write-Host "Id: $Id" + Write-Host "An exception was caught: $($_.Exception.Message)" + } + + $attempts-- + if ($attempts -gt 0) { Start-Sleep $sleepInSeconds } + } while ($attempts -gt 0) + + if ($LatestVersionMap.Contains($Id)) + { + Write-Host "Return cached latest version." + return $LatestVersionMap.$Id + } + else + { + $SubStringId = $Id.Substring(0, $ManifestBaseName.Length + 2); + $MatchingFallbackId = @() + $MatchingFallbackVersion = @() + foreach ($key in $LatestVersionMap.Keys) { + if ($key -like "$SubStringId*") { + $MatchingFallbackId += $key + $MatchingFallbackVersion += $LatestVersionMap[$key] + } + } + if ($MatchingFallbackVersion) + { + $global:FallbackId = $MatchingFallbackId[-1] + $FallbackVersion = $MatchingFallbackVersion[-1] + Write-Host "Return fallback version: $FallbackVersion" + return $FallbackVersion + } + } + + Write-Error "Wrong Id: $Id" +} + +function Get-Package([string]$Id, [string]$Version, [string]$Destination, [string]$FileExt = "nupkg") { + $OutFileName = "$Id.$Version.$FileExt" + $OutFilePath = Join-Path -Path $Destination -ChildPath $OutFileName + + if ($Id -match ".net[0-9]+$") { + $Id = $Id -replace (".net[0-9]+", "") + } + + Invoke-WebRequest -Uri "https://www.nuget.org/api/v2/package/$Id/$Version" -OutFile $OutFilePath + + return $OutFilePath +} + +function Install-Pack([string]$Id, [string]$Version, [string]$Kind) { + $TempZipFile = $(Get-Package -Id $Id -Version $Version -Destination $TempDir -FileExt "zip") + $TempUnzipDir = Join-Path -Path $TempDir -ChildPath "unzipped\$Id" + + switch ($Kind) { + "manifest" { + Expand-Archive -Path $TempZipFile -DestinationPath $TempUnzipDir + New-Item -Path $TizenManifestDir -ItemType "directory" -Force | Out-Null + Copy-Item -Path "$TempUnzipDir\data\*" -Destination $TizenManifestDir -Force + } + {($_ -eq "sdk") -or ($_ -eq "framework")} { + Expand-Archive -Path $TempZipFile -DestinationPath $TempUnzipDir + if ( ($kind -eq "sdk") -and ($Id -match ".net[0-9]+$")) { + $Id = $Id -replace (".net[0-9]+", "") + } + $TargetDirectory = $(Join-Path -Path $DotnetInstallDir -ChildPath "packs\$Id\$Version") + New-Item -Path $TargetDirectory -ItemType "directory" -Force | Out-Null + Copy-Item -Path "$TempUnzipDir/*" -Destination $TargetDirectory -Recurse -Force + } + "template" { + $TargetFileName = "$Id.$Version.nupkg".ToLower() + $TargetDirectory = $(Join-Path -Path $DotnetInstallDir -ChildPath "template-packs") + New-Item -Path $TargetDirectory -ItemType "directory" -Force | Out-Null + Copy-Item $TempZipFile -Destination $(Join-Path -Path $TargetDirectory -ChildPath "$TargetFileName") -Force + } + } +} + +function Remove-Pack([string]$Id, [string]$Version, [string]$Kind) { + switch ($Kind) { + "manifest" { + Remove-Item -Path $TizenManifestDir -Recurse -Force + } + {($_ -eq "sdk") -or ($_ -eq "framework")} { + $TargetDirectory = $(Join-Path -Path $DotnetInstallDir -ChildPath "packs\$Id\$Version") + Remove-Item -Path $TargetDirectory -Recurse -Force + } + "template" { + $TargetFileName = "$Id.$Version.nupkg".ToLower(); + Remove-Item -Path $(Join-Path -Path $DotnetInstallDir -ChildPath "template-packs\$TargetFileName") -Force + } + } +} + +function Install-TizenWorkload([string]$DotnetVersion) +{ + $VersionSplitSymbol = '.' + $SplitVersion = $DotnetVersion.Split($VersionSplitSymbol) + + $CurrentDotnetVersion = [Version]"$($SplitVersion[0]).$($SplitVersion[1])" + $DotnetVersionBand = $SplitVersion[0] + $VersionSplitSymbol + $SplitVersion[1] + $VersionSplitSymbol + $SplitVersion[2][0] + "00" + $ManifestName = "$ManifestBaseName-$DotnetVersionBand" + + if ($DotnetTargetVersionBand -eq "" -or $UpdateAllWorkloads.IsPresent) { + if ($CurrentDotnetVersion -ge "7.0") + { + $IsPreviewVersion = $DotnetVersion.Contains("-preview") -or $DotnetVersion.Contains("-rc") -or $DotnetVersion.Contains("-alpha") + if ($IsPreviewVersion -and ($SplitVersion.Count -ge 4)) { + $DotnetTargetVersionBand = $DotnetVersionBand + $SplitVersion[2].SubString(3) + $VersionSplitSymbol + $($SplitVersion[3]) + $ManifestName = "$ManifestBaseName-$DotnetTargetVersionBand" + } + elseif ($DotnetVersion.Contains("-rtm") -and ($SplitVersion.Count -ge 3)) { + $DotnetTargetVersionBand = $DotnetVersionBand + $SplitVersion[2].SubString(3) + $ManifestName = "$ManifestBaseName-$DotnetTargetVersionBand" + } + else { + $DotnetTargetVersionBand = $DotnetVersionBand + } + } + else { + $DotnetTargetVersionBand = $DotnetVersionBand + } + } + + # Check latest version of manifest. + if ($Version -eq "" -or $UpdateAllWorkloads.IsPresent) { + $Version = Get-LatestVersion -Id $ManifestName + } + + # Check workload manifest directory. + $ManifestDir = Join-Path -Path $DotnetInstallDir -ChildPath "sdk-manifests" | Join-Path -ChildPath $DotnetTargetVersionBand + $TizenManifestDir = Join-Path -Path $ManifestDir -ChildPath "samsung.net.sdk.tizen" + $TizenManifestFile = Join-Path -Path $TizenManifestDir -ChildPath "WorkloadManifest.json" + + # Check and remove already installed old version. + if (Test-Path $TizenManifestFile) { + $ManifestJson = $(Get-Content $TizenManifestFile | ConvertFrom-Json) + $OldVersion = $ManifestJson.version + if ($OldVersion -eq $Version) { + $DotnetWorkloadList = Invoke-Expression "& '$DotnetCommand' workload list | Select-String -Pattern '^tizen'" + if ($DotnetWorkloadList) + { + Write-Host "Tizen Workload $Version version is already installed." + Continue + } + } + + Ensure-Directory $ManifestDir + Write-Host "Removing $ManifestName/$OldVersion from $ManifestDir..." + Remove-Pack -Id $ManifestName -Version $OldVersion -Kind "manifest" + $ManifestJson.packs.PSObject.Properties | ForEach-Object { + Write-Host "Removing $($_.Name)/$($_.Value.version)..." + Remove-Pack -Id $_.Name -Version $_.Value.version -Kind $_.Value.kind + } + } + + Ensure-Directory $ManifestDir + $TempDir = $(New-TemporaryDirectory) + + # Install workload manifest. + Write-Host "Installing $ManifestName/$Version to $ManifestDir..." + if ($global:FallbackId) { + Install-Pack -Id $global:FallbackId -Version $Version -Kind "manifest" + } else { + Install-Pack -Id $ManifestName -Version $Version -Kind "manifest" + } + + # Download and install workload packs. + $NewManifestJson = $(Get-Content $TizenManifestFile | ConvertFrom-Json) + $NewManifestJson.packs.PSObject.Properties | ForEach-Object { + Write-Host "Installing $($_.Name)/$($_.Value.version)..." + Install-Pack -Id $_.Name -Version $_.Value.version -Kind $_.Value.kind + } + + # Add tizen to the installed workload metadata. + # Featured version band for metadata does NOT include any preview specifier. + # https://github.com/dotnet/sdk/blob/main/documentation/general/workloads/user-local-workloads.md + New-Item -Path $(Join-Path -Path $DotnetInstallDir -ChildPath "metadata\workloads\$DotnetVersionBand\InstalledWorkloads\tizen") -Force | Out-Null + if (Test-Path $(Join-Path -Path $DotnetInstallDir -ChildPath "metadata\workloads\$DotnetVersionBand\InstallerType\msi")) { + New-Item -Path "HKLM:\SOFTWARE\Microsoft\dotnet\InstalledWorkloads\Standalone\x64\$DotnetTargetVersionBand\tizen" -Force | Out-Null + } + + # Clean up + Remove-Item -Path $TempDir -Force -Recurse + + Write-Host "Done installing Tizen workload $Version" +} + +# Check dotnet install directory. +if ($DotnetInstallDir -eq "") { + if ($Env:DOTNET_ROOT -And $(Test-Path "$Env:DOTNET_ROOT")) { + $DotnetInstallDir = $Env:DOTNET_ROOT + } else { + $DotnetInstallDir = Join-Path -Path $Env:Programfiles -ChildPath "dotnet" + } +} +if (-Not $(Test-Path "$DotnetInstallDir")) { + Write-Error "No installed dotnet '$DotnetInstallDir'." +} + +# Check installed dotnet version +$DotnetCommand = "$DotnetInstallDir\dotnet" +if (Get-Command $DotnetCommand -ErrorAction SilentlyContinue) +{ + if ($UpdateAllWorkloads.IsPresent) + { + $InstalledDotnetSdks = Invoke-Expression "& '$DotnetCommand' --list-sdks | Select-String -Pattern '^6|^7'" | ForEach-Object {$_ -replace (" \[.*","")} + } + else + { + $InstalledDotnetSdks = Invoke-Expression "& '$DotnetCommand' --version" + } +} +else +{ + Write-Error "'$DotnetCommand' occurs an error." +} + +if (-Not $InstalledDotnetSdks) +{ + Write-Host "`n.NET SDK version 6 or later is required to install Tizen Workload." +} +else +{ + foreach ($DotnetSdk in $InstalledDotnetSdks) + { + try { + Write-Host "`nCheck Tizen Workload for sdk $DotnetSdk" + Install-TizenWorkload -DotnetVersion $DotnetSdk + } + catch { + Write-Host "Failed to install Tizen Workload for sdk $DotnetSdk" + Write-Host "$_" + Continue + } + } +} + +Write-Host "`nDone"