/
ArtifactSummaryTests.cs
293 lines (239 loc) · 13.3 KB
/
ArtifactSummaryTests.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
using Hl7.Fhir.ElementModel;
using Hl7.Fhir.Model;
using Hl7.Fhir.Serialization;
using Hl7.Fhir.Specification.Source;
using Hl7.Fhir.Specification.Summary;
using Hl7.Fhir.Utility;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
using System.Diagnostics;
using System.IO;
using System.IO.Compression;
using System.Linq;
namespace Hl7.Fhir.Specification.Tests
{
[TestClass]
public class ArtifactSummaryTests
{
[TestMethod]
public void TestPatientXmlSummary() => TestPatientSummary(@"TestData\TestPatient.xml");
[TestMethod]
public void TestPatientJsonSummary() => TestPatientSummary(@"TestData\TestPatient.json");
void TestPatientSummary(string path)
{
var summary = assertSummary(path);
Assert.AreEqual(ResourceType.Patient.GetLiteral(), summary.ResourceTypeName);
}
[TestMethod]
public void TestPatientXmlSummaryWithCustomHarvester()
=> TestPatientSummaryWithCustomHarvester(@"TestData\TestPatient.xml", "Donald");
[TestMethod]
public void TestPatientJsonSummaryWithCustomHarvester()
=> TestPatientSummaryWithCustomHarvester(@"TestData\TestPatient.json", "Chalmers");
void TestPatientSummaryWithCustomHarvester(string path, params string[] expectedNames)
{
// Combine default harvesters and custom harvester
var harvesters = new ArtifactSummaryHarvester[ArtifactSummaryGenerator.ConformanceHarvesters.Length + 1];
Array.Copy(ArtifactSummaryGenerator.ConformanceHarvesters, harvesters, ArtifactSummaryGenerator.ConformanceHarvesters.Length);
harvesters[ArtifactSummaryGenerator.ConformanceHarvesters.Length] = HarvestPatientSummary;
var summary = assertSummary(path, harvesters);
Assert.AreEqual(ResourceType.Patient.GetLiteral(), summary.ResourceTypeName);
var familyNames = summary.GetValueOrDefault<string[]>(PatientFamilyNameKey);
Assert.IsNotNull(familyNames);
Assert.AreEqual(1, familyNames.Length);
Assert.IsTrue(expectedNames.SequenceEqual(familyNames));
}
// Custom artifact summary harvester implementation to extract family name(s) from Patient resources
const string PatientFamilyNameKey = "Patient.name.family";
static bool HarvestPatientSummary(IElementNavigator nav, ArtifactSummaryPropertyBag properties)
{
if (properties.GetTypeName() == ResourceType.Patient.GetLiteral())
{
nav.HarvestValues(properties, PatientFamilyNameKey, "name", "family");
return true;
}
return false;
}
[TestMethod]
public void TestValueSetXmlSummary()
{
const string path = @"TestData\validation\SectionTitles.valueset.xml";
var summary = assertSummary(path);
// Common properties
Assert.AreEqual(ResourceType.ValueSet.GetLiteral(), summary.ResourceTypeName);
Assert.IsTrue(summary.ResourceType == ResourceType.ValueSet);
// Conformance resource properties
Assert.IsNotNull(summary.GetConformanceCanonicalUrl());
Assert.AreEqual(@"http://example.org/ValueSet/SectionTitles", summary.GetConformanceCanonicalUrl());
Assert.AreEqual("MainBundle Section title codes", summary.GetConformanceName());
Assert.AreEqual(ConformanceResourceStatus.Draft.GetLiteral(), summary.GetConformanceStatus());
Assert.IsNotNull(summary.GetValueSetSystem());
}
[TestMethod]
public void TestProfilesTypesJson()
{
const string path = @"TestData\profiles-types.json";
var summaries = ArtifactSummaryGenerator.Generate(path);
Assert.IsNotNull(summaries);
Assert.AreNotEqual(0, summaries.Count);
for (int i = 0; i < summaries.Count; i++)
{
var summary = summaries[i];
Assert.IsFalse(summary.IsFaulted);
// Common properties
Assert.AreEqual(path, summary.Origin);
var fi = new FileInfo(path);
Assert.AreEqual(fi.Length, summary.FileSize);
Assert.AreEqual(fi.LastWriteTimeUtc, summary.LastModified);
Assert.AreEqual(ResourceType.StructureDefinition.GetLiteral(), summary.ResourceTypeName);
Assert.IsTrue(summary.ResourceType == ResourceType.StructureDefinition);
// Conformance resource properties
Assert.IsNotNull(summary.GetConformanceCanonicalUrl());
Assert.IsTrue(summary.GetConformanceCanonicalUrl().ToString().StartsWith("http://hl7.org/fhir/StructureDefinition/"));
Assert.IsNotNull(summary.GetConformanceName());
Assert.AreEqual(ConformanceResourceStatus.Draft.GetLiteral(), summary.GetConformanceStatus());
//Debug.WriteLine($"{summary.ResourceType} | {summary.Canonical()} | {summary.Name()}");
// StructureDefinition properties
Assert.IsNotNull(summary.GetStructureDefinitionFhirVersion());
Assert.AreEqual(ModelInfo.Version, summary.GetStructureDefinitionFhirVersion());
Assert.AreEqual(StructureDefinition.StructureDefinitionKind.Datatype.GetLiteral(), summary.GetStructureDefinitionKind());
// If this is a constraining StructDef, then Base should also be specified
Assert.IsTrue(summary.GetStructureDefinitionConstrainedType() == null || summary.GetStructureDefinitionBase() != null);
// [WMR 20180725] Also harvest root element definition text
// [WMR 20180801] Disabled; included version of profiles-types.json does NOT contain definitions...
// var rootDefinition = summary.GetStructureDefinitionRootDefinition();
// Assert.IsNotNull(rootDefinition);
}
}
[TestMethod]
public void TestProfilesResourcesXml()
{
const string path = @"TestData\profiles-resources.xml";
var summaries = ArtifactSummaryGenerator.Generate(path);
Assert.IsNotNull(summaries);
Assert.AreNotEqual(0, summaries.Count);
for (int i = 0; i < summaries.Count; i++)
{
var summary = summaries[i];
Assert.IsFalse(summary.IsFaulted);
// Common properties
Assert.AreEqual(path, summary.Origin);
var fi = new FileInfo(path);
Assert.AreEqual(fi.Length, summary.FileSize);
Assert.AreEqual(fi.LastWriteTimeUtc, summary.LastModified);
if (StringComparer.Ordinal.Equals(ResourceType.StructureDefinition.GetLiteral(), summary.ResourceTypeName))
{
Assert.IsTrue(summary.ResourceType == ResourceType.StructureDefinition);
// Conformance resource properties
Assert.IsNotNull(summary.GetConformanceCanonicalUrl());
Assert.IsTrue(summary.GetConformanceCanonicalUrl().ToString().StartsWith("http://hl7.org/fhir/StructureDefinition/"));
Assert.IsNotNull(summary.GetConformanceName());
Assert.AreEqual(ConformanceResourceStatus.Draft.GetLiteral(), summary.GetConformanceStatus());
//Debug.WriteLine($"{summary.ResourceType} | {summary.Canonical()} | {summary.Name()}");
// StructureDefinition properties
Assert.IsNotNull(summary.GetStructureDefinitionFhirVersion());
Assert.AreEqual(ModelInfo.Version, summary.GetStructureDefinitionFhirVersion());
Assert.AreEqual(StructureDefinition.StructureDefinitionKind.Resource.GetLiteral(), summary.GetStructureDefinitionKind());
// If this is a constraining StructDef, then Base should also be specified
Assert.IsTrue(summary.GetStructureDefinitionConstrainedType() == null || summary.GetStructureDefinitionBase() != null);
// [WMR 20171218] Maturity Level extension
Assert.IsNotNull(summary.GetStructureDefinitionMaturityLevel());
// [WMR 20180725] Also harvest root element definition text
var rootDefinition = summary.GetStructureDefinitionRootDefinition();
Assert.IsNotNull(rootDefinition);
}
}
}
ArtifactSummary assertSummary(string path, params ArtifactSummaryHarvester[] harvesters)
{
if (harvesters == null || harvesters.Length == 0)
{
harvesters = ArtifactSummaryGenerator.ConformanceHarvesters;
}
var summaries = ArtifactSummaryGenerator.Generate(path, harvesters);
Assert.IsNotNull(summaries);
Assert.AreEqual(1, summaries.Count);
var summary = summaries[0];
Assert.IsFalse(summary.IsFaulted);
Assert.AreEqual(path, summary.Origin);
var fi = new FileInfo(path);
Assert.AreEqual(fi.Length, summary.FileSize);
Assert.AreEqual(fi.LastWriteTimeUtc, summary.LastModified);
return summary;
}
#if NET_COMPRESSION
[TestMethod]
public void TestZipSummary()
{
var source = ZipSource.CreateValidationSource();
var summaries = source.ListSummaries().ToList();
Assert.IsNotNull(summaries);
Assert.AreEqual(7155, summaries.Count);
Assert.AreEqual(552, summaries.OfResourceType(ResourceType.StructureDefinition).Count());
Assert.IsTrue(!summaries.Errors().Any());
}
[TestMethod]
public void TestLoadResourceFromZipSource()
{
// ZipSource extracts core ZIP archive to (temp) folder, then delegates to DirectorySource
// i.e. artifact summaries are harvested from files on disk
var source = ZipSource.CreateValidationSource();
var summaries = source.ListSummaries();
var patientUrl = ModelInfo.CanonicalUriForFhirCoreType(FHIRDefinedType.Patient);
var patientSummary = summaries.FindConformanceResources(patientUrl).FirstOrDefault();
Assert.IsNotNull(patientSummary);
Assert.AreEqual(ResourceType.StructureDefinition, patientSummary.ResourceType);
Assert.AreEqual(patientUrl, patientSummary.GetConformanceCanonicalUrl());
Assert.IsNotNull(patientSummary.Origin);
var patientStructure = source.LoadBySummary<StructureDefinition>(patientSummary);
Assert.IsNotNull(patientStructure);
}
[TestMethod]
public void TestLoadResourceFromZipStream()
{
// Harvest summaries and load artifact straight from core ZIP archive
// Use XmlNavigatorStream to navigate resources stored inside a zip file
// ZipDeflateStream does not support seeking (forward-only stream)
// Therefore this only works for the XmlNavigatorStream, as the ctor does NOT (need to) call Reset()
// JsonNavigatorStream cannot support zip streams; ctor needs to call Reset after scanning resourceType
ArtifactSummary corePatientSummary;
var corePatientUrl = ModelInfo.CanonicalUriForFhirCoreType(FHIRDefinedType.Patient);
string zipEntryName = "profiles-resources.xml";
// Generate summaries from core ZIP resource definitions (extract in memory)
using (var archive = ZipFile.Open(ZipSource.SpecificationZipFileName, ZipArchiveMode.Read))
{
var entry = archive.Entries.FirstOrDefault(e => e.Name == zipEntryName);
Assert.IsNotNull(entry);
using (var entryStream = entry.Open())
using (var navStream = new XmlNavigatorStream(entryStream))
{
var summaries = ArtifactSummaryGenerator.Generate(navStream);
Assert.IsNotNull(summaries);
corePatientSummary = summaries.FindConformanceResources(corePatientUrl).FirstOrDefault();
}
}
Assert.IsNotNull(corePatientSummary);
Assert.AreEqual(ResourceType.StructureDefinition, corePatientSummary.ResourceType);
Assert.AreEqual(corePatientUrl, corePatientSummary.GetConformanceCanonicalUrl());
// Load core Patient resource from ZIP (extract in memory)
using (var archive = ZipFile.Open(ZipSource.SpecificationZipFileName, ZipArchiveMode.Read))
{
var entry = archive.Entries.FirstOrDefault(e => e.Name == zipEntryName);
using (var entryStream = entry.Open())
using (var navStream = new XmlNavigatorStream(entryStream))
{
var nav = navStream.Current;
if (nav != null)
{
// Parse target resource from navigator
var parser = new BaseFhirParser();
var corePatient = parser.Parse<StructureDefinition>(nav);
Assert.IsNotNull(corePatient);
Assert.AreEqual(corePatientUrl, corePatient.Url);
}
}
}
}
#endif
}
}