Skip to content

Commit 6402da2

Browse files
committed
Refactor integration tests
Signed-off-by: Victor Chang <[email protected]>
1 parent d9be64b commit 6402da2

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

56 files changed

+4000
-3871
lines changed
Lines changed: 283 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,283 @@
1+
/*
2+
* Copyright 2022 MONAI Consortium
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
using System.Globalization;
18+
using System.Text;
19+
using System.Text.Json;
20+
using System.Text.Json.Nodes;
21+
using System.Xml;
22+
using Ardalis.GuardClauses;
23+
using FellowOakDicom;
24+
using FellowOakDicom.Serialization;
25+
using Minio;
26+
using Monai.Deploy.InformaticsGateway.Configuration;
27+
using Monai.Deploy.InformaticsGateway.Integration.Test.Drivers;
28+
using Monai.Deploy.InformaticsGateway.Integration.Test.Hooks;
29+
using Monai.Deploy.Messaging.Events;
30+
using Monai.Deploy.Messaging.Messages;
31+
using TechTalk.SpecFlow.Infrastructure;
32+
33+
namespace Monai.Deploy.InformaticsGateway.Integration.Test.Common
34+
{
35+
internal class Assertions
36+
{
37+
private readonly Configurations _configurations;
38+
private readonly InformaticsGatewayConfiguration _options;
39+
private readonly ISpecFlowOutputHelper _outputHelper;
40+
41+
public Assertions(Configurations configurations, InformaticsGatewayConfiguration options, ISpecFlowOutputHelper outputHelper)
42+
{
43+
_configurations = configurations ?? throw new ArgumentNullException(nameof(configurations));
44+
_options = options ?? throw new ArgumentNullException(nameof(options));
45+
_outputHelper = outputHelper ?? throw new ArgumentNullException(nameof(outputHelper));
46+
}
47+
48+
internal async Task ShouldHaveUploadedDicomDataToMinio(IReadOnlyList<Message> messages, Dictionary<string, string> fileHashes)
49+
{
50+
Guard.Against.Null(messages);
51+
Guard.Against.NullOrEmpty(fileHashes);
52+
53+
var minioClient = GetMinioClient();
54+
55+
foreach (var message in messages)
56+
{
57+
var request = message.ConvertTo<WorkflowRequestEvent>();
58+
foreach (var file in request.Payload)
59+
{
60+
var dicomValidationKey = string.Empty;
61+
62+
var getObjectArgs = new GetObjectArgs()
63+
.WithBucket(request.Bucket)
64+
.WithObject($"{request.PayloadId}/{file.Path}")
65+
.WithCallbackStream((stream) =>
66+
{
67+
using var memoryStream = new MemoryStream();
68+
stream.CopyTo(memoryStream);
69+
memoryStream.Position = 0;
70+
var dicomFile = DicomFile.Open(memoryStream);
71+
dicomValidationKey = dicomFile.GenerateFileName();
72+
fileHashes.Should().ContainKey(dicomValidationKey).WhoseValue.Should().Be(dicomFile.CalculateHash());
73+
});
74+
await minioClient.GetObjectAsync(getObjectArgs);
75+
76+
var getMetadataObjectArgs = new GetObjectArgs()
77+
.WithBucket(request.Bucket)
78+
.WithObject($"{request.PayloadId}/{file.Metadata}")
79+
.WithCallbackStream((stream) =>
80+
{
81+
using var memoryStream = new MemoryStream();
82+
stream.CopyTo(memoryStream);
83+
var json = Encoding.UTF8.GetString(memoryStream.ToArray());
84+
85+
var dicomFileFromJson = DicomJson.ConvertJsonToDicom(json);
86+
var key = dicomFileFromJson.GenerateFileName();
87+
key.Should().Be(dicomValidationKey);
88+
});
89+
await minioClient.GetObjectAsync(getMetadataObjectArgs);
90+
}
91+
}
92+
}
93+
94+
internal async Task ShouldHaveUploadedFhirDataToMinio(IReadOnlyList<Message> messages, Dictionary<string, string> fhirData)
95+
{
96+
Guard.Against.Null(messages);
97+
98+
var minioClient = GetMinioClient();
99+
100+
foreach (var message in messages)
101+
{
102+
message.ApplicationId.Should().Be(MessageBrokerConfiguration.InformaticsGatewayApplicationId);
103+
var request = message.ConvertTo<WorkflowRequestEvent>();
104+
request.Should().NotBeNull();
105+
request.FileCount.Should().Be(1);
106+
107+
foreach (var file in request.Payload)
108+
{
109+
var getObjectArgs = new GetObjectArgs()
110+
.WithBucket(request.Bucket)
111+
.WithObject($"{request.PayloadId}/{file.Path}")
112+
.WithCallbackStream((stream) =>
113+
{
114+
using var memoryStream = new MemoryStream();
115+
stream.CopyTo(memoryStream);
116+
memoryStream.Position = 0;
117+
var data = Encoding.UTF8.GetString(memoryStream.ToArray());
118+
data.Should().NotBeNullOrWhiteSpace();
119+
120+
var incomingFilename = Path.GetFileName(file.Path);
121+
var storedFileKey = fhirData.Keys.FirstOrDefault(p => p.EndsWith(incomingFilename));
122+
storedFileKey.Should().NotBeNull();
123+
124+
_outputHelper.WriteLine($"Validating file {storedFileKey}...");
125+
if (incomingFilename.EndsWith(".json", true, CultureInfo.InvariantCulture))
126+
{
127+
ValidateJson(fhirData[storedFileKey], data);
128+
}
129+
else
130+
{
131+
ValidateXml(fhirData[storedFileKey], data);
132+
}
133+
});
134+
await minioClient.GetObjectAsync(getObjectArgs);
135+
}
136+
}
137+
}
138+
139+
internal async Task ShouldHaveUploadedHl7ataToMinio(IReadOnlyList<Message> messages)
140+
{
141+
Guard.Against.Null(messages);
142+
143+
var minioClient = GetMinioClient();
144+
145+
foreach (var message in messages)
146+
{
147+
var request = message.ConvertTo<WorkflowRequestEvent>();
148+
var listOjbectsArgs = new ListObjectsArgs()
149+
.WithBucket(request.Bucket)
150+
.WithPrefix(request.PayloadId.ToString())
151+
.WithRecursive(true);
152+
var results = minioClient.ListObjectsAsync(listOjbectsArgs);
153+
results.Subscribe(item =>
154+
{
155+
_outputHelper.WriteLine($"File => {item.Key}...");
156+
},
157+
exception =>
158+
{
159+
_outputHelper.WriteLine($"Error listing files {exception.Message}");
160+
});
161+
162+
foreach (var file in request.Payload)
163+
{
164+
_outputHelper.WriteLine($"Verifying file => {request.PayloadId}/{file.Path}...");
165+
var getObjectArgs = new GetObjectArgs()
166+
.WithBucket(request.Bucket)
167+
.WithObject($"{request.PayloadId}/{file.Path}")
168+
.WithCallbackStream((stream) =>
169+
{
170+
using var memoryStream = new MemoryStream();
171+
stream.CopyTo(memoryStream);
172+
memoryStream.Position = 0;
173+
var data = Encoding.UTF8.GetString(memoryStream.ToArray());
174+
175+
var hl7Message = new HL7.Dotnetcore.Message(data);
176+
hl7Message.ParseMessage().Should().BeTrue();
177+
});
178+
await minioClient.GetObjectAsync(getObjectArgs);
179+
}
180+
}
181+
}
182+
183+
internal void ShouldHaveCorrectNumberOfWorkflowRequestMessages(DataProvider dataProvider, IReadOnlyList<Message> messages, int count)
184+
{
185+
Guard.Against.Null(dataProvider);
186+
Guard.Against.Null(messages);
187+
188+
messages.Should().NotBeNullOrEmpty().And.HaveCount(count);
189+
foreach (var message in messages)
190+
{
191+
message.ApplicationId.Should().Be(MessageBrokerConfiguration.InformaticsGatewayApplicationId);
192+
var request = message.ConvertTo<WorkflowRequestEvent>();
193+
request.Should().NotBeNull();
194+
request.FileCount.Should().Be((dataProvider.DicomSpecs.NumberOfExpectedFiles(dataProvider.StudyGrouping)));
195+
196+
if (dataProvider.Workflows is not null)
197+
{
198+
request.Workflows.Should().Equal(dataProvider.Workflows);
199+
}
200+
}
201+
}
202+
internal void ShouldHaveCorrectNumberOfWorkflowRequestMessagesAndAcrRequest(DataProvider dataProvider, IReadOnlyList<Message> messages, int count)
203+
{
204+
Guard.Against.Null(dataProvider);
205+
Guard.Against.Null(messages);
206+
207+
messages.Should().NotBeNullOrEmpty().And.HaveCount(count);
208+
209+
foreach (var message in messages)
210+
{
211+
message.ApplicationId.Should().Be(MessageBrokerConfiguration.InformaticsGatewayApplicationId);
212+
var request = message.ConvertTo<WorkflowRequestEvent>();
213+
request.Should().NotBeNull();
214+
request.FileCount.Should().Be(dataProvider.DicomSpecs.FileCount);
215+
request.Workflows.Should().Equal(dataProvider.AcrRequest.Application.Id);
216+
}
217+
}
218+
219+
internal void ShouldHaveCorrectNumberOfWorkflowRequestMessagesAndHl7Messages(Hl7Messages hL7Specs, IReadOnlyList<Message> messages, int count)
220+
{
221+
Guard.Against.Null(hL7Specs);
222+
Guard.Against.Null(messages);
223+
224+
messages.Should().NotBeNullOrEmpty().And.HaveCount(count);
225+
226+
foreach (var message in messages)
227+
{
228+
message.ApplicationId.Should().Be(MessageBrokerConfiguration.InformaticsGatewayApplicationId);
229+
var request = message.ConvertTo<WorkflowRequestEvent>();
230+
request.Should().NotBeNull();
231+
request.FileCount.Should().Be(hL7Specs.Files.Count);
232+
}
233+
}
234+
235+
private MinioClient GetMinioClient() => new MinioClient()
236+
.WithEndpoint(_options.Storage.Settings["endpoint"])
237+
.WithCredentials(_options.Storage.Settings["accessKey"], _options.Storage.Settings["accessToken"])
238+
.Build();
239+
240+
private void ValidateXml(string expected, string actual)
241+
{
242+
expected = FormatXml(expected);
243+
expected.Should().Be(actual);
244+
}
245+
246+
private string FormatXml(string xml)
247+
{
248+
var xmlDocument = new XmlDocument();
249+
xmlDocument.LoadXml(xml);
250+
var sb = new StringBuilder();
251+
using (var xmlWriter = XmlWriter.Create(sb, new XmlWriterSettings { Encoding = Encoding.UTF8, Indent = true }))
252+
{
253+
xmlDocument.Save(xmlWriter);
254+
}
255+
return sb.ToString();
256+
}
257+
258+
private void ValidateJson(string expected, string actual)
259+
{
260+
expected = FormatJson(expected);
261+
expected.Should().Be(actual);
262+
}
263+
264+
private string FormatJson(string expected)
265+
{
266+
var jsonDoc = JsonNode.Parse(expected);
267+
return jsonDoc.ToJsonString(new JsonSerializerOptions { WriteIndented = true });
268+
}
269+
270+
internal void ShoulddHaveCorrectNumberOfAckMessages(Dictionary<string, string> responses)
271+
{
272+
foreach (var file in responses.Keys)
273+
{
274+
_outputHelper.WriteLine($"Verifying acknowledgement for {file}...");
275+
var message = new HL7.Dotnetcore.Message(responses[file]);
276+
message.ParseMessage();
277+
var segment = message.DefaultSegment("MSH");
278+
_outputHelper.WriteLine($"ACK Value= {segment.Value}...");
279+
segment.Fields(9).Value.Should().Be("ACK");
280+
}
281+
}
282+
}
283+
}

0 commit comments

Comments
 (0)