From dabee5566671dabe2d10523186dbcadfd4f0015d Mon Sep 17 00:00:00 2001 From: Tyrrellion Date: Fri, 30 May 2025 14:22:03 +0100 Subject: [PATCH 01/18] feat: initial code for compose and waiting for it all the be ready - needs developement Signed-off-by: Tyrrellion --- .../Functions/HealthCheck.cs | 14 +++ .../Functions/IntegrationTests.cs | 88 +++++++++++++++++++ 2 files changed, 102 insertions(+) create mode 100644 src/ServiceLayer.Mesh/Functions/HealthCheck.cs create mode 100644 tests/ServiceLayer.Mesh.Tests/Functions/IntegrationTests.cs diff --git a/src/ServiceLayer.Mesh/Functions/HealthCheck.cs b/src/ServiceLayer.Mesh/Functions/HealthCheck.cs new file mode 100644 index 0000000..3d9c384 --- /dev/null +++ b/src/ServiceLayer.Mesh/Functions/HealthCheck.cs @@ -0,0 +1,14 @@ +using Microsoft.Azure.Functions.Worker; +using Microsoft.Azure.Functions.Worker.Http; +using Microsoft.Extensions.Logging; +using System.Net; + +public class HealthCheckFunction +{ + [Function("HealthCheck")] + public async Task Run([HttpTrigger(AuthorizationLevel.Anonymous, "get", Route = "health")] HttpRequestData req) + { + var response = req.CreateResponse(HttpStatusCode.OK); + return response; + } +} diff --git a/tests/ServiceLayer.Mesh.Tests/Functions/IntegrationTests.cs b/tests/ServiceLayer.Mesh.Tests/Functions/IntegrationTests.cs new file mode 100644 index 0000000..c3d2706 --- /dev/null +++ b/tests/ServiceLayer.Mesh.Tests/Functions/IntegrationTests.cs @@ -0,0 +1,88 @@ +using System; +using System.Diagnostics; +using System.IO; +using System.Threading.Tasks; +using Microsoft.Data.SqlClient; +using Moq; + +namespace ServiceLayer.Mesh.Tests.Integration; + +public class IntegrationTests +{ + private const string ConnectionString = "Server=localhost,1433;User Id=sa;Password=YourPassword123;TrustServerCertificate=True;"; + + public IntegrationTests() + { + var environment = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT"); + if (environment == null) + { + throw new InvalidOperationException("ASPNETCORE_ENVIRONMENT environment variable is not set of is empty."); + } + if (environment == "development") + { + RunCommand("podman compose up"); + } + if (environment == "production") + { + RunCommand("docker compose up"); + } + + // Wait for SQL Server to be reachable + //await WaitForSqlServerAsync(); + } + + public void Teardown() + { + // Stop containers + RunCommand("docker compose down"); + } + + [Fact] + public async Task ShouldWriteToDatabase() + { + using var sql = new SqlConnection(ConnectionString); + await sql.OpenAsync(); + + // var count = await sql.ExecuteScalarAsync("SELECT COUNT(*) FROM SomeTable"); + // Assert.IsTrue(count > 0, "Expected at least one row in SomeTable."); + } + + private void RunCommand(string command) + { + var psi = new ProcessStartInfo("cmd", $"/c {command}") + { + RedirectStandardOutput = true, + RedirectStandardError = true, + UseShellExecute = false, + CreateNoWindow = true + }; + + using var process = Process.Start(psi); + process.WaitForExit(); + + if (process.ExitCode != 0) + { + throw new Exception($"Command failed: {command}\n{process.StandardError.ReadToEnd()}"); + } + } + + private async Task WaitForSqlServerAsync(int timeoutSeconds = 60) + { + var start = DateTime.UtcNow; + while ((DateTime.UtcNow - start).TotalSeconds < timeoutSeconds) + { + try + { + using var sql = new SqlConnection(ConnectionString); + await sql.OpenAsync(); + return; // Success + } + catch + { + await Task.Delay(1000); + } + } + + throw new TimeoutException("SQL Server did not become available in time."); + } +} From 803ce0befb25b322cd39bf543d6a36330a33a67c Mon Sep 17 00:00:00 2001 From: Tyrrellion Date: Fri, 30 May 2025 16:53:42 +0100 Subject: [PATCH 02/18] feat: its now sending a file to mesh! --- .../Functions/IntegrationTests.cs | 106 +++++++++++++----- .../ServiceLayer.Mesh.Tests.csproj | 3 +- .../TestData/KMK_20250212095121_APPT_87.dat | 8 ++ 3 files changed, 91 insertions(+), 26 deletions(-) create mode 100644 tests/ServiceLayer.Mesh.Tests/TestData/KMK_20250212095121_APPT_87.dat diff --git a/tests/ServiceLayer.Mesh.Tests/Functions/IntegrationTests.cs b/tests/ServiceLayer.Mesh.Tests/Functions/IntegrationTests.cs index c3d2706..1cfdeb8 100644 --- a/tests/ServiceLayer.Mesh.Tests/Functions/IntegrationTests.cs +++ b/tests/ServiceLayer.Mesh.Tests/Functions/IntegrationTests.cs @@ -5,6 +5,12 @@ using Microsoft.Data.SqlClient; using Moq; +using System; +using System.Net.Http; +using System.Net.Http.Headers; +using System.Threading.Tasks; +using ServiceLayer.Data; + namespace ServiceLayer.Mesh.Tests.Integration; public class IntegrationTests @@ -13,22 +19,39 @@ public class IntegrationTests public IntegrationTests() { - var environment = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT"); + + } + + private async Task SetupEnvironment() + { + var environment = "development"; if (environment == null) { throw new InvalidOperationException("ASPNETCORE_ENVIRONMENT environment variable is not set of is empty."); } if (environment == "development") { - RunCommand("podman compose up"); + RunCommand("podman compose up -d"); } if (environment == "production") { - RunCommand("docker compose up"); + RunCommand("docker compose up -d"); } - // Wait for SQL Server to be reachable - //await WaitForSqlServerAsync(); + bool environmentIsUp = false; + + while (environmentIsUp == false) + { + var responce = await HttpHelper.SendHttpRequestAsync(HttpMethod.Get, "http://localhost:7072/api/health"); + if (responce.IsSuccessStatusCode) + { + environmentIsUp = true; + } + else + { + await Task.Delay(1000); + } + } } public void Teardown() @@ -38,13 +61,32 @@ public void Teardown() } [Fact] - public async Task ShouldWriteToDatabase() + public async Task EndToEndTest() { - using var sql = new SqlConnection(ConnectionString); - await sql.OpenAsync(); + await SetupEnvironment(); + + byte[] binaryData = await File.ReadAllBytesAsync("TestData/KMK_20250212095121_APPT_87.dat"); + var content = new ByteArrayContent(binaryData); + content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream"); + + var response = await HttpHelper.SendHttpRequestAsync( + HttpMethod.Post, + "http://localhost:8700/messageexchange/X26ABC1/outbox", + content, + headers => + { + headers.Add("Authorization", "NHSMESH X26ABC1:a42f77b9-58de-4b45-b599-2d5bf320b44d:0:202407291437:e3005627136e01706efabcfe72269bc8da3192e90a840ab344ab7f82a39bb5c6"); + headers.Add("Mex-Filename", "KMK_20250212095121_APPT_87.dat"); + headers.Add("Mex-From", "X26ABC1"); + headers.Add("Mex-To", "X26ABC1"); + headers.Add("Mex-Workflowid", "API-DOCS-TEST"); + headers.Add("User-Agent", "HTTPie"); + } + ); - // var count = await sql.ExecuteScalarAsync("SELECT COUNT(*) FROM SomeTable"); - // Assert.IsTrue(count > 0, "Expected at least one row in SomeTable."); + await Task.Delay(5000); + + Teardown(); } private void RunCommand(string command) @@ -65,24 +107,38 @@ private void RunCommand(string command) throw new Exception($"Command failed: {command}\n{process.StandardError.ReadToEnd()}"); } } +} + - private async Task WaitForSqlServerAsync(int timeoutSeconds = 60) + +public static class HttpHelper +{ + private static readonly HttpClient _client = new HttpClient(); + + public static async Task SendHttpRequestAsync( + HttpMethod method, + string url, + HttpContent? content = null, + Action? configureHeaders = null) { - var start = DateTime.UtcNow; - while ((DateTime.UtcNow - start).TotalSeconds < timeoutSeconds) + var request = new HttpRequestMessage(method, url) { - try - { - using var sql = new SqlConnection(ConnectionString); - await sql.OpenAsync(); - return; // Success - } - catch - { - await Task.Delay(1000); - } - } + Content = content + }; + + // Customize headers if provided + configureHeaders?.Invoke(request.Headers); - throw new TimeoutException("SQL Server did not become available in time."); + try + { + var response = await _client.SendAsync(request); + response.EnsureSuccessStatusCode(); // Throw if not a success status + return response; + } + catch (HttpRequestException ex) + { + Console.WriteLine($"HTTP Request failed: {ex.Message}"); + throw; + } } } diff --git a/tests/ServiceLayer.Mesh.Tests/ServiceLayer.Mesh.Tests.csproj b/tests/ServiceLayer.Mesh.Tests/ServiceLayer.Mesh.Tests.csproj index 12c8eaf..92f4669 100644 --- a/tests/ServiceLayer.Mesh.Tests/ServiceLayer.Mesh.Tests.csproj +++ b/tests/ServiceLayer.Mesh.Tests/ServiceLayer.Mesh.Tests.csproj @@ -18,6 +18,7 @@ + @@ -25,7 +26,7 @@ - + PreserveNewest diff --git a/tests/ServiceLayer.Mesh.Tests/TestData/KMK_20250212095121_APPT_87.dat b/tests/ServiceLayer.Mesh.Tests/TestData/KMK_20250212095121_APPT_87.dat new file mode 100644 index 0000000..0b1adc7 --- /dev/null +++ b/tests/ServiceLayer.Mesh.Tests/TestData/KMK_20250212095121_APPT_87.dat @@ -0,0 +1,8 @@ +"NBSSAPPT_HDR"|"00000087"|"20250212"|"095121"|"000005" +"NBSSAPPT_FLDS"|"Sequence"|"BSO"|"Action"|"Clinic Code"|"Holding Clinic"|"Status"|"Attended Not Scr"|"Appointment ID"|"NHS Num"|"Epsiode Type"|"Episode Start"|"BatchID"|"Screen or Asses"|"Screen Appt num"|"Booked By"|"Cancelled By"|"Appt Date"|"Appt Time"|"Location"|"Clinic Name"|"Clinic Name (Let)"|"Clinic Address 1"|"Clinic Address 2"|"Clinic Address 3"|"Clinic Address 4"|"Clinic Address 5"|"Postcode"|"Action Timestamp" +"NBSSAPPT_DATA"|"000001"|"KMK"|"U"|"BU011"|"N"|"D"|""|"BU011-67246-RA1-DN-T1316-1"|"9619663241"|"G"|"2025-02-10"|"KMKG00581"|"S"|"1"|"H"|""|"20250210"|"1316"|"BU"|"BREAST CARE UNIT"|"BREAST CARE UNIT"|"BREAST CARE UNIT"|"MILTON KEYNES HOSPITAL"|"STANDING WAY"|"MILTON KEYNES"|"MK6 5LD"|"MK6 5LD"|"20250212-094011" +"NBSSAPPT_DATA"|"000002"|"KMK"|"U"|"BU011"|"N"|"D"|""|"BU011-67246-RA1-DN-T1345-1"|"9900798635"|"G"|"2025-02-10"|"KMKG00581"|"S"|"1"|"H"|""|"20250210"|"1345"|"BU"|"BREAST CARE UNIT"|"BREAST CARE UNIT"|"BREAST CARE UNIT"|"MILTON KEYNES HOSPITAL"|"STANDING WAY"|"MILTON KEYNES"|"MK6 5LD"|"MK6 5LD"|"20250212-094153" +"NBSSAPPT_DATA"|"000003"|"KMK"|"U"|"BU011"|"N"|"D"|""|"BU011-67246-RA1-DN-T1400-1"|"9612996474"|"G"|"2025-02-10"|"KMKG00581"|"S"|"1"|"H"|""|"20250210"|"1400"|"BU"|"BREAST CARE UNIT"|"BREAST CARE UNIT"|"BREAST CARE UNIT"|"MILTON KEYNES HOSPITAL"|"STANDING WAY"|"MILTON KEYNES"|"MK6 5LD"|"MK6 5LD"|"20250212-094408" +"NBSSAPPT_DATA"|"000004"|"KMK"|"U"|"BU011"|"N"|"D"|""|"BU011-67246-RA1-DN-T1416-1"|"9630806428"|"F"|"2025-01-31"|"KMK001329"|"S"|"1"|"H"|""|"20250210"|"1416"|"BU"|"BREAST CARE UNIT"|"BREAST CARE UNIT"|"BREAST CARE UNIT"|"MILTON KEYNES HOSPITAL"|"STANDING WAY"|"MILTON KEYNES"|"MK6 5LD"|"MK6 5LD"|"20250212-094418" +"NBSSAPPT_DATA"|"000005"|"KMK"|"B"|"DU101"|"Y"|"B"|""|"DU101-67248-RA1-DN-T0930-1"|"9900798961"|"G"|"2025-02-12"|"KMKG00581"|"S"|"1"|"H"|""|"20250212"|"0930"|"DU"|"DUMMY CLINIC"|"HOLDING CLINIC"|"SO USE ONLY, COVID 19"|""|""|""|""|""|"20250212-095013" +"NBSSAPPT_END"|"00000087"|"20250212"|"095122"|"000005" From 4a7213eeab6661b01125b88975c733f2b546ef4f Mon Sep 17 00:00:00 2001 From: alex-clayton-1 Date: Mon, 2 Jun 2025 18:38:29 +0100 Subject: [PATCH 03/18] test: Integration test WIP --- .../Functions/HealthCheck.cs | 14 -- .../Functions/HealthCheckFunction.cs | 14 ++ .../{Functions => }/IntegrationTests.cs | 136 +++++++++--------- 3 files changed, 79 insertions(+), 85 deletions(-) delete mode 100644 src/ServiceLayer.Mesh/Functions/HealthCheck.cs create mode 100644 src/ServiceLayer.Mesh/Functions/HealthCheckFunction.cs rename tests/ServiceLayer.Mesh.Tests/{Functions => }/IntegrationTests.cs (58%) diff --git a/src/ServiceLayer.Mesh/Functions/HealthCheck.cs b/src/ServiceLayer.Mesh/Functions/HealthCheck.cs deleted file mode 100644 index 3d9c384..0000000 --- a/src/ServiceLayer.Mesh/Functions/HealthCheck.cs +++ /dev/null @@ -1,14 +0,0 @@ -using Microsoft.Azure.Functions.Worker; -using Microsoft.Azure.Functions.Worker.Http; -using Microsoft.Extensions.Logging; -using System.Net; - -public class HealthCheckFunction -{ - [Function("HealthCheck")] - public async Task Run([HttpTrigger(AuthorizationLevel.Anonymous, "get", Route = "health")] HttpRequestData req) - { - var response = req.CreateResponse(HttpStatusCode.OK); - return response; - } -} diff --git a/src/ServiceLayer.Mesh/Functions/HealthCheckFunction.cs b/src/ServiceLayer.Mesh/Functions/HealthCheckFunction.cs new file mode 100644 index 0000000..f8beb31 --- /dev/null +++ b/src/ServiceLayer.Mesh/Functions/HealthCheckFunction.cs @@ -0,0 +1,14 @@ +using Microsoft.Azure.Functions.Worker; +using Microsoft.Azure.Functions.Worker.Http; +using System.Net; + +namespace ServiceLayer.Mesh.Functions; + +public class HealthCheckFunction +{ + [Function("HealthCheck")] + public static HttpResponseData Run([HttpTrigger(AuthorizationLevel.Anonymous, "get", Route = "health")] HttpRequestData req) + { + return req.CreateResponse(HttpStatusCode.OK); + } +} diff --git a/tests/ServiceLayer.Mesh.Tests/Functions/IntegrationTests.cs b/tests/ServiceLayer.Mesh.Tests/IntegrationTests.cs similarity index 58% rename from tests/ServiceLayer.Mesh.Tests/Functions/IntegrationTests.cs rename to tests/ServiceLayer.Mesh.Tests/IntegrationTests.cs index 1cfdeb8..24c1ab1 100644 --- a/tests/ServiceLayer.Mesh.Tests/Functions/IntegrationTests.cs +++ b/tests/ServiceLayer.Mesh.Tests/IntegrationTests.cs @@ -1,49 +1,25 @@ -using System; using System.Diagnostics; -using System.IO; -using System.Threading.Tasks; -using Microsoft.Data.SqlClient; -using Moq; - -using System; -using System.Net.Http; +using System.Net; using System.Net.Http.Headers; -using System.Threading.Tasks; -using ServiceLayer.Data; -namespace ServiceLayer.Mesh.Tests.Integration; +namespace ServiceLayer.Mesh.Tests; -public class IntegrationTests +[CollectionDefinition("DockerComposeCollection")] +public class DockerComposeCollection : ICollectionFixture { - private const string ConnectionString = "Server=localhost,1433;User Id=sa;Password=YourPassword123;TrustServerCertificate=True;"; - - public IntegrationTests() - { - - } +} - private async Task SetupEnvironment() +[Collection("DockerComposeCollection")] +public class IntegrationTests +{ + private static async Task WaitForHealthyService() { - var environment = "development"; - if (environment == null) - { - throw new InvalidOperationException("ASPNETCORE_ENVIRONMENT environment variable is not set of is empty."); - } - if (environment == "development") - { - RunCommand("podman compose up -d"); - } - if (environment == "production") - { - RunCommand("docker compose up -d"); - } - bool environmentIsUp = false; while (environmentIsUp == false) { - var responce = await HttpHelper.SendHttpRequestAsync(HttpMethod.Get, "http://localhost:7072/api/health"); - if (responce.IsSuccessStatusCode) + var response = await HttpHelper.SendHttpRequestAsync(HttpMethod.Get, "http://localhost:7072/api/health"); + if (response.IsSuccessStatusCode) { environmentIsUp = true; } @@ -54,18 +30,20 @@ private async Task SetupEnvironment() } } - public void Teardown() - { - // Stop containers - RunCommand("docker compose down"); - } - [Fact] public async Task EndToEndTest() { - await SetupEnvironment(); + // Arrange + await WaitForHealthyService(); + + await SendFileToMeshInbox("KMK_20250212095121_APPT_87.dat"); + + await Task.Delay(5000); + } - byte[] binaryData = await File.ReadAllBytesAsync("TestData/KMK_20250212095121_APPT_87.dat"); + private static async Task SendFileToMeshInbox(string fileName) + { + byte[] binaryData = await File.ReadAllBytesAsync($"TestData/{fileName}"); var content = new ByteArrayContent(binaryData); content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream"); @@ -76,41 +54,15 @@ public async Task EndToEndTest() headers => { headers.Add("Authorization", "NHSMESH X26ABC1:a42f77b9-58de-4b45-b599-2d5bf320b44d:0:202407291437:e3005627136e01706efabcfe72269bc8da3192e90a840ab344ab7f82a39bb5c6"); - headers.Add("Mex-Filename", "KMK_20250212095121_APPT_87.dat"); + headers.Add("Mex-Filename", fileName); headers.Add("Mex-From", "X26ABC1"); headers.Add("Mex-To", "X26ABC1"); headers.Add("Mex-Workflowid", "API-DOCS-TEST"); - headers.Add("User-Agent", "HTTPie"); } ); - - await Task.Delay(5000); - - Teardown(); - } - - private void RunCommand(string command) - { - var psi = new ProcessStartInfo("cmd", $"/c {command}") - { - RedirectStandardOutput = true, - RedirectStandardError = true, - UseShellExecute = false, - CreateNoWindow = true - }; - - using var process = Process.Start(psi); - process.WaitForExit(); - - if (process.ExitCode != 0) - { - throw new Exception($"Command failed: {command}\n{process.StandardError.ReadToEnd()}"); - } } } - - public static class HttpHelper { private static readonly HttpClient _client = new HttpClient(); @@ -138,7 +90,49 @@ public static async Task SendHttpRequestAsync( catch (HttpRequestException ex) { Console.WriteLine($"HTTP Request failed: {ex.Message}"); - throw; + return new HttpResponseMessage(HttpStatusCode.ServiceUnavailable); + } + } +} + +public class DockerComposeFixture : IAsyncLifetime +{ + public async Task InitializeAsync() + { + // Start Docker Compose + var startInfo = new ProcessStartInfo + { + FileName = "docker", + Arguments = "compose up -d mesh-ingest azurite db db-migrations", + RedirectStandardOutput = true, + RedirectStandardError = true, + UseShellExecute = false, + CreateNoWindow = true + }; + + using var process = Process.Start(startInfo); + await process.WaitForExitAsync(); + + if (process.ExitCode != 0) + { + throw new Exception($"docker compose up failed, error: {process.StandardError.ReadToEnd()}"); } } + + public async Task DisposeAsync() + { + // Stop Docker Compose + var stopInfo = new ProcessStartInfo + { + FileName = "docker", + Arguments = "compose down", + RedirectStandardOutput = true, + RedirectStandardError = true, + UseShellExecute = false, + CreateNoWindow = true + }; + + using var process = Process.Start(stopInfo); + await process.WaitForExitAsync(); + } } From beec96e957af3546efcd26bafcc9d4eb6d4c9467 Mon Sep 17 00:00:00 2001 From: alex-clayton-1 Date: Tue, 3 Jun 2025 16:27:50 +0100 Subject: [PATCH 04/18] test: Included mesh sandbox in integration test setup --- compose.yaml | 36 ++++++++- .../IntegrationTests.cs | 80 ++++++++++++++----- 2 files changed, 92 insertions(+), 24 deletions(-) diff --git a/compose.yaml b/compose.yaml index ae785a8..34a638b 100644 --- a/compose.yaml +++ b/compose.yaml @@ -48,7 +48,7 @@ services: FileExtractQueueName: "${FileExtractQueueName}" FileTransformQueueName: "${FileTransformQueueName}" StaleHours: "${StaleHours}" - MeshApiBaseUrl: "http://mesh_sandbox:80/messageexchange" + MeshApiBaseUrl: "http://mesh-sandbox/messageexchange" NbssMailboxId: "${NbssMailboxId}" MeshPassword: "${MeshPassword}" MeshSharedKey: "${MeshSharedKey}" @@ -70,6 +70,8 @@ services: condition: service_healthy db: condition: service_healthy + mesh-sandbox: + condition: service_started networks: - backend @@ -103,10 +105,14 @@ services: ports: - "1433:1433" user: "root" - volumes: - - db-data:/var/opt/mssql + # volumes: + # - db-data:/var/opt/mssql healthcheck: - test: ["CMD-SHELL", "pgrep -f sqlservr || exit 1"] + test: + [ + "CMD-SHELL", + "grep -q 'SQL Server is now ready for client connections' /var/opt/mssql/log/errorlog || exit 1", + ] interval: 20s timeout: 10s retries: 6 @@ -131,6 +137,28 @@ services: networks: - backend + + mesh-sandbox: + container_name: mesh-sandbox + build: ../mesh-sandbox/ + ports: + - "8700:80" + deploy: + restart_policy: + condition: on-failure + max_attempts: 3 + environment: + - SHARED_KEY=TestKey + - SSL=no + volumes: + # mount a different mailboxes.jsonl to pre created mailboxes + - ../mesh-sandbox/src/mesh_sandbox/store/data/mailboxes.jsonl:/app/mesh_sandbox/store/data/mailboxes.jsonl:ro + - ../mesh-sandbox/src/mesh_sandbox/test_plugin:/app/mesh_sandbox/plugins:ro + # you can mount a directory if you want access the stored messages + - ../mesh-sandbox/messages:/tmp/mesh_store + networks: + - backend + networks: backend: name: backend-network diff --git a/tests/ServiceLayer.Mesh.Tests/IntegrationTests.cs b/tests/ServiceLayer.Mesh.Tests/IntegrationTests.cs index 24c1ab1..150b8f7 100644 --- a/tests/ServiceLayer.Mesh.Tests/IntegrationTests.cs +++ b/tests/ServiceLayer.Mesh.Tests/IntegrationTests.cs @@ -1,6 +1,10 @@ using System.Diagnostics; using System.Net; using System.Net.Http.Headers; +using System.Text.Json; +using System.Text.Json.Serialization; +using Azure.Storage.Blobs; +using Azure.Storage.Blobs.Models; namespace ServiceLayer.Mesh.Tests; @@ -12,16 +16,32 @@ public class DockerComposeCollection : ICollectionFixture [Collection("DockerComposeCollection")] public class IntegrationTests { + [Fact] + public async Task EndToEndTest() + { + // Arrange + await WaitForHealthyService(); + + // Act + var fileId = await SendFileToMeshInbox("KMK_20250212095121_APPT_87.dat"); + + // Wait to allow functions to process file + await Task.Delay(10000); + + // Assert + Assert.True(await WasFileUploadedToBlobContainer(fileId)); + } + private static async Task WaitForHealthyService() { - bool environmentIsUp = false; + bool isServiceHealthy = false; - while (environmentIsUp == false) + while (isServiceHealthy == false) { var response = await HttpHelper.SendHttpRequestAsync(HttpMethod.Get, "http://localhost:7072/api/health"); if (response.IsSuccessStatusCode) { - environmentIsUp = true; + isServiceHealthy = true; } else { @@ -30,18 +50,7 @@ private static async Task WaitForHealthyService() } } - [Fact] - public async Task EndToEndTest() - { - // Arrange - await WaitForHealthyService(); - - await SendFileToMeshInbox("KMK_20250212095121_APPT_87.dat"); - - await Task.Delay(5000); - } - - private static async Task SendFileToMeshInbox(string fileName) + private static async Task SendFileToMeshInbox(string fileName) { byte[] binaryData = await File.ReadAllBytesAsync($"TestData/{fileName}"); var content = new ByteArrayContent(binaryData); @@ -60,12 +69,44 @@ private static async Task SendFileToMeshInbox(string fileName) headers.Add("Mex-Workflowid", "API-DOCS-TEST"); } ); + + string responseBody = await response.Content.ReadAsStringAsync(); + + var responseObject = JsonSerializer.Deserialize(responseBody); + + return responseObject.MessageID; + } + + private static async Task WasFileUploadedToBlobContainer(string fileId) + { + var blobConnectionString = ""; + + var containerClient = new BlobContainerClient(blobConnectionString, "incoming-mesh-files"); + + try + { + var blobClient = containerClient.GetBlobClient($"NbssAppointmentEvents/{fileId}"); + + BlobProperties properties = await blobClient.GetPropertiesAsync(); + return true; // If we get properties, the blob exists + } + catch (Exception ex) + { + Console.WriteLine($"An error occurred: {ex.Message}"); + return false; + } + } + + public class MeshResponse + { + [JsonPropertyName("messageID")] + public required string MessageID { get; set; } } } public static class HttpHelper { - private static readonly HttpClient _client = new HttpClient(); + private static readonly HttpClient _client = new(); public static async Task SendHttpRequestAsync( HttpMethod method, @@ -78,19 +119,18 @@ public static async Task SendHttpRequestAsync( Content = content }; - // Customize headers if provided configureHeaders?.Invoke(request.Headers); try { var response = await _client.SendAsync(request); - response.EnsureSuccessStatusCode(); // Throw if not a success status + response.EnsureSuccessStatusCode(); return response; } catch (HttpRequestException ex) { Console.WriteLine($"HTTP Request failed: {ex.Message}"); - return new HttpResponseMessage(HttpStatusCode.ServiceUnavailable); + return new HttpResponseMessage(HttpStatusCode.InternalServerError); } } } @@ -103,7 +143,7 @@ public async Task InitializeAsync() var startInfo = new ProcessStartInfo { FileName = "docker", - Arguments = "compose up -d mesh-ingest azurite db db-migrations", + Arguments = "compose up -d mesh-ingest mesh-sandbox azurite db db-migrations", RedirectStandardOutput = true, RedirectStandardError = true, UseShellExecute = false, From dfe3785d21f84a383c7b5dbcd64fc47af1a8d715 Mon Sep 17 00:00:00 2001 From: alex-clayton-1 Date: Mon, 9 Jun 2025 18:24:59 +0100 Subject: [PATCH 05/18] test: Updated Integration test to also check that mesh file was inserted into db --- .../IntegrationTests.cs | 49 ++++++++++++++++--- 1 file changed, 42 insertions(+), 7 deletions(-) diff --git a/tests/ServiceLayer.Mesh.Tests/IntegrationTests.cs b/tests/ServiceLayer.Mesh.Tests/IntegrationTests.cs index 150b8f7..91dab70 100644 --- a/tests/ServiceLayer.Mesh.Tests/IntegrationTests.cs +++ b/tests/ServiceLayer.Mesh.Tests/IntegrationTests.cs @@ -5,6 +5,8 @@ using System.Text.Json.Serialization; using Azure.Storage.Blobs; using Azure.Storage.Blobs.Models; +using Microsoft.EntityFrameworkCore; +using ServiceLayer.Data; namespace ServiceLayer.Mesh.Tests; @@ -17,7 +19,7 @@ public class DockerComposeCollection : ICollectionFixture public class IntegrationTests { [Fact] - public async Task EndToEndTest() + public async Task FileUploadedToMesh_FileIsUploadedToBlobContainerAndInsertedIntoDb() { // Arrange await WaitForHealthyService(); @@ -25,11 +27,13 @@ public async Task EndToEndTest() // Act var fileId = await SendFileToMeshInbox("KMK_20250212095121_APPT_87.dat"); - // Wait to allow functions to process file - await Task.Delay(10000); + // Wait to allow functions to ingest the file. The CRON timer trigger for the FileDiscovery function must be considered. + await Task.Delay(45000); // Assert + Assert.NotNull(fileId); Assert.True(await WasFileUploadedToBlobContainer(fileId)); + Assert.True(await WasFileInsertedIntoDatabase(fileId)); } private static async Task WaitForHealthyService() @@ -45,12 +49,14 @@ private static async Task WaitForHealthyService() } else { - await Task.Delay(1000); + await Task.Delay(5000); } } + + Console.WriteLine("Mesh Ingest Service is healthy and ready to start ingesting files"); } - private static async Task SendFileToMeshInbox(string fileName) + private static async Task SendFileToMeshInbox(string fileName) { byte[] binaryData = await File.ReadAllBytesAsync($"TestData/{fileName}"); var content = new ByteArrayContent(binaryData); @@ -74,7 +80,7 @@ private static async Task SendFileToMeshInbox(string fileName) var responseObject = JsonSerializer.Deserialize(responseBody); - return responseObject.MessageID; + return responseObject?.MessageID; } private static async Task WasFileUploadedToBlobContainer(string fileId) @@ -97,6 +103,18 @@ private static async Task WasFileUploadedToBlobContainer(string fileId) } } + private static async Task WasFileInsertedIntoDatabase(string fileId) + { + var connectionString = ""; + var options = new DbContextOptionsBuilder() + .UseSqlServer(connectionString) + .Options; + + var context = new ServiceLayerDbContext(options); + + return await context.MeshFiles.AnyAsync(x => x.FileId == fileId); + } + public class MeshResponse { [JsonPropertyName("messageID")] @@ -151,11 +169,17 @@ public async Task InitializeAsync() }; using var process = Process.Start(startInfo); + + if (process == null) + { + throw new Exception("Failed to start the Docker process."); + } + await process.WaitForExitAsync(); if (process.ExitCode != 0) { - throw new Exception($"docker compose up failed, error: {process.StandardError.ReadToEnd()}"); + throw new Exception($"Docker process started but failed, error: {process.StandardError.ReadToEnd()}"); } } @@ -173,6 +197,17 @@ public async Task DisposeAsync() }; using var process = Process.Start(stopInfo); + + if (process == null) + { + throw new Exception("Failed to start the Docker process."); + } + await process.WaitForExitAsync(); + + if (process.ExitCode != 0) + { + throw new Exception($"Docker process started but failed, error: {process.StandardError.ReadToEnd()}"); + } } } From ca26436703e44cc4f312a96c8324fca89f6bd5b2 Mon Sep 17 00:00:00 2001 From: alex-clayton-1 Date: Tue, 10 Jun 2025 10:52:37 +0100 Subject: [PATCH 06/18] test: Moved integration tests into separate project --- src/ServiceLayer.sln | 251 ++++++++++-------- .../IntegrationTests.cs | 60 ++--- .../ServiceLayer.IntegrationTests.csproj | 34 +++ .../TestData/KMK_20250212095121_APPT_87.dat | 0 .../ServiceLayer.TestUtilities/HttpHelper.cs | 34 +++ 5 files changed, 217 insertions(+), 162 deletions(-) rename tests/{ServiceLayer.Mesh.Tests => ServiceLayer.IntegrationTests}/IntegrationTests.cs (78%) create mode 100644 tests/ServiceLayer.IntegrationTests/ServiceLayer.IntegrationTests.csproj rename tests/{ServiceLayer.Mesh.Tests => ServiceLayer.IntegrationTests}/TestData/KMK_20250212095121_APPT_87.dat (100%) create mode 100644 tests/ServiceLayer.TestUtilities/HttpHelper.cs diff --git a/src/ServiceLayer.sln b/src/ServiceLayer.sln index 14cb8a0..daca54b 100644 --- a/src/ServiceLayer.sln +++ b/src/ServiceLayer.sln @@ -21,123 +21,138 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ServiceLayer.Common.Tests", EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ServiceLayer.TestUtilities", "..\tests\ServiceLayer.TestUtilities\ServiceLayer.TestUtilities.csproj", "{43AE0301-63CA-4254-9580-4FB07C9D1920}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ServiceLayer.IntegrationTests", "..\tests\ServiceLayer.IntegrationTests\ServiceLayer.IntegrationTests.csproj", "{3C40C165-1D22-4E9B-80A8-059B321B7639}" +EndProject Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Any CPU = Debug|Any CPU - Debug|x64 = Debug|x64 - Debug|x86 = Debug|x86 - Release|Any CPU = Release|Any CPU - Release|x64 = Release|x64 - Release|x86 = Release|x86 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {B56B41FF-FA39-0FDE-E266-6EC09B268DFB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {B56B41FF-FA39-0FDE-E266-6EC09B268DFB}.Debug|Any CPU.Build.0 = Debug|Any CPU - {B56B41FF-FA39-0FDE-E266-6EC09B268DFB}.Debug|x64.ActiveCfg = Debug|Any CPU - {B56B41FF-FA39-0FDE-E266-6EC09B268DFB}.Debug|x64.Build.0 = Debug|Any CPU - {B56B41FF-FA39-0FDE-E266-6EC09B268DFB}.Debug|x86.ActiveCfg = Debug|Any CPU - {B56B41FF-FA39-0FDE-E266-6EC09B268DFB}.Debug|x86.Build.0 = Debug|Any CPU - {B56B41FF-FA39-0FDE-E266-6EC09B268DFB}.Release|Any CPU.ActiveCfg = Release|Any CPU - {B56B41FF-FA39-0FDE-E266-6EC09B268DFB}.Release|Any CPU.Build.0 = Release|Any CPU - {B56B41FF-FA39-0FDE-E266-6EC09B268DFB}.Release|x64.ActiveCfg = Release|Any CPU - {B56B41FF-FA39-0FDE-E266-6EC09B268DFB}.Release|x64.Build.0 = Release|Any CPU - {B56B41FF-FA39-0FDE-E266-6EC09B268DFB}.Release|x86.ActiveCfg = Release|Any CPU - {B56B41FF-FA39-0FDE-E266-6EC09B268DFB}.Release|x86.Build.0 = Release|Any CPU - {BA052DAE-6FD1-483A-A0AF-DCBCF9E38C72}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {BA052DAE-6FD1-483A-A0AF-DCBCF9E38C72}.Debug|Any CPU.Build.0 = Debug|Any CPU - {BA052DAE-6FD1-483A-A0AF-DCBCF9E38C72}.Debug|x64.ActiveCfg = Debug|Any CPU - {BA052DAE-6FD1-483A-A0AF-DCBCF9E38C72}.Debug|x64.Build.0 = Debug|Any CPU - {BA052DAE-6FD1-483A-A0AF-DCBCF9E38C72}.Debug|x86.ActiveCfg = Debug|Any CPU - {BA052DAE-6FD1-483A-A0AF-DCBCF9E38C72}.Debug|x86.Build.0 = Debug|Any CPU - {BA052DAE-6FD1-483A-A0AF-DCBCF9E38C72}.Release|Any CPU.ActiveCfg = Release|Any CPU - {BA052DAE-6FD1-483A-A0AF-DCBCF9E38C72}.Release|Any CPU.Build.0 = Release|Any CPU - {BA052DAE-6FD1-483A-A0AF-DCBCF9E38C72}.Release|x64.ActiveCfg = Release|Any CPU - {BA052DAE-6FD1-483A-A0AF-DCBCF9E38C72}.Release|x64.Build.0 = Release|Any CPU - {BA052DAE-6FD1-483A-A0AF-DCBCF9E38C72}.Release|x86.ActiveCfg = Release|Any CPU - {BA052DAE-6FD1-483A-A0AF-DCBCF9E38C72}.Release|x86.Build.0 = Release|Any CPU - {803E8A5E-A180-4799-8BE2-DD5BD3C34ED2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {803E8A5E-A180-4799-8BE2-DD5BD3C34ED2}.Debug|Any CPU.Build.0 = Debug|Any CPU - {803E8A5E-A180-4799-8BE2-DD5BD3C34ED2}.Debug|x64.ActiveCfg = Debug|Any CPU - {803E8A5E-A180-4799-8BE2-DD5BD3C34ED2}.Debug|x64.Build.0 = Debug|Any CPU - {803E8A5E-A180-4799-8BE2-DD5BD3C34ED2}.Debug|x86.ActiveCfg = Debug|Any CPU - {803E8A5E-A180-4799-8BE2-DD5BD3C34ED2}.Debug|x86.Build.0 = Debug|Any CPU - {803E8A5E-A180-4799-8BE2-DD5BD3C34ED2}.Release|Any CPU.ActiveCfg = Release|Any CPU - {803E8A5E-A180-4799-8BE2-DD5BD3C34ED2}.Release|Any CPU.Build.0 = Release|Any CPU - {803E8A5E-A180-4799-8BE2-DD5BD3C34ED2}.Release|x64.ActiveCfg = Release|Any CPU - {803E8A5E-A180-4799-8BE2-DD5BD3C34ED2}.Release|x64.Build.0 = Release|Any CPU - {803E8A5E-A180-4799-8BE2-DD5BD3C34ED2}.Release|x86.ActiveCfg = Release|Any CPU - {803E8A5E-A180-4799-8BE2-DD5BD3C34ED2}.Release|x86.Build.0 = Release|Any CPU - {E5EF5B92-52DA-4EF3-956B-8AEE3D333428}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {E5EF5B92-52DA-4EF3-956B-8AEE3D333428}.Debug|Any CPU.Build.0 = Debug|Any CPU - {E5EF5B92-52DA-4EF3-956B-8AEE3D333428}.Debug|x64.ActiveCfg = Debug|Any CPU - {E5EF5B92-52DA-4EF3-956B-8AEE3D333428}.Debug|x64.Build.0 = Debug|Any CPU - {E5EF5B92-52DA-4EF3-956B-8AEE3D333428}.Debug|x86.ActiveCfg = Debug|Any CPU - {E5EF5B92-52DA-4EF3-956B-8AEE3D333428}.Debug|x86.Build.0 = Debug|Any CPU - {E5EF5B92-52DA-4EF3-956B-8AEE3D333428}.Release|Any CPU.ActiveCfg = Release|Any CPU - {E5EF5B92-52DA-4EF3-956B-8AEE3D333428}.Release|Any CPU.Build.0 = Release|Any CPU - {E5EF5B92-52DA-4EF3-956B-8AEE3D333428}.Release|x64.ActiveCfg = Release|Any CPU - {E5EF5B92-52DA-4EF3-956B-8AEE3D333428}.Release|x64.Build.0 = Release|Any CPU - {E5EF5B92-52DA-4EF3-956B-8AEE3D333428}.Release|x86.ActiveCfg = Release|Any CPU - {E5EF5B92-52DA-4EF3-956B-8AEE3D333428}.Release|x86.Build.0 = Release|Any CPU - {F373FEBA-AD0B-4E0B-BEE3-31D22C7AD43D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {F373FEBA-AD0B-4E0B-BEE3-31D22C7AD43D}.Debug|Any CPU.Build.0 = Debug|Any CPU - {F373FEBA-AD0B-4E0B-BEE3-31D22C7AD43D}.Debug|x64.ActiveCfg = Debug|Any CPU - {F373FEBA-AD0B-4E0B-BEE3-31D22C7AD43D}.Debug|x64.Build.0 = Debug|Any CPU - {F373FEBA-AD0B-4E0B-BEE3-31D22C7AD43D}.Debug|x86.ActiveCfg = Debug|Any CPU - {F373FEBA-AD0B-4E0B-BEE3-31D22C7AD43D}.Debug|x86.Build.0 = Debug|Any CPU - {F373FEBA-AD0B-4E0B-BEE3-31D22C7AD43D}.Release|Any CPU.ActiveCfg = Release|Any CPU - {F373FEBA-AD0B-4E0B-BEE3-31D22C7AD43D}.Release|Any CPU.Build.0 = Release|Any CPU - {F373FEBA-AD0B-4E0B-BEE3-31D22C7AD43D}.Release|x64.ActiveCfg = Release|Any CPU - {F373FEBA-AD0B-4E0B-BEE3-31D22C7AD43D}.Release|x64.Build.0 = Release|Any CPU - {F373FEBA-AD0B-4E0B-BEE3-31D22C7AD43D}.Release|x86.ActiveCfg = Release|Any CPU - {F373FEBA-AD0B-4E0B-BEE3-31D22C7AD43D}.Release|x86.Build.0 = Release|Any CPU - {B086BBF9-1A41-48C9-B019-F9C75CA634AF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {B086BBF9-1A41-48C9-B019-F9C75CA634AF}.Debug|Any CPU.Build.0 = Debug|Any CPU - {B086BBF9-1A41-48C9-B019-F9C75CA634AF}.Debug|x64.ActiveCfg = Debug|Any CPU - {B086BBF9-1A41-48C9-B019-F9C75CA634AF}.Debug|x64.Build.0 = Debug|Any CPU - {B086BBF9-1A41-48C9-B019-F9C75CA634AF}.Debug|x86.ActiveCfg = Debug|Any CPU - {B086BBF9-1A41-48C9-B019-F9C75CA634AF}.Debug|x86.Build.0 = Debug|Any CPU - {B086BBF9-1A41-48C9-B019-F9C75CA634AF}.Release|Any CPU.ActiveCfg = Release|Any CPU - {B086BBF9-1A41-48C9-B019-F9C75CA634AF}.Release|Any CPU.Build.0 = Release|Any CPU - {B086BBF9-1A41-48C9-B019-F9C75CA634AF}.Release|x64.ActiveCfg = Release|Any CPU - {B086BBF9-1A41-48C9-B019-F9C75CA634AF}.Release|x64.Build.0 = Release|Any CPU - {B086BBF9-1A41-48C9-B019-F9C75CA634AF}.Release|x86.ActiveCfg = Release|Any CPU - {B086BBF9-1A41-48C9-B019-F9C75CA634AF}.Release|x86.Build.0 = Release|Any CPU - {9642EC3A-9BC3-4557-ACD1-807FE764D5F6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {9642EC3A-9BC3-4557-ACD1-807FE764D5F6}.Debug|Any CPU.Build.0 = Debug|Any CPU - {9642EC3A-9BC3-4557-ACD1-807FE764D5F6}.Debug|x64.ActiveCfg = Debug|Any CPU - {9642EC3A-9BC3-4557-ACD1-807FE764D5F6}.Debug|x64.Build.0 = Debug|Any CPU - {9642EC3A-9BC3-4557-ACD1-807FE764D5F6}.Debug|x86.ActiveCfg = Debug|Any CPU - {9642EC3A-9BC3-4557-ACD1-807FE764D5F6}.Debug|x86.Build.0 = Debug|Any CPU - {9642EC3A-9BC3-4557-ACD1-807FE764D5F6}.Release|Any CPU.ActiveCfg = Release|Any CPU - {9642EC3A-9BC3-4557-ACD1-807FE764D5F6}.Release|Any CPU.Build.0 = Release|Any CPU - {9642EC3A-9BC3-4557-ACD1-807FE764D5F6}.Release|x64.ActiveCfg = Release|Any CPU - {9642EC3A-9BC3-4557-ACD1-807FE764D5F6}.Release|x64.Build.0 = Release|Any CPU - {9642EC3A-9BC3-4557-ACD1-807FE764D5F6}.Release|x86.ActiveCfg = Release|Any CPU - {9642EC3A-9BC3-4557-ACD1-807FE764D5F6}.Release|x86.Build.0 = Release|Any CPU - {43AE0301-63CA-4254-9580-4FB07C9D1920}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {43AE0301-63CA-4254-9580-4FB07C9D1920}.Debug|Any CPU.Build.0 = Debug|Any CPU - {43AE0301-63CA-4254-9580-4FB07C9D1920}.Debug|x64.ActiveCfg = Debug|Any CPU - {43AE0301-63CA-4254-9580-4FB07C9D1920}.Debug|x64.Build.0 = Debug|Any CPU - {43AE0301-63CA-4254-9580-4FB07C9D1920}.Debug|x86.ActiveCfg = Debug|Any CPU - {43AE0301-63CA-4254-9580-4FB07C9D1920}.Debug|x86.Build.0 = Debug|Any CPU - {43AE0301-63CA-4254-9580-4FB07C9D1920}.Release|Any CPU.ActiveCfg = Release|Any CPU - {43AE0301-63CA-4254-9580-4FB07C9D1920}.Release|Any CPU.Build.0 = Release|Any CPU - {43AE0301-63CA-4254-9580-4FB07C9D1920}.Release|x64.ActiveCfg = Release|Any CPU - {43AE0301-63CA-4254-9580-4FB07C9D1920}.Release|x64.Build.0 = Release|Any CPU - {43AE0301-63CA-4254-9580-4FB07C9D1920}.Release|x86.ActiveCfg = Release|Any CPU - {43AE0301-63CA-4254-9580-4FB07C9D1920}.Release|x86.Build.0 = Release|Any CPU - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection - GlobalSection(NestedProjects) = preSolution - {BA052DAE-6FD1-483A-A0AF-DCBCF9E38C72} = {0AB3BF05-4346-4AA6-1389-037BE0695223} - {E5EF5B92-52DA-4EF3-956B-8AEE3D333428} = {0AB3BF05-4346-4AA6-1389-037BE0695223} - {9642EC3A-9BC3-4557-ACD1-807FE764D5F6} = {0AB3BF05-4346-4AA6-1389-037BE0695223} - {43AE0301-63CA-4254-9580-4FB07C9D1920} = {0AB3BF05-4346-4AA6-1389-037BE0695223} - EndGlobalSection - GlobalSection(ExtensibilityGlobals) = postSolution - SolutionGuid = {EEE06B13-019F-4618-A6EB-FD834B6EA7D7} - EndGlobalSection + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|Any CPU = Release|Any CPU + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {B56B41FF-FA39-0FDE-E266-6EC09B268DFB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B56B41FF-FA39-0FDE-E266-6EC09B268DFB}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B56B41FF-FA39-0FDE-E266-6EC09B268DFB}.Debug|x64.ActiveCfg = Debug|Any CPU + {B56B41FF-FA39-0FDE-E266-6EC09B268DFB}.Debug|x64.Build.0 = Debug|Any CPU + {B56B41FF-FA39-0FDE-E266-6EC09B268DFB}.Debug|x86.ActiveCfg = Debug|Any CPU + {B56B41FF-FA39-0FDE-E266-6EC09B268DFB}.Debug|x86.Build.0 = Debug|Any CPU + {B56B41FF-FA39-0FDE-E266-6EC09B268DFB}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B56B41FF-FA39-0FDE-E266-6EC09B268DFB}.Release|Any CPU.Build.0 = Release|Any CPU + {B56B41FF-FA39-0FDE-E266-6EC09B268DFB}.Release|x64.ActiveCfg = Release|Any CPU + {B56B41FF-FA39-0FDE-E266-6EC09B268DFB}.Release|x64.Build.0 = Release|Any CPU + {B56B41FF-FA39-0FDE-E266-6EC09B268DFB}.Release|x86.ActiveCfg = Release|Any CPU + {B56B41FF-FA39-0FDE-E266-6EC09B268DFB}.Release|x86.Build.0 = Release|Any CPU + {BA052DAE-6FD1-483A-A0AF-DCBCF9E38C72}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {BA052DAE-6FD1-483A-A0AF-DCBCF9E38C72}.Debug|Any CPU.Build.0 = Debug|Any CPU + {BA052DAE-6FD1-483A-A0AF-DCBCF9E38C72}.Debug|x64.ActiveCfg = Debug|Any CPU + {BA052DAE-6FD1-483A-A0AF-DCBCF9E38C72}.Debug|x64.Build.0 = Debug|Any CPU + {BA052DAE-6FD1-483A-A0AF-DCBCF9E38C72}.Debug|x86.ActiveCfg = Debug|Any CPU + {BA052DAE-6FD1-483A-A0AF-DCBCF9E38C72}.Debug|x86.Build.0 = Debug|Any CPU + {BA052DAE-6FD1-483A-A0AF-DCBCF9E38C72}.Release|Any CPU.ActiveCfg = Release|Any CPU + {BA052DAE-6FD1-483A-A0AF-DCBCF9E38C72}.Release|Any CPU.Build.0 = Release|Any CPU + {BA052DAE-6FD1-483A-A0AF-DCBCF9E38C72}.Release|x64.ActiveCfg = Release|Any CPU + {BA052DAE-6FD1-483A-A0AF-DCBCF9E38C72}.Release|x64.Build.0 = Release|Any CPU + {BA052DAE-6FD1-483A-A0AF-DCBCF9E38C72}.Release|x86.ActiveCfg = Release|Any CPU + {BA052DAE-6FD1-483A-A0AF-DCBCF9E38C72}.Release|x86.Build.0 = Release|Any CPU + {803E8A5E-A180-4799-8BE2-DD5BD3C34ED2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {803E8A5E-A180-4799-8BE2-DD5BD3C34ED2}.Debug|Any CPU.Build.0 = Debug|Any CPU + {803E8A5E-A180-4799-8BE2-DD5BD3C34ED2}.Debug|x64.ActiveCfg = Debug|Any CPU + {803E8A5E-A180-4799-8BE2-DD5BD3C34ED2}.Debug|x64.Build.0 = Debug|Any CPU + {803E8A5E-A180-4799-8BE2-DD5BD3C34ED2}.Debug|x86.ActiveCfg = Debug|Any CPU + {803E8A5E-A180-4799-8BE2-DD5BD3C34ED2}.Debug|x86.Build.0 = Debug|Any CPU + {803E8A5E-A180-4799-8BE2-DD5BD3C34ED2}.Release|Any CPU.ActiveCfg = Release|Any CPU + {803E8A5E-A180-4799-8BE2-DD5BD3C34ED2}.Release|Any CPU.Build.0 = Release|Any CPU + {803E8A5E-A180-4799-8BE2-DD5BD3C34ED2}.Release|x64.ActiveCfg = Release|Any CPU + {803E8A5E-A180-4799-8BE2-DD5BD3C34ED2}.Release|x64.Build.0 = Release|Any CPU + {803E8A5E-A180-4799-8BE2-DD5BD3C34ED2}.Release|x86.ActiveCfg = Release|Any CPU + {803E8A5E-A180-4799-8BE2-DD5BD3C34ED2}.Release|x86.Build.0 = Release|Any CPU + {E5EF5B92-52DA-4EF3-956B-8AEE3D333428}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {E5EF5B92-52DA-4EF3-956B-8AEE3D333428}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E5EF5B92-52DA-4EF3-956B-8AEE3D333428}.Debug|x64.ActiveCfg = Debug|Any CPU + {E5EF5B92-52DA-4EF3-956B-8AEE3D333428}.Debug|x64.Build.0 = Debug|Any CPU + {E5EF5B92-52DA-4EF3-956B-8AEE3D333428}.Debug|x86.ActiveCfg = Debug|Any CPU + {E5EF5B92-52DA-4EF3-956B-8AEE3D333428}.Debug|x86.Build.0 = Debug|Any CPU + {E5EF5B92-52DA-4EF3-956B-8AEE3D333428}.Release|Any CPU.ActiveCfg = Release|Any CPU + {E5EF5B92-52DA-4EF3-956B-8AEE3D333428}.Release|Any CPU.Build.0 = Release|Any CPU + {E5EF5B92-52DA-4EF3-956B-8AEE3D333428}.Release|x64.ActiveCfg = Release|Any CPU + {E5EF5B92-52DA-4EF3-956B-8AEE3D333428}.Release|x64.Build.0 = Release|Any CPU + {E5EF5B92-52DA-4EF3-956B-8AEE3D333428}.Release|x86.ActiveCfg = Release|Any CPU + {E5EF5B92-52DA-4EF3-956B-8AEE3D333428}.Release|x86.Build.0 = Release|Any CPU + {F373FEBA-AD0B-4E0B-BEE3-31D22C7AD43D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {F373FEBA-AD0B-4E0B-BEE3-31D22C7AD43D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F373FEBA-AD0B-4E0B-BEE3-31D22C7AD43D}.Debug|x64.ActiveCfg = Debug|Any CPU + {F373FEBA-AD0B-4E0B-BEE3-31D22C7AD43D}.Debug|x64.Build.0 = Debug|Any CPU + {F373FEBA-AD0B-4E0B-BEE3-31D22C7AD43D}.Debug|x86.ActiveCfg = Debug|Any CPU + {F373FEBA-AD0B-4E0B-BEE3-31D22C7AD43D}.Debug|x86.Build.0 = Debug|Any CPU + {F373FEBA-AD0B-4E0B-BEE3-31D22C7AD43D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {F373FEBA-AD0B-4E0B-BEE3-31D22C7AD43D}.Release|Any CPU.Build.0 = Release|Any CPU + {F373FEBA-AD0B-4E0B-BEE3-31D22C7AD43D}.Release|x64.ActiveCfg = Release|Any CPU + {F373FEBA-AD0B-4E0B-BEE3-31D22C7AD43D}.Release|x64.Build.0 = Release|Any CPU + {F373FEBA-AD0B-4E0B-BEE3-31D22C7AD43D}.Release|x86.ActiveCfg = Release|Any CPU + {F373FEBA-AD0B-4E0B-BEE3-31D22C7AD43D}.Release|x86.Build.0 = Release|Any CPU + {B086BBF9-1A41-48C9-B019-F9C75CA634AF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B086BBF9-1A41-48C9-B019-F9C75CA634AF}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B086BBF9-1A41-48C9-B019-F9C75CA634AF}.Debug|x64.ActiveCfg = Debug|Any CPU + {B086BBF9-1A41-48C9-B019-F9C75CA634AF}.Debug|x64.Build.0 = Debug|Any CPU + {B086BBF9-1A41-48C9-B019-F9C75CA634AF}.Debug|x86.ActiveCfg = Debug|Any CPU + {B086BBF9-1A41-48C9-B019-F9C75CA634AF}.Debug|x86.Build.0 = Debug|Any CPU + {B086BBF9-1A41-48C9-B019-F9C75CA634AF}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B086BBF9-1A41-48C9-B019-F9C75CA634AF}.Release|Any CPU.Build.0 = Release|Any CPU + {B086BBF9-1A41-48C9-B019-F9C75CA634AF}.Release|x64.ActiveCfg = Release|Any CPU + {B086BBF9-1A41-48C9-B019-F9C75CA634AF}.Release|x64.Build.0 = Release|Any CPU + {B086BBF9-1A41-48C9-B019-F9C75CA634AF}.Release|x86.ActiveCfg = Release|Any CPU + {B086BBF9-1A41-48C9-B019-F9C75CA634AF}.Release|x86.Build.0 = Release|Any CPU + {9642EC3A-9BC3-4557-ACD1-807FE764D5F6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {9642EC3A-9BC3-4557-ACD1-807FE764D5F6}.Debug|Any CPU.Build.0 = Debug|Any CPU + {9642EC3A-9BC3-4557-ACD1-807FE764D5F6}.Debug|x64.ActiveCfg = Debug|Any CPU + {9642EC3A-9BC3-4557-ACD1-807FE764D5F6}.Debug|x64.Build.0 = Debug|Any CPU + {9642EC3A-9BC3-4557-ACD1-807FE764D5F6}.Debug|x86.ActiveCfg = Debug|Any CPU + {9642EC3A-9BC3-4557-ACD1-807FE764D5F6}.Debug|x86.Build.0 = Debug|Any CPU + {9642EC3A-9BC3-4557-ACD1-807FE764D5F6}.Release|Any CPU.ActiveCfg = Release|Any CPU + {9642EC3A-9BC3-4557-ACD1-807FE764D5F6}.Release|Any CPU.Build.0 = Release|Any CPU + {9642EC3A-9BC3-4557-ACD1-807FE764D5F6}.Release|x64.ActiveCfg = Release|Any CPU + {9642EC3A-9BC3-4557-ACD1-807FE764D5F6}.Release|x64.Build.0 = Release|Any CPU + {9642EC3A-9BC3-4557-ACD1-807FE764D5F6}.Release|x86.ActiveCfg = Release|Any CPU + {9642EC3A-9BC3-4557-ACD1-807FE764D5F6}.Release|x86.Build.0 = Release|Any CPU + {43AE0301-63CA-4254-9580-4FB07C9D1920}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {43AE0301-63CA-4254-9580-4FB07C9D1920}.Debug|Any CPU.Build.0 = Debug|Any CPU + {43AE0301-63CA-4254-9580-4FB07C9D1920}.Debug|x64.ActiveCfg = Debug|Any CPU + {43AE0301-63CA-4254-9580-4FB07C9D1920}.Debug|x64.Build.0 = Debug|Any CPU + {43AE0301-63CA-4254-9580-4FB07C9D1920}.Debug|x86.ActiveCfg = Debug|Any CPU + {43AE0301-63CA-4254-9580-4FB07C9D1920}.Debug|x86.Build.0 = Debug|Any CPU + {43AE0301-63CA-4254-9580-4FB07C9D1920}.Release|Any CPU.ActiveCfg = Release|Any CPU + {43AE0301-63CA-4254-9580-4FB07C9D1920}.Release|Any CPU.Build.0 = Release|Any CPU + {43AE0301-63CA-4254-9580-4FB07C9D1920}.Release|x64.ActiveCfg = Release|Any CPU + {43AE0301-63CA-4254-9580-4FB07C9D1920}.Release|x64.Build.0 = Release|Any CPU + {43AE0301-63CA-4254-9580-4FB07C9D1920}.Release|x86.ActiveCfg = Release|Any CPU + {43AE0301-63CA-4254-9580-4FB07C9D1920}.Release|x86.Build.0 = Release|Any CPU + {3C40C165-1D22-4E9B-80A8-059B321B7639}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {3C40C165-1D22-4E9B-80A8-059B321B7639}.Debug|Any CPU.Build.0 = Debug|Any CPU + {3C40C165-1D22-4E9B-80A8-059B321B7639}.Debug|x64.ActiveCfg = Debug|Any CPU + {3C40C165-1D22-4E9B-80A8-059B321B7639}.Debug|x64.Build.0 = Debug|Any CPU + {3C40C165-1D22-4E9B-80A8-059B321B7639}.Debug|x86.ActiveCfg = Debug|Any CPU + {3C40C165-1D22-4E9B-80A8-059B321B7639}.Debug|x86.Build.0 = Debug|Any CPU + {3C40C165-1D22-4E9B-80A8-059B321B7639}.Release|Any CPU.ActiveCfg = Release|Any CPU + {3C40C165-1D22-4E9B-80A8-059B321B7639}.Release|Any CPU.Build.0 = Release|Any CPU + {3C40C165-1D22-4E9B-80A8-059B321B7639}.Release|x64.ActiveCfg = Release|Any CPU + {3C40C165-1D22-4E9B-80A8-059B321B7639}.Release|x64.Build.0 = Release|Any CPU + {3C40C165-1D22-4E9B-80A8-059B321B7639}.Release|x86.ActiveCfg = Release|Any CPU + {3C40C165-1D22-4E9B-80A8-059B321B7639}.Release|x86.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(NestedProjects) = preSolution + {BA052DAE-6FD1-483A-A0AF-DCBCF9E38C72} = {0AB3BF05-4346-4AA6-1389-037BE0695223} + {E5EF5B92-52DA-4EF3-956B-8AEE3D333428} = {0AB3BF05-4346-4AA6-1389-037BE0695223} + {9642EC3A-9BC3-4557-ACD1-807FE764D5F6} = {0AB3BF05-4346-4AA6-1389-037BE0695223} + {43AE0301-63CA-4254-9580-4FB07C9D1920} = {0AB3BF05-4346-4AA6-1389-037BE0695223} + {3C40C165-1D22-4E9B-80A8-059B321B7639} = {0AB3BF05-4346-4AA6-1389-037BE0695223} + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {EEE06B13-019F-4618-A6EB-FD834B6EA7D7} + EndGlobalSection EndGlobal diff --git a/tests/ServiceLayer.Mesh.Tests/IntegrationTests.cs b/tests/ServiceLayer.IntegrationTests/IntegrationTests.cs similarity index 78% rename from tests/ServiceLayer.Mesh.Tests/IntegrationTests.cs rename to tests/ServiceLayer.IntegrationTests/IntegrationTests.cs index 91dab70..1ebbc24 100644 --- a/tests/ServiceLayer.Mesh.Tests/IntegrationTests.cs +++ b/tests/ServiceLayer.IntegrationTests/IntegrationTests.cs @@ -1,5 +1,4 @@ using System.Diagnostics; -using System.Net; using System.Net.Http.Headers; using System.Text.Json; using System.Text.Json.Serialization; @@ -7,8 +6,9 @@ using Azure.Storage.Blobs.Models; using Microsoft.EntityFrameworkCore; using ServiceLayer.Data; +using ServiceLayer.TestUtilities; -namespace ServiceLayer.Mesh.Tests; +namespace ServiceLayer.IntegrationTests; [CollectionDefinition("DockerComposeCollection")] public class DockerComposeCollection : ICollectionFixture @@ -19,7 +19,7 @@ public class DockerComposeCollection : ICollectionFixture public class IntegrationTests { [Fact] - public async Task FileUploadedToMesh_FileIsUploadedToBlobContainerAndInsertedIntoDb() + public async Task FileSentToMeshInbox_FileIsUploadedToBlobContainerAndInsertedIntoDb() { // Arrange await WaitForHealthyService(); @@ -38,22 +38,25 @@ public async Task FileUploadedToMesh_FileIsUploadedToBlobContainerAndInsertedInt private static async Task WaitForHealthyService() { - bool isServiceHealthy = false; + int attemptCounter = 0; - while (isServiceHealthy == false) + while (attemptCounter < 10) { var response = await HttpHelper.SendHttpRequestAsync(HttpMethod.Get, "http://localhost:7072/api/health"); + if (response.IsSuccessStatusCode) { - isServiceHealthy = true; - } - else - { - await Task.Delay(5000); + Console.WriteLine("Mesh Ingest Service is healthy and ready to start ingesting files."); + return; } + + Console.WriteLine("Mesh Ingest Service is unhealthy"); + attemptCounter++; + await Task.Delay(5000); } - Console.WriteLine("Mesh Ingest Service is healthy and ready to start ingesting files"); + Console.WriteLine("Max attempts reached. Mesh Ingest Service is still unhealthy."); + throw new TimeoutException("Timed out waiting on Mesh Ingest Service health check"); } private static async Task SendFileToMeshInbox(string fileName) @@ -85,7 +88,7 @@ private static async Task WaitForHealthyService() private static async Task WasFileUploadedToBlobContainer(string fileId) { - var blobConnectionString = ""; + var blobConnectionString = "DefaultEndpointsProtocol=http;AccountName=devstoreaccount1;AccountKey=Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw==;BlobEndpoint=http://127.0.0.1:10000/devstoreaccount1"; var containerClient = new BlobContainerClient(blobConnectionString, "incoming-mesh-files"); @@ -105,7 +108,7 @@ private static async Task WasFileUploadedToBlobContainer(string fileId) private static async Task WasFileInsertedIntoDatabase(string fileId) { - var connectionString = ""; + var connectionString = "Server=localhost;Database=ServiceLayer;User Id=SA;Password=YourStrong@Passw0rd;TrustServerCertificate=True"; var options = new DbContextOptionsBuilder() .UseSqlServer(connectionString) .Options; @@ -122,37 +125,6 @@ public class MeshResponse } } -public static class HttpHelper -{ - private static readonly HttpClient _client = new(); - - public static async Task SendHttpRequestAsync( - HttpMethod method, - string url, - HttpContent? content = null, - Action? configureHeaders = null) - { - var request = new HttpRequestMessage(method, url) - { - Content = content - }; - - configureHeaders?.Invoke(request.Headers); - - try - { - var response = await _client.SendAsync(request); - response.EnsureSuccessStatusCode(); - return response; - } - catch (HttpRequestException ex) - { - Console.WriteLine($"HTTP Request failed: {ex.Message}"); - return new HttpResponseMessage(HttpStatusCode.InternalServerError); - } - } -} - public class DockerComposeFixture : IAsyncLifetime { public async Task InitializeAsync() diff --git a/tests/ServiceLayer.IntegrationTests/ServiceLayer.IntegrationTests.csproj b/tests/ServiceLayer.IntegrationTests/ServiceLayer.IntegrationTests.csproj new file mode 100644 index 0000000..92f4669 --- /dev/null +++ b/tests/ServiceLayer.IntegrationTests/ServiceLayer.IntegrationTests.csproj @@ -0,0 +1,34 @@ + + + + net9.0 + enable + enable + false + + + + + + + + + + + + + + + + + + + + + + + PreserveNewest + + + + diff --git a/tests/ServiceLayer.Mesh.Tests/TestData/KMK_20250212095121_APPT_87.dat b/tests/ServiceLayer.IntegrationTests/TestData/KMK_20250212095121_APPT_87.dat similarity index 100% rename from tests/ServiceLayer.Mesh.Tests/TestData/KMK_20250212095121_APPT_87.dat rename to tests/ServiceLayer.IntegrationTests/TestData/KMK_20250212095121_APPT_87.dat diff --git a/tests/ServiceLayer.TestUtilities/HttpHelper.cs b/tests/ServiceLayer.TestUtilities/HttpHelper.cs new file mode 100644 index 0000000..5c171ae --- /dev/null +++ b/tests/ServiceLayer.TestUtilities/HttpHelper.cs @@ -0,0 +1,34 @@ +using System.Net; +using System.Net.Http.Headers; + +namespace ServiceLayer.TestUtilities; + +public static class HttpHelper +{ + private static readonly HttpClient _client = new(); + + public static async Task SendHttpRequestAsync( + HttpMethod method, + string url, + HttpContent? content = null, + Action? configureHeaders = null) + { + var request = new HttpRequestMessage(method, url) + { + Content = content + }; + + configureHeaders?.Invoke(request.Headers); + + try + { + var response = await _client.SendAsync(request); + return response; + } + catch (Exception ex) + { + Console.WriteLine($"HTTP Request failed: {ex.Message}"); + return new HttpResponseMessage(HttpStatusCode.InternalServerError); + } + } +} From 8415f93d6de8e38ea9c881be23610880b4cad5b0 Mon Sep 17 00:00:00 2001 From: alex-clayton-1 Date: Tue, 10 Jun 2025 11:26:26 +0100 Subject: [PATCH 07/18] style: Fixed formatting issue in sln file --- src/ServiceLayer.sln | 262 +++++++++++++++++++++---------------------- 1 file changed, 131 insertions(+), 131 deletions(-) diff --git a/src/ServiceLayer.sln b/src/ServiceLayer.sln index daca54b..67173a1 100644 --- a/src/ServiceLayer.sln +++ b/src/ServiceLayer.sln @@ -24,135 +24,135 @@ EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ServiceLayer.IntegrationTests", "..\tests\ServiceLayer.IntegrationTests\ServiceLayer.IntegrationTests.csproj", "{3C40C165-1D22-4E9B-80A8-059B321B7639}" EndProject Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Any CPU = Debug|Any CPU - Debug|x64 = Debug|x64 - Debug|x86 = Debug|x86 - Release|Any CPU = Release|Any CPU - Release|x64 = Release|x64 - Release|x86 = Release|x86 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {B56B41FF-FA39-0FDE-E266-6EC09B268DFB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {B56B41FF-FA39-0FDE-E266-6EC09B268DFB}.Debug|Any CPU.Build.0 = Debug|Any CPU - {B56B41FF-FA39-0FDE-E266-6EC09B268DFB}.Debug|x64.ActiveCfg = Debug|Any CPU - {B56B41FF-FA39-0FDE-E266-6EC09B268DFB}.Debug|x64.Build.0 = Debug|Any CPU - {B56B41FF-FA39-0FDE-E266-6EC09B268DFB}.Debug|x86.ActiveCfg = Debug|Any CPU - {B56B41FF-FA39-0FDE-E266-6EC09B268DFB}.Debug|x86.Build.0 = Debug|Any CPU - {B56B41FF-FA39-0FDE-E266-6EC09B268DFB}.Release|Any CPU.ActiveCfg = Release|Any CPU - {B56B41FF-FA39-0FDE-E266-6EC09B268DFB}.Release|Any CPU.Build.0 = Release|Any CPU - {B56B41FF-FA39-0FDE-E266-6EC09B268DFB}.Release|x64.ActiveCfg = Release|Any CPU - {B56B41FF-FA39-0FDE-E266-6EC09B268DFB}.Release|x64.Build.0 = Release|Any CPU - {B56B41FF-FA39-0FDE-E266-6EC09B268DFB}.Release|x86.ActiveCfg = Release|Any CPU - {B56B41FF-FA39-0FDE-E266-6EC09B268DFB}.Release|x86.Build.0 = Release|Any CPU - {BA052DAE-6FD1-483A-A0AF-DCBCF9E38C72}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {BA052DAE-6FD1-483A-A0AF-DCBCF9E38C72}.Debug|Any CPU.Build.0 = Debug|Any CPU - {BA052DAE-6FD1-483A-A0AF-DCBCF9E38C72}.Debug|x64.ActiveCfg = Debug|Any CPU - {BA052DAE-6FD1-483A-A0AF-DCBCF9E38C72}.Debug|x64.Build.0 = Debug|Any CPU - {BA052DAE-6FD1-483A-A0AF-DCBCF9E38C72}.Debug|x86.ActiveCfg = Debug|Any CPU - {BA052DAE-6FD1-483A-A0AF-DCBCF9E38C72}.Debug|x86.Build.0 = Debug|Any CPU - {BA052DAE-6FD1-483A-A0AF-DCBCF9E38C72}.Release|Any CPU.ActiveCfg = Release|Any CPU - {BA052DAE-6FD1-483A-A0AF-DCBCF9E38C72}.Release|Any CPU.Build.0 = Release|Any CPU - {BA052DAE-6FD1-483A-A0AF-DCBCF9E38C72}.Release|x64.ActiveCfg = Release|Any CPU - {BA052DAE-6FD1-483A-A0AF-DCBCF9E38C72}.Release|x64.Build.0 = Release|Any CPU - {BA052DAE-6FD1-483A-A0AF-DCBCF9E38C72}.Release|x86.ActiveCfg = Release|Any CPU - {BA052DAE-6FD1-483A-A0AF-DCBCF9E38C72}.Release|x86.Build.0 = Release|Any CPU - {803E8A5E-A180-4799-8BE2-DD5BD3C34ED2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {803E8A5E-A180-4799-8BE2-DD5BD3C34ED2}.Debug|Any CPU.Build.0 = Debug|Any CPU - {803E8A5E-A180-4799-8BE2-DD5BD3C34ED2}.Debug|x64.ActiveCfg = Debug|Any CPU - {803E8A5E-A180-4799-8BE2-DD5BD3C34ED2}.Debug|x64.Build.0 = Debug|Any CPU - {803E8A5E-A180-4799-8BE2-DD5BD3C34ED2}.Debug|x86.ActiveCfg = Debug|Any CPU - {803E8A5E-A180-4799-8BE2-DD5BD3C34ED2}.Debug|x86.Build.0 = Debug|Any CPU - {803E8A5E-A180-4799-8BE2-DD5BD3C34ED2}.Release|Any CPU.ActiveCfg = Release|Any CPU - {803E8A5E-A180-4799-8BE2-DD5BD3C34ED2}.Release|Any CPU.Build.0 = Release|Any CPU - {803E8A5E-A180-4799-8BE2-DD5BD3C34ED2}.Release|x64.ActiveCfg = Release|Any CPU - {803E8A5E-A180-4799-8BE2-DD5BD3C34ED2}.Release|x64.Build.0 = Release|Any CPU - {803E8A5E-A180-4799-8BE2-DD5BD3C34ED2}.Release|x86.ActiveCfg = Release|Any CPU - {803E8A5E-A180-4799-8BE2-DD5BD3C34ED2}.Release|x86.Build.0 = Release|Any CPU - {E5EF5B92-52DA-4EF3-956B-8AEE3D333428}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {E5EF5B92-52DA-4EF3-956B-8AEE3D333428}.Debug|Any CPU.Build.0 = Debug|Any CPU - {E5EF5B92-52DA-4EF3-956B-8AEE3D333428}.Debug|x64.ActiveCfg = Debug|Any CPU - {E5EF5B92-52DA-4EF3-956B-8AEE3D333428}.Debug|x64.Build.0 = Debug|Any CPU - {E5EF5B92-52DA-4EF3-956B-8AEE3D333428}.Debug|x86.ActiveCfg = Debug|Any CPU - {E5EF5B92-52DA-4EF3-956B-8AEE3D333428}.Debug|x86.Build.0 = Debug|Any CPU - {E5EF5B92-52DA-4EF3-956B-8AEE3D333428}.Release|Any CPU.ActiveCfg = Release|Any CPU - {E5EF5B92-52DA-4EF3-956B-8AEE3D333428}.Release|Any CPU.Build.0 = Release|Any CPU - {E5EF5B92-52DA-4EF3-956B-8AEE3D333428}.Release|x64.ActiveCfg = Release|Any CPU - {E5EF5B92-52DA-4EF3-956B-8AEE3D333428}.Release|x64.Build.0 = Release|Any CPU - {E5EF5B92-52DA-4EF3-956B-8AEE3D333428}.Release|x86.ActiveCfg = Release|Any CPU - {E5EF5B92-52DA-4EF3-956B-8AEE3D333428}.Release|x86.Build.0 = Release|Any CPU - {F373FEBA-AD0B-4E0B-BEE3-31D22C7AD43D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {F373FEBA-AD0B-4E0B-BEE3-31D22C7AD43D}.Debug|Any CPU.Build.0 = Debug|Any CPU - {F373FEBA-AD0B-4E0B-BEE3-31D22C7AD43D}.Debug|x64.ActiveCfg = Debug|Any CPU - {F373FEBA-AD0B-4E0B-BEE3-31D22C7AD43D}.Debug|x64.Build.0 = Debug|Any CPU - {F373FEBA-AD0B-4E0B-BEE3-31D22C7AD43D}.Debug|x86.ActiveCfg = Debug|Any CPU - {F373FEBA-AD0B-4E0B-BEE3-31D22C7AD43D}.Debug|x86.Build.0 = Debug|Any CPU - {F373FEBA-AD0B-4E0B-BEE3-31D22C7AD43D}.Release|Any CPU.ActiveCfg = Release|Any CPU - {F373FEBA-AD0B-4E0B-BEE3-31D22C7AD43D}.Release|Any CPU.Build.0 = Release|Any CPU - {F373FEBA-AD0B-4E0B-BEE3-31D22C7AD43D}.Release|x64.ActiveCfg = Release|Any CPU - {F373FEBA-AD0B-4E0B-BEE3-31D22C7AD43D}.Release|x64.Build.0 = Release|Any CPU - {F373FEBA-AD0B-4E0B-BEE3-31D22C7AD43D}.Release|x86.ActiveCfg = Release|Any CPU - {F373FEBA-AD0B-4E0B-BEE3-31D22C7AD43D}.Release|x86.Build.0 = Release|Any CPU - {B086BBF9-1A41-48C9-B019-F9C75CA634AF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {B086BBF9-1A41-48C9-B019-F9C75CA634AF}.Debug|Any CPU.Build.0 = Debug|Any CPU - {B086BBF9-1A41-48C9-B019-F9C75CA634AF}.Debug|x64.ActiveCfg = Debug|Any CPU - {B086BBF9-1A41-48C9-B019-F9C75CA634AF}.Debug|x64.Build.0 = Debug|Any CPU - {B086BBF9-1A41-48C9-B019-F9C75CA634AF}.Debug|x86.ActiveCfg = Debug|Any CPU - {B086BBF9-1A41-48C9-B019-F9C75CA634AF}.Debug|x86.Build.0 = Debug|Any CPU - {B086BBF9-1A41-48C9-B019-F9C75CA634AF}.Release|Any CPU.ActiveCfg = Release|Any CPU - {B086BBF9-1A41-48C9-B019-F9C75CA634AF}.Release|Any CPU.Build.0 = Release|Any CPU - {B086BBF9-1A41-48C9-B019-F9C75CA634AF}.Release|x64.ActiveCfg = Release|Any CPU - {B086BBF9-1A41-48C9-B019-F9C75CA634AF}.Release|x64.Build.0 = Release|Any CPU - {B086BBF9-1A41-48C9-B019-F9C75CA634AF}.Release|x86.ActiveCfg = Release|Any CPU - {B086BBF9-1A41-48C9-B019-F9C75CA634AF}.Release|x86.Build.0 = Release|Any CPU - {9642EC3A-9BC3-4557-ACD1-807FE764D5F6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {9642EC3A-9BC3-4557-ACD1-807FE764D5F6}.Debug|Any CPU.Build.0 = Debug|Any CPU - {9642EC3A-9BC3-4557-ACD1-807FE764D5F6}.Debug|x64.ActiveCfg = Debug|Any CPU - {9642EC3A-9BC3-4557-ACD1-807FE764D5F6}.Debug|x64.Build.0 = Debug|Any CPU - {9642EC3A-9BC3-4557-ACD1-807FE764D5F6}.Debug|x86.ActiveCfg = Debug|Any CPU - {9642EC3A-9BC3-4557-ACD1-807FE764D5F6}.Debug|x86.Build.0 = Debug|Any CPU - {9642EC3A-9BC3-4557-ACD1-807FE764D5F6}.Release|Any CPU.ActiveCfg = Release|Any CPU - {9642EC3A-9BC3-4557-ACD1-807FE764D5F6}.Release|Any CPU.Build.0 = Release|Any CPU - {9642EC3A-9BC3-4557-ACD1-807FE764D5F6}.Release|x64.ActiveCfg = Release|Any CPU - {9642EC3A-9BC3-4557-ACD1-807FE764D5F6}.Release|x64.Build.0 = Release|Any CPU - {9642EC3A-9BC3-4557-ACD1-807FE764D5F6}.Release|x86.ActiveCfg = Release|Any CPU - {9642EC3A-9BC3-4557-ACD1-807FE764D5F6}.Release|x86.Build.0 = Release|Any CPU - {43AE0301-63CA-4254-9580-4FB07C9D1920}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {43AE0301-63CA-4254-9580-4FB07C9D1920}.Debug|Any CPU.Build.0 = Debug|Any CPU - {43AE0301-63CA-4254-9580-4FB07C9D1920}.Debug|x64.ActiveCfg = Debug|Any CPU - {43AE0301-63CA-4254-9580-4FB07C9D1920}.Debug|x64.Build.0 = Debug|Any CPU - {43AE0301-63CA-4254-9580-4FB07C9D1920}.Debug|x86.ActiveCfg = Debug|Any CPU - {43AE0301-63CA-4254-9580-4FB07C9D1920}.Debug|x86.Build.0 = Debug|Any CPU - {43AE0301-63CA-4254-9580-4FB07C9D1920}.Release|Any CPU.ActiveCfg = Release|Any CPU - {43AE0301-63CA-4254-9580-4FB07C9D1920}.Release|Any CPU.Build.0 = Release|Any CPU - {43AE0301-63CA-4254-9580-4FB07C9D1920}.Release|x64.ActiveCfg = Release|Any CPU - {43AE0301-63CA-4254-9580-4FB07C9D1920}.Release|x64.Build.0 = Release|Any CPU - {43AE0301-63CA-4254-9580-4FB07C9D1920}.Release|x86.ActiveCfg = Release|Any CPU - {43AE0301-63CA-4254-9580-4FB07C9D1920}.Release|x86.Build.0 = Release|Any CPU - {3C40C165-1D22-4E9B-80A8-059B321B7639}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {3C40C165-1D22-4E9B-80A8-059B321B7639}.Debug|Any CPU.Build.0 = Debug|Any CPU - {3C40C165-1D22-4E9B-80A8-059B321B7639}.Debug|x64.ActiveCfg = Debug|Any CPU - {3C40C165-1D22-4E9B-80A8-059B321B7639}.Debug|x64.Build.0 = Debug|Any CPU - {3C40C165-1D22-4E9B-80A8-059B321B7639}.Debug|x86.ActiveCfg = Debug|Any CPU - {3C40C165-1D22-4E9B-80A8-059B321B7639}.Debug|x86.Build.0 = Debug|Any CPU - {3C40C165-1D22-4E9B-80A8-059B321B7639}.Release|Any CPU.ActiveCfg = Release|Any CPU - {3C40C165-1D22-4E9B-80A8-059B321B7639}.Release|Any CPU.Build.0 = Release|Any CPU - {3C40C165-1D22-4E9B-80A8-059B321B7639}.Release|x64.ActiveCfg = Release|Any CPU - {3C40C165-1D22-4E9B-80A8-059B321B7639}.Release|x64.Build.0 = Release|Any CPU - {3C40C165-1D22-4E9B-80A8-059B321B7639}.Release|x86.ActiveCfg = Release|Any CPU - {3C40C165-1D22-4E9B-80A8-059B321B7639}.Release|x86.Build.0 = Release|Any CPU - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection - GlobalSection(NestedProjects) = preSolution - {BA052DAE-6FD1-483A-A0AF-DCBCF9E38C72} = {0AB3BF05-4346-4AA6-1389-037BE0695223} - {E5EF5B92-52DA-4EF3-956B-8AEE3D333428} = {0AB3BF05-4346-4AA6-1389-037BE0695223} - {9642EC3A-9BC3-4557-ACD1-807FE764D5F6} = {0AB3BF05-4346-4AA6-1389-037BE0695223} - {43AE0301-63CA-4254-9580-4FB07C9D1920} = {0AB3BF05-4346-4AA6-1389-037BE0695223} - {3C40C165-1D22-4E9B-80A8-059B321B7639} = {0AB3BF05-4346-4AA6-1389-037BE0695223} - EndGlobalSection - GlobalSection(ExtensibilityGlobals) = postSolution - SolutionGuid = {EEE06B13-019F-4618-A6EB-FD834B6EA7D7} - EndGlobalSection + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|Any CPU = Release|Any CPU + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {B56B41FF-FA39-0FDE-E266-6EC09B268DFB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B56B41FF-FA39-0FDE-E266-6EC09B268DFB}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B56B41FF-FA39-0FDE-E266-6EC09B268DFB}.Debug|x64.ActiveCfg = Debug|Any CPU + {B56B41FF-FA39-0FDE-E266-6EC09B268DFB}.Debug|x64.Build.0 = Debug|Any CPU + {B56B41FF-FA39-0FDE-E266-6EC09B268DFB}.Debug|x86.ActiveCfg = Debug|Any CPU + {B56B41FF-FA39-0FDE-E266-6EC09B268DFB}.Debug|x86.Build.0 = Debug|Any CPU + {B56B41FF-FA39-0FDE-E266-6EC09B268DFB}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B56B41FF-FA39-0FDE-E266-6EC09B268DFB}.Release|Any CPU.Build.0 = Release|Any CPU + {B56B41FF-FA39-0FDE-E266-6EC09B268DFB}.Release|x64.ActiveCfg = Release|Any CPU + {B56B41FF-FA39-0FDE-E266-6EC09B268DFB}.Release|x64.Build.0 = Release|Any CPU + {B56B41FF-FA39-0FDE-E266-6EC09B268DFB}.Release|x86.ActiveCfg = Release|Any CPU + {B56B41FF-FA39-0FDE-E266-6EC09B268DFB}.Release|x86.Build.0 = Release|Any CPU + {BA052DAE-6FD1-483A-A0AF-DCBCF9E38C72}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {BA052DAE-6FD1-483A-A0AF-DCBCF9E38C72}.Debug|Any CPU.Build.0 = Debug|Any CPU + {BA052DAE-6FD1-483A-A0AF-DCBCF9E38C72}.Debug|x64.ActiveCfg = Debug|Any CPU + {BA052DAE-6FD1-483A-A0AF-DCBCF9E38C72}.Debug|x64.Build.0 = Debug|Any CPU + {BA052DAE-6FD1-483A-A0AF-DCBCF9E38C72}.Debug|x86.ActiveCfg = Debug|Any CPU + {BA052DAE-6FD1-483A-A0AF-DCBCF9E38C72}.Debug|x86.Build.0 = Debug|Any CPU + {BA052DAE-6FD1-483A-A0AF-DCBCF9E38C72}.Release|Any CPU.ActiveCfg = Release|Any CPU + {BA052DAE-6FD1-483A-A0AF-DCBCF9E38C72}.Release|Any CPU.Build.0 = Release|Any CPU + {BA052DAE-6FD1-483A-A0AF-DCBCF9E38C72}.Release|x64.ActiveCfg = Release|Any CPU + {BA052DAE-6FD1-483A-A0AF-DCBCF9E38C72}.Release|x64.Build.0 = Release|Any CPU + {BA052DAE-6FD1-483A-A0AF-DCBCF9E38C72}.Release|x86.ActiveCfg = Release|Any CPU + {BA052DAE-6FD1-483A-A0AF-DCBCF9E38C72}.Release|x86.Build.0 = Release|Any CPU + {803E8A5E-A180-4799-8BE2-DD5BD3C34ED2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {803E8A5E-A180-4799-8BE2-DD5BD3C34ED2}.Debug|Any CPU.Build.0 = Debug|Any CPU + {803E8A5E-A180-4799-8BE2-DD5BD3C34ED2}.Debug|x64.ActiveCfg = Debug|Any CPU + {803E8A5E-A180-4799-8BE2-DD5BD3C34ED2}.Debug|x64.Build.0 = Debug|Any CPU + {803E8A5E-A180-4799-8BE2-DD5BD3C34ED2}.Debug|x86.ActiveCfg = Debug|Any CPU + {803E8A5E-A180-4799-8BE2-DD5BD3C34ED2}.Debug|x86.Build.0 = Debug|Any CPU + {803E8A5E-A180-4799-8BE2-DD5BD3C34ED2}.Release|Any CPU.ActiveCfg = Release|Any CPU + {803E8A5E-A180-4799-8BE2-DD5BD3C34ED2}.Release|Any CPU.Build.0 = Release|Any CPU + {803E8A5E-A180-4799-8BE2-DD5BD3C34ED2}.Release|x64.ActiveCfg = Release|Any CPU + {803E8A5E-A180-4799-8BE2-DD5BD3C34ED2}.Release|x64.Build.0 = Release|Any CPU + {803E8A5E-A180-4799-8BE2-DD5BD3C34ED2}.Release|x86.ActiveCfg = Release|Any CPU + {803E8A5E-A180-4799-8BE2-DD5BD3C34ED2}.Release|x86.Build.0 = Release|Any CPU + {E5EF5B92-52DA-4EF3-956B-8AEE3D333428}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {E5EF5B92-52DA-4EF3-956B-8AEE3D333428}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E5EF5B92-52DA-4EF3-956B-8AEE3D333428}.Debug|x64.ActiveCfg = Debug|Any CPU + {E5EF5B92-52DA-4EF3-956B-8AEE3D333428}.Debug|x64.Build.0 = Debug|Any CPU + {E5EF5B92-52DA-4EF3-956B-8AEE3D333428}.Debug|x86.ActiveCfg = Debug|Any CPU + {E5EF5B92-52DA-4EF3-956B-8AEE3D333428}.Debug|x86.Build.0 = Debug|Any CPU + {E5EF5B92-52DA-4EF3-956B-8AEE3D333428}.Release|Any CPU.ActiveCfg = Release|Any CPU + {E5EF5B92-52DA-4EF3-956B-8AEE3D333428}.Release|Any CPU.Build.0 = Release|Any CPU + {E5EF5B92-52DA-4EF3-956B-8AEE3D333428}.Release|x64.ActiveCfg = Release|Any CPU + {E5EF5B92-52DA-4EF3-956B-8AEE3D333428}.Release|x64.Build.0 = Release|Any CPU + {E5EF5B92-52DA-4EF3-956B-8AEE3D333428}.Release|x86.ActiveCfg = Release|Any CPU + {E5EF5B92-52DA-4EF3-956B-8AEE3D333428}.Release|x86.Build.0 = Release|Any CPU + {F373FEBA-AD0B-4E0B-BEE3-31D22C7AD43D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {F373FEBA-AD0B-4E0B-BEE3-31D22C7AD43D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F373FEBA-AD0B-4E0B-BEE3-31D22C7AD43D}.Debug|x64.ActiveCfg = Debug|Any CPU + {F373FEBA-AD0B-4E0B-BEE3-31D22C7AD43D}.Debug|x64.Build.0 = Debug|Any CPU + {F373FEBA-AD0B-4E0B-BEE3-31D22C7AD43D}.Debug|x86.ActiveCfg = Debug|Any CPU + {F373FEBA-AD0B-4E0B-BEE3-31D22C7AD43D}.Debug|x86.Build.0 = Debug|Any CPU + {F373FEBA-AD0B-4E0B-BEE3-31D22C7AD43D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {F373FEBA-AD0B-4E0B-BEE3-31D22C7AD43D}.Release|Any CPU.Build.0 = Release|Any CPU + {F373FEBA-AD0B-4E0B-BEE3-31D22C7AD43D}.Release|x64.ActiveCfg = Release|Any CPU + {F373FEBA-AD0B-4E0B-BEE3-31D22C7AD43D}.Release|x64.Build.0 = Release|Any CPU + {F373FEBA-AD0B-4E0B-BEE3-31D22C7AD43D}.Release|x86.ActiveCfg = Release|Any CPU + {F373FEBA-AD0B-4E0B-BEE3-31D22C7AD43D}.Release|x86.Build.0 = Release|Any CPU + {B086BBF9-1A41-48C9-B019-F9C75CA634AF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B086BBF9-1A41-48C9-B019-F9C75CA634AF}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B086BBF9-1A41-48C9-B019-F9C75CA634AF}.Debug|x64.ActiveCfg = Debug|Any CPU + {B086BBF9-1A41-48C9-B019-F9C75CA634AF}.Debug|x64.Build.0 = Debug|Any CPU + {B086BBF9-1A41-48C9-B019-F9C75CA634AF}.Debug|x86.ActiveCfg = Debug|Any CPU + {B086BBF9-1A41-48C9-B019-F9C75CA634AF}.Debug|x86.Build.0 = Debug|Any CPU + {B086BBF9-1A41-48C9-B019-F9C75CA634AF}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B086BBF9-1A41-48C9-B019-F9C75CA634AF}.Release|Any CPU.Build.0 = Release|Any CPU + {B086BBF9-1A41-48C9-B019-F9C75CA634AF}.Release|x64.ActiveCfg = Release|Any CPU + {B086BBF9-1A41-48C9-B019-F9C75CA634AF}.Release|x64.Build.0 = Release|Any CPU + {B086BBF9-1A41-48C9-B019-F9C75CA634AF}.Release|x86.ActiveCfg = Release|Any CPU + {B086BBF9-1A41-48C9-B019-F9C75CA634AF}.Release|x86.Build.0 = Release|Any CPU + {9642EC3A-9BC3-4557-ACD1-807FE764D5F6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {9642EC3A-9BC3-4557-ACD1-807FE764D5F6}.Debug|Any CPU.Build.0 = Debug|Any CPU + {9642EC3A-9BC3-4557-ACD1-807FE764D5F6}.Debug|x64.ActiveCfg = Debug|Any CPU + {9642EC3A-9BC3-4557-ACD1-807FE764D5F6}.Debug|x64.Build.0 = Debug|Any CPU + {9642EC3A-9BC3-4557-ACD1-807FE764D5F6}.Debug|x86.ActiveCfg = Debug|Any CPU + {9642EC3A-9BC3-4557-ACD1-807FE764D5F6}.Debug|x86.Build.0 = Debug|Any CPU + {9642EC3A-9BC3-4557-ACD1-807FE764D5F6}.Release|Any CPU.ActiveCfg = Release|Any CPU + {9642EC3A-9BC3-4557-ACD1-807FE764D5F6}.Release|Any CPU.Build.0 = Release|Any CPU + {9642EC3A-9BC3-4557-ACD1-807FE764D5F6}.Release|x64.ActiveCfg = Release|Any CPU + {9642EC3A-9BC3-4557-ACD1-807FE764D5F6}.Release|x64.Build.0 = Release|Any CPU + {9642EC3A-9BC3-4557-ACD1-807FE764D5F6}.Release|x86.ActiveCfg = Release|Any CPU + {9642EC3A-9BC3-4557-ACD1-807FE764D5F6}.Release|x86.Build.0 = Release|Any CPU + {43AE0301-63CA-4254-9580-4FB07C9D1920}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {43AE0301-63CA-4254-9580-4FB07C9D1920}.Debug|Any CPU.Build.0 = Debug|Any CPU + {43AE0301-63CA-4254-9580-4FB07C9D1920}.Debug|x64.ActiveCfg = Debug|Any CPU + {43AE0301-63CA-4254-9580-4FB07C9D1920}.Debug|x64.Build.0 = Debug|Any CPU + {43AE0301-63CA-4254-9580-4FB07C9D1920}.Debug|x86.ActiveCfg = Debug|Any CPU + {43AE0301-63CA-4254-9580-4FB07C9D1920}.Debug|x86.Build.0 = Debug|Any CPU + {43AE0301-63CA-4254-9580-4FB07C9D1920}.Release|Any CPU.ActiveCfg = Release|Any CPU + {43AE0301-63CA-4254-9580-4FB07C9D1920}.Release|Any CPU.Build.0 = Release|Any CPU + {43AE0301-63CA-4254-9580-4FB07C9D1920}.Release|x64.ActiveCfg = Release|Any CPU + {43AE0301-63CA-4254-9580-4FB07C9D1920}.Release|x64.Build.0 = Release|Any CPU + {43AE0301-63CA-4254-9580-4FB07C9D1920}.Release|x86.ActiveCfg = Release|Any CPU + {43AE0301-63CA-4254-9580-4FB07C9D1920}.Release|x86.Build.0 = Release|Any CPU + {3C40C165-1D22-4E9B-80A8-059B321B7639}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {3C40C165-1D22-4E9B-80A8-059B321B7639}.Debug|Any CPU.Build.0 = Debug|Any CPU + {3C40C165-1D22-4E9B-80A8-059B321B7639}.Debug|x64.ActiveCfg = Debug|Any CPU + {3C40C165-1D22-4E9B-80A8-059B321B7639}.Debug|x64.Build.0 = Debug|Any CPU + {3C40C165-1D22-4E9B-80A8-059B321B7639}.Debug|x86.ActiveCfg = Debug|Any CPU + {3C40C165-1D22-4E9B-80A8-059B321B7639}.Debug|x86.Build.0 = Debug|Any CPU + {3C40C165-1D22-4E9B-80A8-059B321B7639}.Release|Any CPU.ActiveCfg = Release|Any CPU + {3C40C165-1D22-4E9B-80A8-059B321B7639}.Release|Any CPU.Build.0 = Release|Any CPU + {3C40C165-1D22-4E9B-80A8-059B321B7639}.Release|x64.ActiveCfg = Release|Any CPU + {3C40C165-1D22-4E9B-80A8-059B321B7639}.Release|x64.Build.0 = Release|Any CPU + {3C40C165-1D22-4E9B-80A8-059B321B7639}.Release|x86.ActiveCfg = Release|Any CPU + {3C40C165-1D22-4E9B-80A8-059B321B7639}.Release|x86.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(NestedProjects) = preSolution + {BA052DAE-6FD1-483A-A0AF-DCBCF9E38C72} = {0AB3BF05-4346-4AA6-1389-037BE0695223} + {E5EF5B92-52DA-4EF3-956B-8AEE3D333428} = {0AB3BF05-4346-4AA6-1389-037BE0695223} + {9642EC3A-9BC3-4557-ACD1-807FE764D5F6} = {0AB3BF05-4346-4AA6-1389-037BE0695223} + {43AE0301-63CA-4254-9580-4FB07C9D1920} = {0AB3BF05-4346-4AA6-1389-037BE0695223} + {3C40C165-1D22-4E9B-80A8-059B321B7639} = {0AB3BF05-4346-4AA6-1389-037BE0695223} + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {EEE06B13-019F-4618-A6EB-FD834B6EA7D7} + EndGlobalSection EndGlobal From 562cff1d2cb2d83a9c9c176ecb7185ca4dd91c75 Mon Sep 17 00:00:00 2001 From: alex-clayton-1 Date: Tue, 10 Jun 2025 17:04:12 +0100 Subject: [PATCH 08/18] test: Introduced environment variables and readme for integration tests --- .../IntegrationTests.cs | 34 +++++++++++++------ tests/ServiceLayer.IntegrationTests/README.md | 14 ++++++++ 2 files changed, 38 insertions(+), 10 deletions(-) create mode 100644 tests/ServiceLayer.IntegrationTests/README.md diff --git a/tests/ServiceLayer.IntegrationTests/IntegrationTests.cs b/tests/ServiceLayer.IntegrationTests/IntegrationTests.cs index 1ebbc24..cd19114 100644 --- a/tests/ServiceLayer.IntegrationTests/IntegrationTests.cs +++ b/tests/ServiceLayer.IntegrationTests/IntegrationTests.cs @@ -18,6 +18,21 @@ public class DockerComposeCollection : ICollectionFixture [Collection("DockerComposeCollection")] public class IntegrationTests { + private readonly string _azuriteAccountKey = Environment.GetEnvironmentVariable("AZURITE_ACCOUNT_KEY") + ?? throw new InvalidOperationException($"Environment variable 'AZURITE_ACCOUNT_KEY' is not set."); + private readonly string _azuriteAccountName = Environment.GetEnvironmentVariable("AZURITE_ACCOUNT_NAME") + ?? throw new InvalidOperationException($"Environment variable 'AZURITE_ACCOUNT_NAME' is not set."); + private readonly string _azuriteBlobPort = Environment.GetEnvironmentVariable("AZURITE_BLOB_PORT") + ?? throw new InvalidOperationException($"Environment variable 'AZURITE_BLOB_PORT' is not set."); + private readonly string _meshIngestPort = Environment.GetEnvironmentVariable("MESH_INGEST_PORT") + ?? throw new InvalidOperationException($"Environment variable 'MESH_INGEST_PORT' is not set."); + private readonly string _meshSandboxPort = Environment.GetEnvironmentVariable("MESH_SANDBOX_PORT") + ?? throw new InvalidOperationException($"Environment variable 'MESH_SANDBOX_PORT' is not set."); + private readonly string _blobContainerName = Environment.GetEnvironmentVariable("BLOB_CONTAINER_NAME") + ?? throw new InvalidOperationException($"Environment variable 'BLOB_CONTAINER_NAME' is not set."); + private readonly string _databaseConnectionString = Environment.GetEnvironmentVariable("DATABASE_CONNECTION_STRING") + ?? throw new InvalidOperationException($"Environment variable 'DATABASE_CONNECTION_STRING' is not set."); + [Fact] public async Task FileSentToMeshInbox_FileIsUploadedToBlobContainerAndInsertedIntoDb() { @@ -36,13 +51,13 @@ public async Task FileSentToMeshInbox_FileIsUploadedToBlobContainerAndInsertedIn Assert.True(await WasFileInsertedIntoDatabase(fileId)); } - private static async Task WaitForHealthyService() + private async Task WaitForHealthyService() { int attemptCounter = 0; while (attemptCounter < 10) { - var response = await HttpHelper.SendHttpRequestAsync(HttpMethod.Get, "http://localhost:7072/api/health"); + var response = await HttpHelper.SendHttpRequestAsync(HttpMethod.Get, $"http://localhost:{_meshIngestPort}/api/health"); if (response.IsSuccessStatusCode) { @@ -59,7 +74,7 @@ private static async Task WaitForHealthyService() throw new TimeoutException("Timed out waiting on Mesh Ingest Service health check"); } - private static async Task SendFileToMeshInbox(string fileName) + private async Task SendFileToMeshInbox(string fileName) { byte[] binaryData = await File.ReadAllBytesAsync($"TestData/{fileName}"); var content = new ByteArrayContent(binaryData); @@ -67,7 +82,7 @@ private static async Task WaitForHealthyService() var response = await HttpHelper.SendHttpRequestAsync( HttpMethod.Post, - "http://localhost:8700/messageexchange/X26ABC1/outbox", + $"http://localhost:{_meshSandboxPort}/messageexchange/X26ABC1/outbox", content, headers => { @@ -86,11 +101,11 @@ private static async Task WaitForHealthyService() return responseObject?.MessageID; } - private static async Task WasFileUploadedToBlobContainer(string fileId) + private async Task WasFileUploadedToBlobContainer(string fileId) { - var blobConnectionString = "DefaultEndpointsProtocol=http;AccountName=devstoreaccount1;AccountKey=Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw==;BlobEndpoint=http://127.0.0.1:10000/devstoreaccount1"; + var blobConnectionString = $"DefaultEndpointsProtocol=http;AccountName={_azuriteAccountName};AccountKey={_azuriteAccountKey};BlobEndpoint=http://localhost:{_azuriteBlobPort}/{_azuriteAccountName}"; - var containerClient = new BlobContainerClient(blobConnectionString, "incoming-mesh-files"); + var containerClient = new BlobContainerClient(blobConnectionString, _blobContainerName); try { @@ -106,11 +121,10 @@ private static async Task WasFileUploadedToBlobContainer(string fileId) } } - private static async Task WasFileInsertedIntoDatabase(string fileId) + private async Task WasFileInsertedIntoDatabase(string fileId) { - var connectionString = "Server=localhost;Database=ServiceLayer;User Id=SA;Password=YourStrong@Passw0rd;TrustServerCertificate=True"; var options = new DbContextOptionsBuilder() - .UseSqlServer(connectionString) + .UseSqlServer(_databaseConnectionString) .Options; var context = new ServiceLayerDbContext(options); diff --git a/tests/ServiceLayer.IntegrationTests/README.md b/tests/ServiceLayer.IntegrationTests/README.md new file mode 100644 index 0000000..9f7e762 --- /dev/null +++ b/tests/ServiceLayer.IntegrationTests/README.md @@ -0,0 +1,14 @@ +Provide the values for all environment variables when running the integration tests, e.g. + +```sh +dotnet test \ + -e AZURITE_ACCOUNT_KEY="Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw==" \ + -e AZURITE_ACCOUNT_NAME=devstoreaccount1 \ + -e AZURITE_BLOB_PORT=10000 \ + -e MESH_INGEST_PORT=7072 \ + -e MESH_SANDBOX_PORT=8700 \ + -e BLOB_CONTAINER_NAME=incoming-mesh-files \ + -e DATABASE_CONNECTION_STRING="Server=localhost;Database=ServiceLayer;User Id=SA;Password=YourStrong@Passw0rd;TrustServerCertificate=True" +``` + +Also, remember to set the FileDiscoveryTimerExpression to a shorter interval e.g. every 5 seconds (*/5 * * * * *) From 5774d67ce19c1aeec4a3567e9c08d119e734d025 Mon Sep 17 00:00:00 2001 From: alex-clayton-1 Date: Wed, 11 Jun 2025 11:16:22 +0100 Subject: [PATCH 09/18] test: Updated integration test to use new environment variable name --- .../IntegrationTests.cs | 20 +++++++++++++------ tests/ServiceLayer.IntegrationTests/README.md | 2 +- .../ServiceLayer.TestUtilities/HttpHelper.cs | 3 +-- 3 files changed, 16 insertions(+), 9 deletions(-) diff --git a/tests/ServiceLayer.IntegrationTests/IntegrationTests.cs b/tests/ServiceLayer.IntegrationTests/IntegrationTests.cs index cd19114..5b47403 100644 --- a/tests/ServiceLayer.IntegrationTests/IntegrationTests.cs +++ b/tests/ServiceLayer.IntegrationTests/IntegrationTests.cs @@ -28,8 +28,8 @@ public class IntegrationTests ?? throw new InvalidOperationException($"Environment variable 'MESH_INGEST_PORT' is not set."); private readonly string _meshSandboxPort = Environment.GetEnvironmentVariable("MESH_SANDBOX_PORT") ?? throw new InvalidOperationException($"Environment variable 'MESH_SANDBOX_PORT' is not set."); - private readonly string _blobContainerName = Environment.GetEnvironmentVariable("BLOB_CONTAINER_NAME") - ?? throw new InvalidOperationException($"Environment variable 'BLOB_CONTAINER_NAME' is not set."); + private readonly string _meshBlobContainerName = Environment.GetEnvironmentVariable("MESH_BLOB_CONTAINER_NAME") + ?? throw new InvalidOperationException($"Environment variable 'MESH_BLOB_CONTAINER_NAME' is not set."); private readonly string _databaseConnectionString = Environment.GetEnvironmentVariable("DATABASE_CONNECTION_STRING") ?? throw new InvalidOperationException($"Environment variable 'DATABASE_CONNECTION_STRING' is not set."); @@ -53,6 +53,8 @@ public async Task FileSentToMeshInbox_FileIsUploadedToBlobContainerAndInsertedIn private async Task WaitForHealthyService() { + Console.WriteLine("Waiting for Mesh Ingest Service health check to pass..."); + int attemptCounter = 0; while (attemptCounter < 10) @@ -105,7 +107,7 @@ private async Task WasFileUploadedToBlobContainer(string fileId) { var blobConnectionString = $"DefaultEndpointsProtocol=http;AccountName={_azuriteAccountName};AccountKey={_azuriteAccountKey};BlobEndpoint=http://localhost:{_azuriteBlobPort}/{_azuriteAccountName}"; - var containerClient = new BlobContainerClient(blobConnectionString, _blobContainerName); + var containerClient = new BlobContainerClient(blobConnectionString, _meshBlobContainerName); try { @@ -143,11 +145,12 @@ public class DockerComposeFixture : IAsyncLifetime { public async Task InitializeAsync() { - // Start Docker Compose + Console.WriteLine("Starting up docker containers..."); + var startInfo = new ProcessStartInfo { FileName = "docker", - Arguments = "compose up -d mesh-ingest mesh-sandbox azurite db db-migrations", + Arguments = "compose up -d svclyr-mesh-ingest mesh-sandbox azurite db db-migrations", RedirectStandardOutput = true, RedirectStandardError = true, UseShellExecute = false, @@ -167,11 +170,14 @@ public async Task InitializeAsync() { throw new Exception($"Docker process started but failed, error: {process.StandardError.ReadToEnd()}"); } + + Console.WriteLine("Docker containers successfully started"); } public async Task DisposeAsync() { - // Stop Docker Compose + Console.WriteLine("Stopping docker containers..."); + var stopInfo = new ProcessStartInfo { FileName = "docker", @@ -195,5 +201,7 @@ public async Task DisposeAsync() { throw new Exception($"Docker process started but failed, error: {process.StandardError.ReadToEnd()}"); } + + Console.WriteLine("Docker containers stopped"); } } diff --git a/tests/ServiceLayer.IntegrationTests/README.md b/tests/ServiceLayer.IntegrationTests/README.md index 9f7e762..82e29c8 100644 --- a/tests/ServiceLayer.IntegrationTests/README.md +++ b/tests/ServiceLayer.IntegrationTests/README.md @@ -7,7 +7,7 @@ dotnet test \ -e AZURITE_BLOB_PORT=10000 \ -e MESH_INGEST_PORT=7072 \ -e MESH_SANDBOX_PORT=8700 \ - -e BLOB_CONTAINER_NAME=incoming-mesh-files \ + -e MESH_BLOB_CONTAINER_NAME=incoming-mesh-files \ -e DATABASE_CONNECTION_STRING="Server=localhost;Database=ServiceLayer;User Id=SA;Password=YourStrong@Passw0rd;TrustServerCertificate=True" ``` diff --git a/tests/ServiceLayer.TestUtilities/HttpHelper.cs b/tests/ServiceLayer.TestUtilities/HttpHelper.cs index 5c171ae..13fc2c3 100644 --- a/tests/ServiceLayer.TestUtilities/HttpHelper.cs +++ b/tests/ServiceLayer.TestUtilities/HttpHelper.cs @@ -25,9 +25,8 @@ public static async Task SendHttpRequestAsync( var response = await _client.SendAsync(request); return response; } - catch (Exception ex) + catch { - Console.WriteLine($"HTTP Request failed: {ex.Message}"); return new HttpResponseMessage(HttpStatusCode.InternalServerError); } } From 0d721312ff317db6396af38253ef4c14152761f6 Mon Sep 17 00:00:00 2001 From: alex-clayton-1 Date: Wed, 11 Jun 2025 14:39:54 +0100 Subject: [PATCH 10/18] test: Added separate .env file for the integration tests --- .../ServiceLayer.IntegrationTests/.env.tests | 35 +++++++++++++++++++ .../IntegrationTests.cs | 2 +- tests/ServiceLayer.IntegrationTests/README.md | 12 +++++-- .../ServiceLayer.IntegrationTests.csproj | 13 ++++--- 4 files changed, 54 insertions(+), 8 deletions(-) create mode 100644 tests/ServiceLayer.IntegrationTests/.env.tests diff --git a/tests/ServiceLayer.IntegrationTests/.env.tests b/tests/ServiceLayer.IntegrationTests/.env.tests new file mode 100644 index 0000000..08c011f --- /dev/null +++ b/tests/ServiceLayer.IntegrationTests/.env.tests @@ -0,0 +1,35 @@ +# Database +DATABASE_USER=SA +DATABASE_PASSWORD=YourStrong@Passw0rd +DATABASE_NAME=ServiceLayer +DATABASE_HOST=db +DatabaseConnectionString=Server=${DATABASE_HOST};Database=${DATABASE_NAME};User Id=${DATABASE_USER};Password=${DATABASE_PASSWORD};TrustServerCertificate=True + +# MESH +MeshSharedKey=TestKey +MeshPassword=password +NbssMailboxId=X26ABC1 +MeshApiBaseUrl=http://localhost:8700/messageexchange + +# Other +ASPNETCORE_ENVIRONMENT=Development +FileDiscoveryTimerExpression=*/5 * * * * * # Every 5 seconds so that the test doesn't have to wait too long +MeshHandshakeTimerExpression=0 0 0 * * * # Midnight +FileRetryTimerExpression=0 0 * * * * +FileExtractQueueName=file-extract +FileTransformQueueName=file-transform +StaleHours=12 +MeshBlobContainerName=incoming-mesh-files +API_PORT=7071 +MESH_INGEST_PORT=7072 + +# Event Grid +EVENT_GRID_TOPIC_URL=https://localhost:60101/api/events +EVENT_GRID_TOPIC_KEY=TheLocal+DevelopmentKey= + +# Azurite +AZURITE_ACCOUNT_KEY=Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw== # Standard default Azurite key +AZURITE_CONNECTION_STRING=DefaultEndpointsProtocol=http;AccountName=devstoreaccount1;AccountKey=${AZURITE_ACCOUNT_KEY};BlobEndpoint=http://azurite:10000/devstoreaccount1;QueueEndpoint=http://azurite:10001/devstoreaccount1;TableEndpoint=http://azurite/devstoreaccount1 +AZURITE_BLOB_PORT=10000 +AZURITE_QUEUE_PORT=10001 +AZURITE_TABLE_PORT=10002 diff --git a/tests/ServiceLayer.IntegrationTests/IntegrationTests.cs b/tests/ServiceLayer.IntegrationTests/IntegrationTests.cs index 5b47403..3f9eb37 100644 --- a/tests/ServiceLayer.IntegrationTests/IntegrationTests.cs +++ b/tests/ServiceLayer.IntegrationTests/IntegrationTests.cs @@ -150,7 +150,7 @@ public async Task InitializeAsync() var startInfo = new ProcessStartInfo { FileName = "docker", - Arguments = "compose up -d svclyr-mesh-ingest mesh-sandbox azurite db db-migrations", + Arguments = "compose --env-file .env.tests up -d svclyr-mesh-ingest mesh-sandbox azurite db db-migrations", RedirectStandardOutput = true, RedirectStandardError = true, UseShellExecute = false, diff --git a/tests/ServiceLayer.IntegrationTests/README.md b/tests/ServiceLayer.IntegrationTests/README.md index 82e29c8..18864ed 100644 --- a/tests/ServiceLayer.IntegrationTests/README.md +++ b/tests/ServiceLayer.IntegrationTests/README.md @@ -1,5 +1,13 @@ -Provide the values for all environment variables when running the integration tests, e.g. +The integration tests require the following environment variables to run: +- AZURITE_ACCOUNT_KEY +- AZURITE_ACCOUNT_NAME +- AZURITE_BLOB_PORT +- MESH_INGEST_PORT +- MESH_SANDBOX_PORT +- MESH_BLOB_CONTAINER_NAME +- DATABASE_CONNECTION_STRING +They can be passed as arguments like so ```sh dotnet test \ -e AZURITE_ACCOUNT_KEY="Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw==" \ @@ -10,5 +18,3 @@ dotnet test \ -e MESH_BLOB_CONTAINER_NAME=incoming-mesh-files \ -e DATABASE_CONNECTION_STRING="Server=localhost;Database=ServiceLayer;User Id=SA;Password=YourStrong@Passw0rd;TrustServerCertificate=True" ``` - -Also, remember to set the FileDiscoveryTimerExpression to a shorter interval e.g. every 5 seconds (*/5 * * * * *) diff --git a/tests/ServiceLayer.IntegrationTests/ServiceLayer.IntegrationTests.csproj b/tests/ServiceLayer.IntegrationTests/ServiceLayer.IntegrationTests.csproj index 92f4669..187409b 100644 --- a/tests/ServiceLayer.IntegrationTests/ServiceLayer.IntegrationTests.csproj +++ b/tests/ServiceLayer.IntegrationTests/ServiceLayer.IntegrationTests.csproj @@ -26,9 +26,14 @@ - - PreserveNewest - - + + PreserveNewest + + + + + PreserveNewest + + From 4d3d205091f4b5f26344332fb16f4b6e1087d3dc Mon Sep 17 00:00:00 2001 From: alex-clayton-1 Date: Wed, 11 Jun 2025 16:14:23 +0100 Subject: [PATCH 11/18] test: Added comment about mesh-sandbox repo in compose file --- compose.yaml | 3 ++- tests/ServiceLayer.IntegrationTests/IntegrationTests.cs | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/compose.yaml b/compose.yaml index bdfe776..6095421 100644 --- a/compose.yaml +++ b/compose.yaml @@ -140,7 +140,8 @@ services: networks: - backend - + # Clone the mesh sandbox repo so that it is in the same directory as dtos-service-layer + # https://github.com/NHSDigital/mesh-sandbox mesh-sandbox: container_name: mesh-sandbox build: ../mesh-sandbox/ diff --git a/tests/ServiceLayer.IntegrationTests/IntegrationTests.cs b/tests/ServiceLayer.IntegrationTests/IntegrationTests.cs index 3f9eb37..669f546 100644 --- a/tests/ServiceLayer.IntegrationTests/IntegrationTests.cs +++ b/tests/ServiceLayer.IntegrationTests/IntegrationTests.cs @@ -42,7 +42,7 @@ public async Task FileSentToMeshInbox_FileIsUploadedToBlobContainerAndInsertedIn // Act var fileId = await SendFileToMeshInbox("KMK_20250212095121_APPT_87.dat"); - // Wait to allow functions to ingest the file. The CRON timer trigger for the FileDiscovery function must be considered. + // Wait to allow functions to ingest the file await Task.Delay(45000); // Assert From cbb97a8ee75a1a1154c2ff7da635e3180a486e7b Mon Sep 17 00:00:00 2001 From: alex-clayton-1 Date: Thu, 12 Jun 2025 10:59:44 +0100 Subject: [PATCH 12/18] test: Updated readme --- compose.yaml | 2 -- tests/ServiceLayer.IntegrationTests/README.md | 10 ++++++++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/compose.yaml b/compose.yaml index 6095421..7cbeb31 100644 --- a/compose.yaml +++ b/compose.yaml @@ -108,8 +108,6 @@ services: ports: - "1433:1433" user: "root" - # volumes: - # - db-data:/var/opt/mssql healthcheck: test: [ diff --git a/tests/ServiceLayer.IntegrationTests/README.md b/tests/ServiceLayer.IntegrationTests/README.md index 18864ed..8d7f393 100644 --- a/tests/ServiceLayer.IntegrationTests/README.md +++ b/tests/ServiceLayer.IntegrationTests/README.md @@ -1,4 +1,10 @@ -The integration tests require the following environment variables to run: +# Integration Tests + +The integration tests start up docker containers using [compose.yaml](../../compose.yaml) and provide them with the environment variables defined in [.env.tests](.env.tests). Once the containers are up, the integration tests are executed, after the tests have finished, the containers are stopped. + +## How to run the tests + +To run the integration tests, you also need to pass the following environment variables as arguments when executing `dotnet test`: - AZURITE_ACCOUNT_KEY - AZURITE_ACCOUNT_NAME - AZURITE_BLOB_PORT @@ -7,7 +13,7 @@ The integration tests require the following environment variables to run: - MESH_BLOB_CONTAINER_NAME - DATABASE_CONNECTION_STRING -They can be passed as arguments like so +E.g. ```sh dotnet test \ -e AZURITE_ACCOUNT_KEY="Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw==" \ From 0f75658f94bc7b17adc65af2ca8e108bcebf1192 Mon Sep 17 00:00:00 2001 From: alex-clayton-1 Date: Thu, 12 Jun 2025 13:01:46 +0100 Subject: [PATCH 13/18] docs: Updated readme --- tests/ServiceLayer.IntegrationTests/README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/ServiceLayer.IntegrationTests/README.md b/tests/ServiceLayer.IntegrationTests/README.md index 8d7f393..621c7c5 100644 --- a/tests/ServiceLayer.IntegrationTests/README.md +++ b/tests/ServiceLayer.IntegrationTests/README.md @@ -5,6 +5,7 @@ The integration tests start up docker containers using [compose.yaml](../../comp ## How to run the tests To run the integration tests, you also need to pass the following environment variables as arguments when executing `dotnet test`: + - AZURITE_ACCOUNT_KEY - AZURITE_ACCOUNT_NAME - AZURITE_BLOB_PORT @@ -14,6 +15,7 @@ To run the integration tests, you also need to pass the following environment va - DATABASE_CONNECTION_STRING E.g. + ```sh dotnet test \ -e AZURITE_ACCOUNT_KEY="Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw==" \ From 81aee89dce76c18f7ab3def85646be3e0651279f Mon Sep 17 00:00:00 2001 From: alex-clayton-1 Date: Thu, 12 Jun 2025 13:06:45 +0100 Subject: [PATCH 14/18] ci: Updated unit.sh so that it doesn't attempt to run the integration tests --- scripts/tests/unit.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/tests/unit.sh b/scripts/tests/unit.sh index 2696f20..26257e3 100755 --- a/scripts/tests/unit.sh +++ b/scripts/tests/unit.sh @@ -7,7 +7,7 @@ if [[ "${1:-}" == "--no-build" ]]; then fi COVERAGE_DIR="coverage" -TEST_PROJECTS=$(find tests -name '*.csproj') +TEST_PROJECTS=$(find tests -name '*.csproj' -not -name "ServiceLayer.IntegrationTests.csproj") rm -rf "$COVERAGE_DIR" mkdir -p "$COVERAGE_DIR" From e4c7fd4622818cfe7f8788d65a5758f56914a106 Mon Sep 17 00:00:00 2001 From: alex-clayton-1 Date: Thu, 12 Jun 2025 13:17:32 +0100 Subject: [PATCH 15/18] Reverted unnecessary changes to ServiceLayer.Mesh.Tests.csproj --- tests/ServiceLayer.Mesh.Tests/ServiceLayer.Mesh.Tests.csproj | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tests/ServiceLayer.Mesh.Tests/ServiceLayer.Mesh.Tests.csproj b/tests/ServiceLayer.Mesh.Tests/ServiceLayer.Mesh.Tests.csproj index 92f4669..12c8eaf 100644 --- a/tests/ServiceLayer.Mesh.Tests/ServiceLayer.Mesh.Tests.csproj +++ b/tests/ServiceLayer.Mesh.Tests/ServiceLayer.Mesh.Tests.csproj @@ -18,7 +18,6 @@ - @@ -26,7 +25,7 @@ - + PreserveNewest From 96206154994c79452704c1116eb18907f4d14a96 Mon Sep 17 00:00:00 2001 From: alex-clayton-1 Date: Thu, 12 Jun 2025 13:41:36 +0100 Subject: [PATCH 16/18] test: Added submodule for mesh-sandbox --- .gitmodules | 5 ++++- compose.yaml | 7 +------ tests/mesh-sandbox | 1 + 3 files changed, 6 insertions(+), 7 deletions(-) create mode 160000 tests/mesh-sandbox diff --git a/.gitmodules b/.gitmodules index 5c6205a..4deb995 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,5 +1,8 @@ [submodule "src/dotnet-mesh-client"] - # path = src/Shared/dotnet-mesh-client path = src/dotnet-mesh-client url = https://github.com/NHSDigital/dotnet-mesh-client.git branch = main +[submodule "tests/mesh-sandbox"] + path = tests/mesh-sandbox + url = https://github.com/NHSDigital/mesh-sandbox + branch = main diff --git a/compose.yaml b/compose.yaml index 7cbeb31..db33be7 100644 --- a/compose.yaml +++ b/compose.yaml @@ -138,11 +138,9 @@ services: networks: - backend - # Clone the mesh sandbox repo so that it is in the same directory as dtos-service-layer - # https://github.com/NHSDigital/mesh-sandbox mesh-sandbox: container_name: mesh-sandbox - build: ../mesh-sandbox/ + build: tests/mesh-sandbox/ ports: - "8700:80" deploy: @@ -168,9 +166,6 @@ networks: volumes: azurite-data: name: azurite-data - db-data: - name: db-data - driver: local mesh-config-data: name: mesh-config-data driver: local diff --git a/tests/mesh-sandbox b/tests/mesh-sandbox new file mode 160000 index 0000000..9282e95 --- /dev/null +++ b/tests/mesh-sandbox @@ -0,0 +1 @@ +Subproject commit 9282e957e853c64c85053124e8f37252f74fb156 From 563de27e72a1ebea738ad258e1ec69695ac7b470 Mon Sep 17 00:00:00 2001 From: alex-clayton-1 Date: Thu, 12 Jun 2025 13:42:14 +0100 Subject: [PATCH 17/18] test: Removed unneccessary project reference --- .../ServiceLayer.IntegrationTests.csproj | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/ServiceLayer.IntegrationTests/ServiceLayer.IntegrationTests.csproj b/tests/ServiceLayer.IntegrationTests/ServiceLayer.IntegrationTests.csproj index 187409b..37e8311 100644 --- a/tests/ServiceLayer.IntegrationTests/ServiceLayer.IntegrationTests.csproj +++ b/tests/ServiceLayer.IntegrationTests/ServiceLayer.IntegrationTests.csproj @@ -18,7 +18,6 @@ - From 717c215915134b4f80a946c26a517721b59e5e31 Mon Sep 17 00:00:00 2001 From: alex-clayton-1 Date: Thu, 12 Jun 2025 14:07:40 +0100 Subject: [PATCH 18/18] refactor: Made HealthCheckFunction class static --- src/ServiceLayer.Mesh/Functions/HealthCheckFunction.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ServiceLayer.Mesh/Functions/HealthCheckFunction.cs b/src/ServiceLayer.Mesh/Functions/HealthCheckFunction.cs index f8beb31..3cd9f09 100644 --- a/src/ServiceLayer.Mesh/Functions/HealthCheckFunction.cs +++ b/src/ServiceLayer.Mesh/Functions/HealthCheckFunction.cs @@ -4,9 +4,9 @@ namespace ServiceLayer.Mesh.Functions; -public class HealthCheckFunction +public static class HealthCheckFunction { - [Function("HealthCheck")] + [Function("HealthCheckFunction")] public static HttpResponseData Run([HttpTrigger(AuthorizationLevel.Anonymous, "get", Route = "health")] HttpRequestData req) { return req.CreateResponse(HttpStatusCode.OK);