From 8a831a9e45a500d1e036efcbb2c4205fbf834ee7 Mon Sep 17 00:00:00 2001 From: Grahame Grieve Date: Tue, 12 Nov 2024 13:24:09 +1030 Subject: [PATCH] Start testing metadata in tx tests, and consequent bugs and library upgrades for that (patternMode in ComparisonUtilities) --- .../txClient/TerminologyClientR2.java | 5 + .../txClient/TerminologyClientR3.java | 5 + .../txClient/TerminologyClientR4.java | 7 +- .../r4/utils/client/FHIRToolingClient.java | 36 +-- .../fhir/r4b/context/TextClientLogger.java | 6 +- .../client/ITerminologyClient.java | 1 + .../client/TerminologyClientR5.java | 5 + .../fhir/r5/test/utils/CompareUtilities.java | 181 ++++++++++---- .../r5/elementmodel/LanguageUtilsTest.java | 2 +- .../org/hl7/fhir/r5/sql/SQLOnFhirTests.java | 2 +- .../hl7/fhir/r5/test/GraphQLEngineTests.java | 2 +- .../r5/test/NarrativeGenerationTests.java | 4 +- .../org/hl7/fhir/r5/test/ParsingTests.java | 2 +- .../fhir/r5/test/ResourceToElementTest.java | 2 +- .../java/org/hl7/fhir/r5/test/VocabTests.java | 2 +- .../test/profiles/GeneratedPEModelTest.java | 2 +- .../hl7/fhir/r5/test/profiles/PETests.java | 2 +- .../r5/test/utils/CompareUtilitiesTests.java | 4 +- .../json/actualExtraProperty.json.error | 2 +- .../special/TxServiceTestHelper.java | 4 +- .../hl7/fhir/validation/special/TxTester.java | 112 ++++++--- .../validation/special/TxTesterScrubbers.java | 11 + .../validation/special/TxTesterSorters.java | 222 +++++++++++++++++- .../comparison/tests/ComparisonTests.java | 2 +- .../tests/LocalTerminologyServiceTests.java | 28 ++- .../tests/TerminologyServiceTests.java | 9 +- .../tests/StructureMappingTests.java | 4 +- 27 files changed, 521 insertions(+), 143 deletions(-) diff --git a/org.hl7.fhir.convertors/src/main/java/org/hl7/fhir/convertors/txClient/TerminologyClientR2.java b/org.hl7.fhir.convertors/src/main/java/org/hl7/fhir/convertors/txClient/TerminologyClientR2.java index f005cdb359..5cbc96328f 100644 --- a/org.hl7.fhir.convertors/src/main/java/org/hl7/fhir/convertors/txClient/TerminologyClientR2.java +++ b/org.hl7.fhir.convertors/src/main/java/org/hl7/fhir/convertors/txClient/TerminologyClientR2.java @@ -163,6 +163,11 @@ public CapabilityStatement getCapabilitiesStatementQuick() throws FHIRException return (CapabilityStatement) VersionConvertorFactory_10_50.convertResource(client.getConformanceStatementQuick()); } + @Override + public CapabilityStatement getCapabilitiesStatement() throws FHIRException { + return (CapabilityStatement) VersionConvertorFactory_10_50.convertResource(client.getConformanceStatement()); + } + @Override public Parameters lookupCode(Map params) throws FHIRException { return (Parameters) VersionConvertorFactory_10_50.convertResource(client.lookupCode(params)); diff --git a/org.hl7.fhir.convertors/src/main/java/org/hl7/fhir/convertors/txClient/TerminologyClientR3.java b/org.hl7.fhir.convertors/src/main/java/org/hl7/fhir/convertors/txClient/TerminologyClientR3.java index 792cb04efc..84f51cd387 100644 --- a/org.hl7.fhir.convertors/src/main/java/org/hl7/fhir/convertors/txClient/TerminologyClientR3.java +++ b/org.hl7.fhir.convertors/src/main/java/org/hl7/fhir/convertors/txClient/TerminologyClientR3.java @@ -153,6 +153,11 @@ public CapabilityStatement getCapabilitiesStatementQuick() throws FHIRException return (CapabilityStatement) VersionConvertorFactory_30_50.convertResource(client.getCapabilitiesStatementQuick()); } + @Override + public CapabilityStatement getCapabilitiesStatement() throws FHIRException { + return (CapabilityStatement) VersionConvertorFactory_30_50.convertResource(client.getCapabilitiesStatement()); + } + @Override public Parameters lookupCode(Map params) throws FHIRException { return (Parameters) VersionConvertorFactory_30_50.convertResource(client.lookupCode(params)); diff --git a/org.hl7.fhir.convertors/src/main/java/org/hl7/fhir/convertors/txClient/TerminologyClientR4.java b/org.hl7.fhir.convertors/src/main/java/org/hl7/fhir/convertors/txClient/TerminologyClientR4.java index 7e40c994bc..313de8c67b 100644 --- a/org.hl7.fhir.convertors/src/main/java/org/hl7/fhir/convertors/txClient/TerminologyClientR4.java +++ b/org.hl7.fhir.convertors/src/main/java/org/hl7/fhir/convertors/txClient/TerminologyClientR4.java @@ -64,7 +64,7 @@ public EnumSet getAllowedVersions() { } public FhirPublication getActualVersion() { - return FhirPublication.STU3; + return FhirPublication.R4; } @@ -177,6 +177,11 @@ public CapabilityStatement getCapabilitiesStatementQuick() throws FHIRException return (CapabilityStatement) VersionConvertorFactory_40_50.convertResource(client.getCapabilitiesStatementQuick()); } + @Override + public CapabilityStatement getCapabilitiesStatement() throws FHIRException { + return (CapabilityStatement) VersionConvertorFactory_40_50.convertResource(client.getCapabilitiesStatement()); + } + @Override public Parameters lookupCode(Map params) throws FHIRException { return (Parameters) VersionConvertorFactory_40_50.convertResource(client.lookupCode(params)); diff --git a/org.hl7.fhir.r4/src/main/java/org/hl7/fhir/r4/utils/client/FHIRToolingClient.java b/org.hl7.fhir.r4/src/main/java/org/hl7/fhir/r4/utils/client/FHIRToolingClient.java index 11451ad421..5495dca053 100644 --- a/org.hl7.fhir.r4/src/main/java/org/hl7/fhir/r4/utils/client/FHIRToolingClient.java +++ b/org.hl7.fhir.r4/src/main/java/org/hl7/fhir/r4/utils/client/FHIRToolingClient.java @@ -71,7 +71,6 @@ public class FHIRToolingClient extends FHIRBaseToolingClient { @Setter private ResourceFormat preferredResourceFormat; private int maxResultSetSize = -1;// _count - private CapabilityStatement capabilities; @Getter @Setter private Client client = new Client(); @@ -100,13 +99,6 @@ public void initialize(String baseServiceUrl) throws URISyntaxException { this.maxResultSetSize = -1; } - private void checkCapabilities() { - try { - capabilities = getCapabilitiesStatementQuick(); - } catch (Throwable e) { - } - } - public String getPreferredResourceFormat() { return preferredResourceFormat.getHeader(); } @@ -130,10 +122,10 @@ public TerminologyCapabilities getTerminologyCapabilities() { return capabilities; } - public CapabilityStatement getCapabilitiesStatement() { + public CapabilityStatement getCapabilitiesStatementQuick() { CapabilityStatement conformance = null; try { - conformance = (CapabilityStatement) client.issueGetResourceRequest(resourceAddress.resolveMetadataUri(false), + conformance = (CapabilityStatement) client.issueGetResourceRequest(resourceAddress.resolveMetadataUri(true), withVer(getPreferredResourceFormat(), "4.0"), generateHeaders(false), "CapabilitiesStatement", timeoutNormal).getReference(); } catch (Exception e) { throw new FHIRException("Error fetching the server's conformance statement", e); @@ -141,18 +133,15 @@ public CapabilityStatement getCapabilitiesStatement() { return conformance; } - public CapabilityStatement getCapabilitiesStatementQuick() throws EFhirClientException { - if (capabilities != null) - return capabilities; - try { - capabilities = (CapabilityStatement) client.issueGetResourceRequest(resourceAddress.resolveMetadataUri(true), - withVer(getPreferredResourceFormat(), "4.0"), generateHeaders(false), "CapabilitiesStatement-Quick", timeoutNormal) - .getReference(); - } catch (Exception e) { - throw new FHIRException("Error fetching the server's capability statement: " + e.getMessage(), e); - } - return capabilities; - } + public CapabilityStatement getCapabilitiesStatement() throws EFhirClientException { + try { + return (CapabilityStatement) client.issueGetResourceRequest(resourceAddress.resolveMetadataUri(false), + withVer(getPreferredResourceFormat(), "4.0"), generateHeaders(false), "CapabilitiesStatement-Quick", timeoutNormal) + .getReference(); + } catch (Exception e) { + throw new FHIRException("Error fetching the server's capability statement: " + e.getMessage(), e); + } + } public Resource read(String resourceClass, String id) {// TODO Change this to AddressableResource recordUse(); @@ -562,8 +551,7 @@ private Iterable generateHeaders(boolean hasBody) { } public String getServerVersion() { - checkCapabilities(); - return capabilities == null ? null : capabilities.getSoftware().getVersion(); + return getCapabilitiesStatementQuick().getSoftware().getVersion(); } public Bundle search(String type, String criteria) { diff --git a/org.hl7.fhir.r4b/src/main/java/org/hl7/fhir/r4b/context/TextClientLogger.java b/org.hl7.fhir.r4b/src/main/java/org/hl7/fhir/r4b/context/TextClientLogger.java index fa29392ae0..c7a680e639 100644 --- a/org.hl7.fhir.r4b/src/main/java/org/hl7/fhir/r4b/context/TextClientLogger.java +++ b/org.hl7.fhir.r4b/src/main/java/org/hl7/fhir/r4b/context/TextClientLogger.java @@ -61,11 +61,11 @@ public void logRequest(String method, String url, List headers, byte[] b file.println("\r\n--- " + id + " -----------------\r\nRequest: \r\n"); file.println(method + " " + url + " HTTP/1.0"); for (String s : headers) - file.println(Utilities.escapeXml(s)); + file.println(s); if (body != null) { file.println(""); try { - file.println(Utilities.escapeXml(new String(body, "UTF-8"))); + file.println(new String(body, "UTF-8")); } catch (UnsupportedEncodingException e) { } } @@ -82,7 +82,7 @@ public void logResponse(String outcome, List headers, byte[] body, long if (body != null) { file.println(""); try { - file.println(Utilities.escapeXml(new String(body, "UTF-8"))); + file.println(new String(body, "UTF-8")); } catch (UnsupportedEncodingException e) { } } diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/terminologies/client/ITerminologyClient.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/terminologies/client/ITerminologyClient.java index 2be9473c00..172b9349e0 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/terminologies/client/ITerminologyClient.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/terminologies/client/ITerminologyClient.java @@ -60,6 +60,7 @@ public interface ITerminologyClient { ITerminologyClient setLogger(ToolingClientLogger txLog) throws FHIRException; int getRetryCount() throws FHIRException; ITerminologyClient setRetryCount(int retryCount) throws FHIRException; + CapabilityStatement getCapabilitiesStatement() throws FHIRException; CapabilityStatement getCapabilitiesStatementQuick() throws FHIRException; Parameters lookupCode(Map params) throws FHIRException; Parameters lookupCode(Parameters params) throws FHIRException; diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/terminologies/client/TerminologyClientR5.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/terminologies/client/TerminologyClientR5.java index b0f2f7b467..fd859b0e97 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/terminologies/client/TerminologyClientR5.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/terminologies/client/TerminologyClientR5.java @@ -165,6 +165,11 @@ public CapabilityStatement getCapabilitiesStatementQuick() { return client.getCapabilitiesStatementQuick(); } + @Override + public CapabilityStatement getCapabilitiesStatement() { + return client.getCapabilitiesStatement(); + } + @Override public Parameters lookupCode(Map params) { return client.lookupCode(params); diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/test/utils/CompareUtilities.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/test/utils/CompareUtilities.java index 2445a23d58..97e1f11586 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/test/utils/CompareUtilities.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/test/utils/CompareUtilities.java @@ -3,6 +3,7 @@ import org.apache.commons.codec.binary.Base64; import org.apache.commons.lang3.StringUtils; import org.hl7.fhir.exceptions.FHIRException; +import org.hl7.fhir.r5.model.Constants; import org.hl7.fhir.utilities.*; import org.hl7.fhir.utilities.filesystem.CSFile; import org.hl7.fhir.utilities.filesystem.ManagedFileAccess; @@ -27,6 +28,7 @@ import javax.xml.parsers.DocumentBuilderFactory; import java.io.*; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; import java.util.Map; @@ -34,12 +36,51 @@ public class CompareUtilities extends BaseTestingUtilities { private static final boolean SHOW_DIFF = false; private JsonObject externals; + private Map variables; + private boolean patternMode; + + public CompareUtilities() { + super(); + this.variables = new HashMap(); + } + + public CompareUtilities(JsonObject externals) { + super(); + this.externals = externals; + this.variables = new HashMap(); + } + + public CompareUtilities(JsonObject externals, Map variables) { + super(); + this.externals = externals; + this.variables = variables; + } + + /** + * in pattern mode, the comparison is only looking to find the expected properties. anything else is ignored + * @return + */ + public boolean isPatternMode() { + return patternMode; + } + + public CompareUtilities setPatternMode(boolean patternMode) { + this.patternMode = patternMode; + return this; + } public String createNotEqualMessage(String id, final String message, final String expected, final String actual) { + if (patternMode) { return new StringBuilder() - .append(message).append('\n') - .append("Expected:").append(presentExpected(expected)).append(" for "+id).append('\n') + .append(message).append(". ") + .append("Expected:").append(presentExpected(expected)).append(" for "+id).append(". ") .append("Actual :").append("\""+actual+"\"").toString(); + } else { + return new StringBuilder() + .append(message).append('\n') + .append("Expected:").append(presentExpected(expected)).append(" for "+id).append('\n') + .append("Actual :").append("\""+actual+"\"").toString(); + } } private String presentExpected(String expected) { @@ -64,8 +105,13 @@ private String presentExpected(String expected) { switch (expected) { case "$$" : return "$$"; case "$instant$": return "\"An Instant\""; + case "$date$": return "\"A date\""; case "$uuid$": return "\"A Uuid\""; + case "$string$": return "\"A string\""; case "$id$": return "\"An Id\""; + case "$url$": return "\"A URL\""; + case "$token$": return "\"A Token\""; + case "$version$": return variables.containsKey("version") ? variables.get("version") : "(anything)"; default: return "Unhandled template: "+expected; } } @@ -74,15 +120,13 @@ private String presentExpected(String expected) { } } - public static String checkXMLIsSame(String id, InputStream expected, InputStream actual) throws Exception { - CompareUtilities self = new CompareUtilities(); - String result = self.compareXml(id, expected, actual); + public String checkXMLIsSame(String id, InputStream expected, InputStream actual) throws Exception { + String result = compareXml(id, expected, actual); return result; } - public static String checkXMLIsSame(String id, String expected, String actual) throws Exception { - CompareUtilities self = new CompareUtilities(); - String result = self.compareXml(id, expected, actual); + public String checkXMLIsSame(String id, String expected, String actual) throws Exception { + String result = compareXml(id, expected, actual); if (result != null && SHOW_DIFF) { String diff = getDiffTool(); if (diff != null && ManagedFileAccess.file(diff).exists() || Utilities.isToken(diff)) { @@ -92,7 +136,7 @@ public static String checkXMLIsSame(String id, String expected, String actual) t return result; } - private static String getDiffTool() throws IOException { + private String getDiffTool() throws IOException { if (FhirSettings.hasDiffToolPath()) { return FhirSettings.getDiffToolPath(); } else if (System.getenv("ProgramFiles") != null) { @@ -219,14 +263,12 @@ private Document loadXml(InputStream fn) throws Exception { return builder.parse(fn); } - public static String checkJsonSrcIsSame(String id, String expected, String actual, JsonObject externals) throws FileNotFoundException, IOException { - return checkJsonSrcIsSame(id, expected, actual, true, externals); + public String checkJsonSrcIsSame(String id, String expected, String actual) throws FileNotFoundException, IOException { + return checkJsonSrcIsSame(id, expected, actual, true); } - public static String checkJsonSrcIsSame(String id, String expectedString, String actualString, boolean showDiff, JsonObject externals) throws FileNotFoundException, IOException { - CompareUtilities self = new CompareUtilities(); - self.externals = externals; - String result = self.compareJsonSrc(id, expectedString, actualString); + public String checkJsonSrcIsSame(String id, String expectedString, String actualString, boolean showDiff) throws FileNotFoundException, IOException { + String result = compareJsonSrc(id, expectedString, actualString); if (result != null && SHOW_DIFF && showDiff) { String diff = null; if (System.getProperty("os.name").contains("Linux")) @@ -259,9 +301,8 @@ else if (Utilities.checkFile("WinMerge", Utilities.path(System.getenv("ProgramFi return result; } - public static String checkJsonIsSame(String id, String expected, String actual) throws FileNotFoundException, IOException { - CompareUtilities self = new CompareUtilities(); - String result = self.compareJson(id, expected, actual); + public String checkJsonIsSame(String id, String expected, String actual) throws FileNotFoundException, IOException { + String result = compareJson(id, expected, actual); if (result != null && SHOW_DIFF) { String diff = Utilities.path(System.getenv("ProgramFiles(X86)"), "WinMerge", "WinMergeU.exe"); List command = new ArrayList(); @@ -294,16 +335,17 @@ private String compareObjects(String id, String path, JsonObject expectedJsonObj String n = en.getName(); if (!n.equals("fhir_comments")) { if (expectedJsonObject.has(n)) { - String s = compareNodes(id, path + '.' + n, expectedJsonObject.get(n), en.getValue(), countOnlys.contains(n)); + String s = compareNodes(id, path + '.' + n, expectedJsonObject.get(n), en.getValue(), countOnlys.contains(n), n, actualJsonObject); if (!Utilities.noString(s)) return s; - } else - return "properties differ at " + path + ": missing property " + n; + } else if (!patternMode) { + return "properties differ at " + path + ": unexpected property " + n; + } } } for (JsonProperty en : expectedJsonObject.getProperties()) { String n = en.getName(); - if (!n.equals("fhir_comments") && !n.equals("$optional$") && !optionals.contains(n)) { + if (!n.equals("fhir_comments") && !isOptional(n, optionals)) { if (!actualJsonObject.has(n) && !allOptional(en.getValue())) return "properties differ at " + path + ": missing property " + n; } @@ -311,6 +353,10 @@ private String compareObjects(String id, String path, JsonObject expectedJsonObj return null; } + private boolean isOptional(String n, List optionals) { + return n.equals("$optional$") || optionals.contains("*") || optionals.contains(n); + } + private boolean allOptional(JsonElement value) { if (value.isJsonArray()) { JsonArray a = value.asJsonArray(); @@ -352,7 +398,7 @@ private List listCountOnlys(JsonObject expectedJsonObject) { return res; } - private String compareNodes(String id, String path, JsonElement expectedJsonElement, JsonElement actualJsonElement, boolean countOnly) { + private String compareNodes(String id, String path, JsonElement expectedJsonElement, JsonElement actualJsonElement, boolean countOnly, String name, JsonObject parent) { if (!(expectedJsonElement instanceof JsonPrimitive && actualJsonElement instanceof JsonPrimitive)) { if (actualJsonElement.getClass() != expectedJsonElement.getClass()) { return createNotEqualMessage(id, "properties differ at " + path, expectedJsonElement.getClass().getName(), actualJsonElement.getClass().getName()); @@ -394,38 +440,59 @@ private String compareNodes(String id, String path, JsonElement expectedJsonElem return createNotEqualMessage(id, "array item count differs at " + path, Integer.toString(es), Integer.toString(as)); } } else { - int expectedMin = countExpectedMin(expectedArray); - int oc = optionalCount(expectedArray); - - if (as > es || as < expectedMin) - return createNotEqualMessage(id, "array item count differs at " + path, Integer.toString(es), Integer.toString(as)); - int c = 0; - for (int i = 0; i < es; i++) { - if (c >= as) { - if (i >= es - oc && isOptional(expectedArray.get(i))) { - return null; // this is OK - } else { - return "One or more array items did not match at "+path+" starting at index "+i; + int expectedMin = countExpectedMin(expectedArray, name, parent); + int oc = optionalCount(expectedArray, name, parent); + + + if (patternMode) { + int c = 0; + for (int i = 0; i < expectedArray.size(); i++) { + String s = "Doesn't exist"; + CommaSeparatedStringBuilder cs = new CommaSeparatedStringBuilder("\r\n"); + cs.append(""); + while (s != null && c < actualArray.size()) { + s = compareNodes(id, path + "[" + Integer.toString(i) + "]", expectedArray.get(i), actualArray.get(c), false, null, null); + if (s != null) { + cs.append(" "+s); + } + c++; + } + if (s != null) { + return "The expected item at "+path+" at index "+i+" was not found: "+cs.toString(); } } - String s = compareNodes(id, path + "[" + Integer.toString(i) + "]", expectedArray.get(i), actualArray.get(c), false); - if (!Utilities.noString(s) && !isOptional(expectedArray.get(i))) { - return s; + } else { + if (as > es || as < expectedMin) { + return createNotEqualMessage(id, "array item count differs at " + path, Integer.toString(es), Integer.toString(as)); + } + int c = 0; + for (int i = 0; i < es; i++) { + if (c >= as) { + if (i >= es - oc && isOptional(expectedArray.get(i), name, parent)) { + return null; // this is OK + } else { + return "One or more array items did not match at "+path+" starting at index "+i; + } + } + String s = compareNodes(id, path + "[" + Integer.toString(i) + "]", expectedArray.get(i), actualArray.get(c), false, null, null); + if (!Utilities.noString(s) && !isOptional(expectedArray.get(i), name, parent)) { + return s; + } + if (Utilities.noString(s)) { + c++; + } } - if (Utilities.noString(s)) { - c++; + if (c < as) { + return "Unexpected Node found in array at '"+path+"' at index "+c; } } - if (c < as) { - return "Unexpected Node found in array at '"+path+"' at index "+c; - } } } else return "unhandled property " + actualJsonElement.getClass().getName(); return null; } - private int optionalCount(JsonArray arr) { + private int optionalCount(JsonArray arr, String name, JsonObject parent) { int c = 0; for (JsonElement e : arr) { if (e.isJsonObject()) { @@ -438,14 +505,14 @@ private int optionalCount(JsonArray arr) { return c; } - private boolean isOptional(JsonElement e) { + private boolean isOptional(JsonElement e, String name, JsonObject parent) { return e.isJsonObject() && e.asJsonObject().has("$optional$"); } - private int countExpectedMin(JsonArray array) { + private int countExpectedMin(JsonArray array, String name, JsonObject parent) { int count = array.size(); for (JsonElement e : array) { - if (isOptional(e)) { + if (isOptional(e, name, parent)) { count--; } } @@ -485,8 +552,13 @@ private boolean matches(String actualJsonString, String expectedJsonString) { switch (expectedJsonString) { case "$$" : return true; case "$instant$": return actualJsonString.matches("([0-9]([0-9]([0-9][1-9]|[1-9]0)|[1-9]00)|[1-9]000)-(0[1-9]|1[0-2])-(0[1-9]|[1-2][0-9]|3[0-1])T([01][0-9]|2[0-3]):[0-5][0-9]:([0-5][0-9]|60)(\\.[0-9]{1,9})?(Z|(\\+|-)((0[0-9]|1[0-3]):[0-5][0-9]|14:00))"); + case "$date$": return actualJsonString.matches("([0-9]([0-9]([0-9][1-9]|[1-9]0)|[1-9]00)|[1-9]000)-(0[1-9]|1[0-2])-(0[1-9]|[1-2][0-9]|3[0-1])(T([01][0-9]|2[0-3]):[0-5][0-9]:([0-5][0-9]|60)(\\.[0-9]{1,9})?(Z|(\\+|-)((0[0-9]|1[0-3]):[0-5][0-9]|14:00)))?"); case "$uuid$": return actualJsonString.matches("urn:uuid:[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}"); + case "$string$": return actualJsonString.equals(actualJsonString.trim()); case "$id$": return actualJsonString.matches("[A-Za-z0-9\\-\\.]{1,64}"); + case "$url$": return actualJsonString.matches("(https?://|www\\.)[-a-zA-Z0-9+&@#/%?=~_|!:.;]*[-a-zA-Z0-9+&@#/%=~_|]"); + case "$token$": return actualJsonString.matches("[0-9a-zA-Z_][0-9a-zA-Z_\\.\\-]*"); + case "$version$": return matchesVariable(actualJsonString, "version"); default: throw new Error("Unhandled template: "+expectedJsonString); } @@ -496,6 +568,14 @@ private boolean matches(String actualJsonString, String expectedJsonString) { } } + private boolean matchesVariable(String value, String name) { + if (variables.containsKey(name)) { + return value.equals(variables.get(name)); + } else { + return true; + } + } + private List readChoices(String s) { List list = new ArrayList<>(); for (String p : s.split("\\|")) { @@ -504,13 +584,12 @@ private List readChoices(String s) { return list; } - public static String checkTextIsSame(String id, String expected, String actual) throws FileNotFoundException, IOException { + public String checkTextIsSame(String id, String expected, String actual) throws FileNotFoundException, IOException { return checkTextIsSame(id, expected, actual, true); } - public static String checkTextIsSame(String id, String expectedString, String actualString, boolean showDiff) throws FileNotFoundException, IOException { - CompareUtilities self = new CompareUtilities(); - String result = self.compareText(id, expectedString, actualString); + public String checkTextIsSame(String id, String expectedString, String actualString, boolean showDiff) throws FileNotFoundException, IOException { + String result = compareText(id, expectedString, actualString); if (result != null && SHOW_DIFF && showDiff) { String diff = null; if (System.getProperty("os.name").contains("Linux")) diff --git a/org.hl7.fhir.r5/src/test/java/org/hl7/fhir/r5/elementmodel/LanguageUtilsTest.java b/org.hl7.fhir.r5/src/test/java/org/hl7/fhir/r5/elementmodel/LanguageUtilsTest.java index 631731b27c..4825f225e2 100644 --- a/org.hl7.fhir.r5/src/test/java/org/hl7/fhir/r5/elementmodel/LanguageUtilsTest.java +++ b/org.hl7.fhir.r5/src/test/java/org/hl7/fhir/r5/elementmodel/LanguageUtilsTest.java @@ -47,7 +47,7 @@ void importFromTranslations() throws Exception { .lines() .collect(Collectors.joining("\n")); - String msg = CompareUtilities.checkJsonSrcIsSame("", generatedResource.toString(),text, null); + String msg = new CompareUtilities().checkJsonSrcIsSame("", generatedResource.toString(),text); Assertions.assertNull(msg); } diff --git a/org.hl7.fhir.r5/src/test/java/org/hl7/fhir/r5/sql/SQLOnFhirTests.java b/org.hl7.fhir.r5/src/test/java/org/hl7/fhir/r5/sql/SQLOnFhirTests.java index d650980fbc..1d4d60c520 100644 --- a/org.hl7.fhir.r5/src/test/java/org/hl7/fhir/r5/sql/SQLOnFhirTests.java +++ b/org.hl7.fhir.r5/src/test/java/org/hl7/fhir/r5/sql/SQLOnFhirTests.java @@ -138,7 +138,7 @@ public void test(String name, TestDetails test) throws FileNotFoundException, IO // sortResults(rows); String expS = JsonParser.compose(exp, true); String rowS = JsonParser.compose(rows, true); - String c = CompareUtilities.checkJsonSrcIsSame(name, expS, rowS, null); + String c = new CompareUtilities().checkJsonSrcIsSame(name, expS, rowS); Assertions.assertNull(c, c); } else if (test.testCase.has("expectCount")) { Assertions.assertEquals(test.testCase.asInteger("expectCount"), results.size()); diff --git a/org.hl7.fhir.r5/src/test/java/org/hl7/fhir/r5/test/GraphQLEngineTests.java b/org.hl7.fhir.r5/src/test/java/org/hl7/fhir/r5/test/GraphQLEngineTests.java index ecba23c021..8e01e5d8d0 100644 --- a/org.hl7.fhir.r5/src/test/java/org/hl7/fhir/r5/test/GraphQLEngineTests.java +++ b/org.hl7.fhir.r5/src/test/java/org/hl7/fhir/r5/test/GraphQLEngineTests.java @@ -98,7 +98,7 @@ private void testResource(String id, Resource resource, String output, String so IOUtils.copy(CompareUtilities.loadTestResourceStream("r5", "graphql", source), ManagedFileAccess.outStream(CompareUtilities.tempFile("graphql", source))); IOUtils.copy(CompareUtilities.loadTestResourceStream("r5", "graphql", output), ManagedFileAccess.outStream(CompareUtilities.tempFile("graphql", output))); TextFile.stringToFile(str.toString(), CompareUtilities.tempFile("graphql", output+".out")); - msg = CompareUtilities.checkJsonIsSame(id, CompareUtilities.tempFile("graphql", output), CompareUtilities.tempFile("graphql", output+".out")); + msg = new CompareUtilities().checkJsonIsSame(id, CompareUtilities.tempFile("graphql", output), CompareUtilities.tempFile("graphql", output+".out")); Assertions.assertTrue(Utilities.noString(msg), msg); } else diff --git a/org.hl7.fhir.r5/src/test/java/org/hl7/fhir/r5/test/NarrativeGenerationTests.java b/org.hl7.fhir.r5/src/test/java/org/hl7/fhir/r5/test/NarrativeGenerationTests.java index cab59327ea..82fdb3e78d 100644 --- a/org.hl7.fhir.r5/src/test/java/org/hl7/fhir/r5/test/NarrativeGenerationTests.java +++ b/org.hl7.fhir.r5/src/test/java/org/hl7/fhir/r5/test/NarrativeGenerationTests.java @@ -279,7 +279,7 @@ public void test(String id, TestDetails test) throws Exception { String actualFileName = CompareUtilities.tempFile("narrative", test.getId() + ".html"); TextFile.stringToFile(expected, expectedFileName); TextFile.stringToFile(actual, actualFileName); - String msg = CompareUtilities.checkXMLIsSame(id, expectedFileName, actualFileName); + String msg = new CompareUtilities().checkXMLIsSame(id, expectedFileName, actualFileName); Assertions.assertTrue(msg == null, "Output does not match expected: "+msg); String disp = RendererFactory.factory(source, rc).buildSummary(ResourceWrapper.forResource(rc.getContextUtilities(), source)); @@ -289,7 +289,7 @@ public void test(String id, TestDetails test) throws Exception { actualFileName = CompareUtilities.tempFile("narrative", test.getId() + ".txt"); TextFile.stringToFile(expected, expectedFileName); TextFile.stringToFile(actual, actualFileName); - msg = CompareUtilities.checkTextIsSame(id, expected, actual); + msg = new CompareUtilities().checkTextIsSame(id, expected, actual); Assertions.assertTrue(msg == null, "Summary Output does not match expected: "+msg); // diff --git a/org.hl7.fhir.r5/src/test/java/org/hl7/fhir/r5/test/ParsingTests.java b/org.hl7.fhir.r5/src/test/java/org/hl7/fhir/r5/test/ParsingTests.java index b34987537e..ca7d8ebbe4 100644 --- a/org.hl7.fhir.r5/src/test/java/org/hl7/fhir/r5/test/ParsingTests.java +++ b/org.hl7.fhir.r5/src/test/java/org/hl7/fhir/r5/test/ParsingTests.java @@ -58,7 +58,7 @@ public void test(String name) throws Exception { r = new XmlParser().parse(b); b = new JsonParser().setOutputStyle(OutputStyle.PRETTY).composeBytes(r); String output = new String(b); - String msg = CompareUtilities.checkJsonSrcIsSame(name, src, output, null); + String msg = new CompareUtilities().checkJsonSrcIsSame(name, src, output); Assertions.assertTrue(msg == null, msg); } diff --git a/org.hl7.fhir.r5/src/test/java/org/hl7/fhir/r5/test/ResourceToElementTest.java b/org.hl7.fhir.r5/src/test/java/org/hl7/fhir/r5/test/ResourceToElementTest.java index 1051b07a48..fa30c96e5e 100644 --- a/org.hl7.fhir.r5/src/test/java/org/hl7/fhir/r5/test/ResourceToElementTest.java +++ b/org.hl7.fhir.r5/src/test/java/org/hl7/fhir/r5/test/ResourceToElementTest.java @@ -40,7 +40,7 @@ private void runTest(String filename) throws IOException, FileNotFoundException, Element e = p.parse(res); new org.hl7.fhir.r5.elementmodel.XmlParser(ctxt).compose(e, ManagedFileAccess.outStream(src), OutputStyle.PRETTY, null); new XmlParser().setOutputStyle(OutputStyle.PRETTY).compose(ManagedFileAccess.outStream(dst), res); - String msg = CompareUtilities.checkXMLIsSame(filename, src, dst); + String msg = new CompareUtilities().checkXMLIsSame(filename, src, dst); Assertions.assertNull(msg); } diff --git a/org.hl7.fhir.r5/src/test/java/org/hl7/fhir/r5/test/VocabTests.java b/org.hl7.fhir.r5/src/test/java/org/hl7/fhir/r5/test/VocabTests.java index 78d3fdbca9..ef160a77b0 100644 --- a/org.hl7.fhir.r5/src/test/java/org/hl7/fhir/r5/test/VocabTests.java +++ b/org.hl7.fhir.r5/src/test/java/org/hl7/fhir/r5/test/VocabTests.java @@ -157,7 +157,7 @@ private void testExpansion(TestDetails test, ValueSet sourceVS, ValueSet targetV String actualFileName = CompareUtilities.tempFile("vocab", test.getId() + ".actual.html"); TextFile.stringToFile(expected, expectedFileName); TextFile.stringToFile(actual, actualFileName); - String msg = CompareUtilities.checkXMLIsSame(test.id, expectedFileName, actualFileName); + String msg = new CompareUtilities().checkXMLIsSame(test.id, expectedFileName, actualFileName); Assertions.assertTrue(msg == null, "Output does not match expected: "+msg); } else { Assertions.fail("Expansion Failed: "+outcome.getError()); diff --git a/org.hl7.fhir.r5/src/test/java/org/hl7/fhir/r5/test/profiles/GeneratedPEModelTest.java b/org.hl7.fhir.r5/src/test/java/org/hl7/fhir/r5/test/profiles/GeneratedPEModelTest.java index d85d2d4489..61b14c08a1 100644 --- a/org.hl7.fhir.r5/src/test/java/org/hl7/fhir/r5/test/profiles/GeneratedPEModelTest.java +++ b/org.hl7.fhir.r5/src/test/java/org/hl7/fhir/r5/test/profiles/GeneratedPEModelTest.java @@ -68,7 +68,7 @@ public void testPEGenLoad() throws Exception { Observation tgt = tp.build(ctxt); new XmlParser().setOutputStyle(OutputStyle.PRETTY).compose(ManagedFileAccess.outStream(Utilities.path("[tmp]", "pe-instance-gen.xml")), tgt); - String msg = CompareUtilities.checkXMLIsSame("PEGEN", TestingUtilities.loadTestResourceStream("r5", "profiles", "pe-instance.xml"), ManagedFileAccess.inStream(Utilities.path("[tmp]", "pe-instance-gen.xml"))); + String msg = new CompareUtilities().checkXMLIsSame("PEGEN", TestingUtilities.loadTestResourceStream("r5", "profiles", "pe-instance.xml"), ManagedFileAccess.inStream(Utilities.path("[tmp]", "pe-instance-gen.xml"))); Assertions.assertNull(msg, msg); } diff --git a/org.hl7.fhir.r5/src/test/java/org/hl7/fhir/r5/test/profiles/PETests.java b/org.hl7.fhir.r5/src/test/java/org/hl7/fhir/r5/test/profiles/PETests.java index eed237ad0f..34a18f6539 100644 --- a/org.hl7.fhir.r5/src/test/java/org/hl7/fhir/r5/test/profiles/PETests.java +++ b/org.hl7.fhir.r5/src/test/java/org/hl7/fhir/r5/test/profiles/PETests.java @@ -422,7 +422,7 @@ public void testGenerate() throws IOException { private void checkGeneratedJava(String name) throws FileNotFoundException, IOException { String actual = Utilities.normalize(TextFile.fileToString(Utilities.path("[tmp]", "codegen", name+".java"))); String expected = Utilities.normalize(TestingUtilities.loadTestResource("r5", "profiles", name+".java")); - String msg = CompareUtilities.checkTextIsSame(name, expected, actual); + String msg = new CompareUtilities().checkTextIsSame(name, expected, actual); if (msg != null) { Assertions.fail("Generated code for "+name+" is different: "+msg); } diff --git a/org.hl7.fhir.r5/src/test/java/org/hl7/fhir/r5/test/utils/CompareUtilitiesTests.java b/org.hl7.fhir.r5/src/test/java/org/hl7/fhir/r5/test/utils/CompareUtilitiesTests.java index bb11b97585..03edba360d 100644 --- a/org.hl7.fhir.r5/src/test/java/org/hl7/fhir/r5/test/utils/CompareUtilitiesTests.java +++ b/org.hl7.fhir.r5/src/test/java/org/hl7/fhir/r5/test/utils/CompareUtilitiesTests.java @@ -59,7 +59,7 @@ public void testCompareXML(String expectedFileName, String actualFileName, Strin InputStream expectedXMLStream = classLoader.getResourceAsStream(expectedXMLPath); InputStream actualXMLStream = classLoader.getResourceAsStream(actualXMLPath); - final String actualOutput = CompareUtilities.checkXMLIsSame(expectedFileName, expectedXMLStream, actualXMLStream); + final String actualOutput = new CompareUtilities().checkXMLIsSame(expectedFileName, expectedXMLStream, actualXMLStream); if (expectedOutputFileName == null) { assertNull(actualOutput); @@ -91,7 +91,7 @@ public void testCompareJSON(String expectedFileName, String actualFileName, Stri final String expectedJSONPath = ROOT_JSON_TEST_PATH.resolve(expectedFileName).toString(); final String actualJSONPath = ROOT_JSON_TEST_PATH.resolve(actualFileName).toString(); - final String actualOutput = CompareUtilities.checkJsonSrcIsSame(expectedFileName, getResourceAsString(expectedJSONPath), getResourceAsString(actualJSONPath), false, null); + final String actualOutput = new CompareUtilities().checkJsonSrcIsSame(expectedFileName, getResourceAsString(expectedJSONPath), getResourceAsString(actualJSONPath), false); if (expectedOutputFileName == null) { assertNull(actualOutput); } else { diff --git a/org.hl7.fhir.r5/src/test/resources/testUtilities/json/actualExtraProperty.json.error b/org.hl7.fhir.r5/src/test/resources/testUtilities/json/actualExtraProperty.json.error index dc127601cb..8bca7ed5f9 100644 --- a/org.hl7.fhir.r5/src/test/resources/testUtilities/json/actualExtraProperty.json.error +++ b/org.hl7.fhir.r5/src/test/resources/testUtilities/json/actualExtraProperty.json.error @@ -1 +1 @@ -properties differ at : missing property unexpectedProperty \ No newline at end of file +properties differ at : unexpected property unexpectedProperty \ No newline at end of file diff --git a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/special/TxServiceTestHelper.java b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/special/TxServiceTestHelper.java index b9ea0ffdb4..576b2aa500 100644 --- a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/special/TxServiceTestHelper.java +++ b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/special/TxServiceTestHelper.java @@ -108,7 +108,7 @@ public static String getDiffForValidation(String id, IWorkerContext context, Str writeDiffToFileSystem( name, expectedResponse, actualResponse); - String diff = CompareUtilities.checkJsonSrcIsSame(id, expectedResponse, actualResponse, externals); + String diff = new CompareUtilities(externals).checkJsonSrcIsSame(id, expectedResponse, actualResponse); if (diff != null) { Utilities.createDirectory(Utilities.getDirectoryForFile(fp)); TextFile.stringToFile(actualResponse, fp); @@ -182,7 +182,7 @@ public static String getDiffForValidation(String id, IWorkerContext context, Str writeDiffToFileSystem(name, expectedResponse, actualResponse); - String diff = CompareUtilities.checkJsonSrcIsSame(id, expectedResponse, actualResponse, externals); + String diff = new CompareUtilities(externals).checkJsonSrcIsSame(id, expectedResponse, actualResponse); if (diff != null) { Utilities.createDirectory(Utilities.getDirectoryForFile(fp)); TextFile.stringToFile(actualResponse, fp); diff --git a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/special/TxTester.java b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/special/TxTester.java index 896fb2d758..e24462e2c1 100644 --- a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/special/TxTester.java +++ b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/special/TxTester.java @@ -19,8 +19,10 @@ import java.util.Calendar; import java.util.Collection; import java.util.GregorianCalendar; +import java.util.HashMap; import java.util.List; import java.util.Locale; +import java.util.Map; import java.util.TimeZone; import java.util.zip.ZipEntry; import java.util.zip.ZipInputStream; @@ -30,11 +32,13 @@ import org.hl7.fhir.exceptions.DefinitionException; import org.hl7.fhir.exceptions.FHIRException; import org.hl7.fhir.exceptions.FHIRFormatError; +import org.hl7.fhir.r4b.context.TextClientLogger; import org.hl7.fhir.r5.formats.IParser.OutputStyle; import org.hl7.fhir.r5.model.CapabilityStatement; import org.hl7.fhir.r5.model.OperationOutcome; import org.hl7.fhir.r5.model.Parameters; import org.hl7.fhir.r5.model.Resource; +import org.hl7.fhir.r5.model.TerminologyCapabilities; import org.hl7.fhir.r5.model.ValueSet; import org.hl7.fhir.r5.terminologies.client.ITerminologyClient; import org.hl7.fhir.r5.test.utils.CompareUtilities; @@ -65,6 +69,8 @@ public interface ITxTesterLoader { private JsonObject externals; private String software; private List fails = new ArrayList<>(); + private CapabilityStatement cstmt; + private TerminologyCapabilities tc; public TxTester(ITxTesterLoader loader, String server, boolean tight, JsonObject externals) { @@ -107,14 +113,14 @@ public boolean execute(String version, List modes, String filter) throws json.add("date", new SimpleDateFormat("EEE, MMM d, yyyy HH:mmZ", new Locale("en", "US")).format(Calendar.getInstance().getTime()) + timezone()); try { JsonObject tests = loadTests(); - ITerminologyClient tx = connectToServer(modes); - boolean ok = checkClient(tx); + tx = connectToServer(modes); + boolean ok = checkClient(); for (JsonObject suite : tests.getJsonObjects("suites")) { if ((!suite.has("mode") || modes.contains(suite.asString("mode")))) { if (suite.asBoolean("disabled")) { // ok = true; } else { - ok = runSuite(suite, tx, modes, filter, json.forceArray("suites")) && ok; + ok = runSuite(suite, modes, filter, json.forceArray("suites")) && ok; } } } @@ -123,10 +129,10 @@ public boolean execute(String version, List modes, String filter) throws if (filter == null) { String m = modes.isEmpty() ? "[none]" : CommaSeparatedStringBuilder.join(";", modes); if (ok) { - System.out.println(software+" passed all HL7 terminology service tests (modes "+m+", tests v"+loadVersion()+", runner v"+VersionUtil.getBaseVersion()+")"); + System.out.println(software+" passed all HL7 terminology service tests ("+Utilities.pluralize("mode", modes.size())+" "+m+", tests v"+loadVersion()+", runner v"+VersionUtil.getBaseVersion()+")"); return true; } else { - System.out.println(software+" did not pass all HL7 terminology service tests (modes "+m+", tests v"+loadVersion()+", runner v"+VersionUtil.getBaseVersion()+")"); + System.out.println(software+" did not pass all HL7 terminology service tests ("+Utilities.pluralize("mode", modes.size())+" "+m+", tests v"+loadVersion()+", runner v"+VersionUtil.getBaseVersion()+")"); System.out.println("Failed Tests: "+ CommaSeparatedStringBuilder.join(",", fails )); return false; } @@ -153,12 +159,12 @@ private String timezone() { return offset; } - private boolean checkClient(ITerminologyClient tx) { - CapabilityStatement cstmt = tx.getCapabilitiesStatementQuick(); + private boolean checkClient() { + cstmt = tx.getCapabilitiesStatement(); if (cstmt.hasSoftware()) { software = cstmt.getSoftware().getName()+" v"+cstmt.getSoftware().getVersion(); } - tx.getTerminologyCapabilities(); + tc = tx.getTerminologyCapabilities(); return true; } @@ -171,7 +177,7 @@ private String loadVersion() throws JsonException, IOException { return processHistoryMarkdown(loader.loadContent("history.md")); } - private String processHistoryMarkdown(byte[] content) throws IOException { + public static String processHistoryMarkdown(byte[] content) throws IOException { DataInputStream in = new DataInputStream(new ByteArrayInputStream(content)); BufferedReader br = new BufferedReader(new InputStreamReader(in)); try { @@ -179,7 +185,7 @@ private String processHistoryMarkdown(byte[] content) throws IOException { //Read File Line By Line while ((strLine = br.readLine()) != null) { if (strLine.startsWith("## ")) { - return strLine.substring(3); + return strLine.substring(3).trim(); } } } finally { @@ -189,7 +195,7 @@ private String processHistoryMarkdown(byte[] content) throws IOException { return "<1.6.0"; } - private ITerminologyClient connectToServer(List modes) throws URISyntaxException { + private ITerminologyClient connectToServer(List modes) throws URISyntaxException, IOException { System.out.println("Connect to "+server); software = server; ITerminologyClient client = new TerminologyClientFactory(FhirPublication.R4).makeClient("Test-Server", server, "Tools/Java", null); @@ -201,18 +207,18 @@ public String executeTest(JsonObject suite, JsonObject test, List modes) error = null; if (tx == null) { tx = connectToServer(modes); - checkClient(tx); + checkClient(); } List setup = loadSetupResources(suite); - if (runTest(suite, test, tx, setup, modes, "*", null)) { + if (runTest(suite, test, setup, modes, "*", null)) { return null; } else { return error; } } - private boolean runSuite(JsonObject suite, ITerminologyClient tx, List modes, String filter, JsonArray output) throws FHIRFormatError, FileNotFoundException, IOException { + private boolean runSuite(JsonObject suite, List modes, String filter, JsonArray output) throws FHIRFormatError, FileNotFoundException, IOException { System.out.println("Group "+suite.asString("name")); JsonObject outputS = new JsonObject(); if (output != null) { @@ -226,14 +232,14 @@ private boolean runSuite(JsonObject suite, ITerminologyClient tx, List m if (test.asBoolean("disabled")) { ok = true; } else { - ok = runTest(suite, test, tx, setup, modes, filter, outputS.forceArray("tests")) && ok; + ok = runTest(suite, test, setup, modes, filter, outputS.forceArray("tests")) && ok; } } } return ok; } - private boolean runTest(JsonObject suite, JsonObject test, ITerminologyClient tx, List setup, List modes, String filter, JsonArray output) throws FHIRFormatError, DefinitionException, FileNotFoundException, FHIRException, IOException { + private boolean runTest(JsonObject suite, JsonObject test, List setup, List modes, String filter, JsonArray output) throws FHIRFormatError, DefinitionException, FileNotFoundException, FHIRException, IOException { JsonObject outputT = new JsonObject(); if (output != null) { output.add(outputT); @@ -253,7 +259,8 @@ private boolean runTest(JsonObject suite, JsonObject test, ITerminologyClient tx } } - Parameters req = (Parameters) loader.loadResource(chooseParam(test, "request", modes)); + String reqFile = chooseParam(test, "request", modes); + Parameters req = reqFile == null ? null : (Parameters) loader.loadResource(reqFile); String fn = chooseParam(test, "response", modes); String resp = TextFile.bytesToString(loader.loadContent(fn)); @@ -266,16 +273,20 @@ private boolean runTest(JsonObject suite, JsonObject test, ITerminologyClient tx String lang = test.asString("Content-Language"); String msg = null; - if (test.asString("operation").equals("expand")) { - msg = expand(test.str("name"), tx, setup, req, resp, fp, lang, profile, ext, getResponseCode(test)); + if (test.asString("operation").equals("metadata")) { + msg = metadata(test.str("name"), setup, resp, fp, lang, profile, ext); + } else if (test.asString("operation").equals("term-caps")) { + msg = termcaps(test.str("name"), setup, resp, fp, lang, profile, ext); + } else if (test.asString("operation").equals("expand")) { + msg = expand(test.str("name"), setup, req, resp, fp, lang, profile, ext, getResponseCode(test)); } else if (test.asString("operation").equals("validate-code")) { - msg = validate(test.str("name"),tx, setup, req, resp, fp, lang, profile, ext, getResponseCode(test)); + msg = validate(test.str("name"), setup, req, resp, fp, lang, profile, ext, getResponseCode(test)); } else if (test.asString("operation").equals("cs-validate-code")) { - msg = validateCS(test.str("name"),tx, setup, req, resp, fp, lang, profile, ext, getResponseCode(test)); + msg = validateCS(test.str("name"), setup, req, resp, fp, lang, profile, ext, getResponseCode(test)); } else if (test.asString("operation").equals("lookup")) { - msg = lookup(test.str("name"),tx, setup, req, resp, fp, lang, profile, ext, getResponseCode(test)); + msg = lookup(test.str("name"), setup, req, resp, fp, lang, profile, ext, getResponseCode(test)); } else if (test.asString("operation").equals("translate")) { - msg = translate(test.str("name"),tx, setup, req, resp, fp, lang, profile, ext, getResponseCode(test)); + msg = translate(test.str("name"), setup, req, resp, fp, lang, profile, ext, getResponseCode(test)); } else { throw new Exception("Unknown Operation "+test.asString("operation")); } @@ -311,6 +322,34 @@ private boolean runTest(JsonObject suite, JsonObject test, ITerminologyClient tx } } + private String metadata(String id, List setup, String resp, String fp, String lang, Parameters profile, JsonObject ext) throws IOException { + CapabilityStatement cs = cstmt.copy(); + TxTesterScrubbers.scrubCapStmt(cs, tight); + TxTesterSorters.sortCapStmt(cs); + String csj = new org.hl7.fhir.r5.formats.JsonParser().setOutputStyle(OutputStyle.PRETTY).composeString(cs); + + String diff = new CompareUtilities(ext, vars()).setPatternMode(true).checkJsonSrcIsSame(id, resp, csj, false); + if (diff != null) { + Utilities.createDirectory(Utilities.getDirectoryForFile(fp)); + TextFile.stringToFile(csj, fp); + } + return diff; + } + + private String termcaps(String id, List setup, String resp, String fp, String lang, Parameters profile, JsonObject ext) throws IOException { + TerminologyCapabilities cs = tc.copy(); + TxTesterScrubbers.scrubTermCaps(cs, tight); + TxTesterSorters.sortTermCaps(cs); + String csj = new org.hl7.fhir.r5.formats.JsonParser().setOutputStyle(OutputStyle.PRETTY).composeString(cs); + + String diff = new CompareUtilities(ext, vars()).setPatternMode(true).checkJsonSrcIsSame(id, resp, csj, false); + if (diff != null) { + Utilities.createDirectory(Utilities.getDirectoryForFile(fp)); + TextFile.stringToFile(csj, fp); + } + return diff; + } + private String getResponseCode(JsonObject test) { if (test.has("http-code")) { return test.asString("http-code"); @@ -340,7 +379,7 @@ private String serverId() throws URISyntaxException { return new URI(server).getHost(); } - private String lookup(String id, ITerminologyClient tx, List setup, Parameters p, String resp, String fp, String lang, Parameters profile, JsonObject ext, String tcode) throws IOException { + private String lookup(String id, List setup, Parameters p, String resp, String fp, String lang, Parameters profile, JsonObject ext, String tcode) throws IOException { for (Resource r : setup) { p.addParameter().setName("tx-resource").setResource(r); } @@ -363,7 +402,7 @@ private String lookup(String id, ITerminologyClient tx, List setup, Pa if (tcode != null && !httpCodeOk(tcode, code)) { return "Response Code fail: should be '"+tcode+"' but is '"+code+"'"; } - String diff = CompareUtilities.checkJsonSrcIsSame(id, resp, pj, false, ext); + String diff = new CompareUtilities(ext, vars()).checkJsonSrcIsSame(id, resp, pj, false); if (diff != null) { Utilities.createDirectory(Utilities.getDirectoryForFile(fp)); TextFile.stringToFile(pj, fp); @@ -371,7 +410,7 @@ private String lookup(String id, ITerminologyClient tx, List setup, Pa return diff; } - private String translate(String id, ITerminologyClient tx, List setup, Parameters p, String resp, String fp, String lang, Parameters profile, JsonObject ext, String tcode) throws IOException { + private String translate(String id, List setup, Parameters p, String resp, String fp, String lang, Parameters profile, JsonObject ext, String tcode) throws IOException { for (Resource r : setup) { p.addParameter().setName("tx-resource").setResource(r); } @@ -394,7 +433,7 @@ private String translate(String id, ITerminologyClient tx, List setup, if (tcode != null && !httpCodeOk(tcode, code)) { return "Response Code fail: should be '"+tcode+"' but is '"+code+"'"; } - String diff = CompareUtilities.checkJsonSrcIsSame(id, resp, pj, false, ext); + String diff = new CompareUtilities(ext, vars()).checkJsonSrcIsSame(id, resp, pj, false); if (diff != null) { Utilities.createDirectory(Utilities.getDirectoryForFile(fp)); TextFile.stringToFile(pj, fp); @@ -402,7 +441,7 @@ private String translate(String id, ITerminologyClient tx, List setup, return diff; } - private String expand(String id, ITerminologyClient tx, List setup, Parameters p, String resp, String fp, String lang, Parameters profile, JsonObject ext, String tcode) throws IOException { + private String expand(String id, List setup, Parameters p, String resp, String fp, String lang, Parameters profile, JsonObject ext, String tcode) throws IOException { for (Resource r : setup) { p.addParameter().setName("tx-resource").setResource(r); } @@ -425,7 +464,7 @@ private String expand(String id, ITerminologyClient tx, List setup, Pa if (tcode != null && !httpCodeOk(tcode, code)) { return "Response Code fail: should be '"+tcode+"' but is '"+code+"'"; } - String diff = CompareUtilities.checkJsonSrcIsSame(id, resp, vsj, false, ext); + String diff = new CompareUtilities(ext, vars()).checkJsonSrcIsSame(id, resp, vsj, false); if (diff != null) { Utilities.createDirectory(Utilities.getDirectoryForFile(fp)); TextFile.stringToFile(vsj, fp); @@ -444,7 +483,7 @@ private boolean httpCodeOk(String tcode, int code) { } } - private String validate(String id, ITerminologyClient tx, List setup, Parameters p, String resp, String fp, String lang, Parameters profile, JsonObject ext, String tcode) throws IOException { + private String validate(String id, List setup, Parameters p, String resp, String fp, String lang, Parameters profile, JsonObject ext, String tcode) throws IOException { for (Resource r : setup) { p.addParameter().setName("tx-resource").setResource(r); } @@ -468,7 +507,7 @@ private String validate(String id, ITerminologyClient tx, List setup, if (tcode != null && !httpCodeOk(tcode, code)) { return "Response Code fail: should be '"+tcode+"' but is '"+code+"'"; } - String diff = CompareUtilities.checkJsonSrcIsSame(id, resp, pj, false, ext); + String diff = new CompareUtilities(ext, vars()).checkJsonSrcIsSame(id, resp, pj, false); if (diff != null) { Utilities.createDirectory(Utilities.getDirectoryForFile(fp)); TextFile.stringToFile(pj, fp); @@ -476,7 +515,7 @@ private String validate(String id, ITerminologyClient tx, List setup, return diff; } - private String validateCS(String id, ITerminologyClient tx, List setup, Parameters p, String resp, String fp, String lang, Parameters profile, JsonObject ext, String tcode) throws IOException { + private String validateCS(String id, List setup, Parameters p, String resp, String fp, String lang, Parameters profile, JsonObject ext, String tcode) throws IOException { for (Resource r : setup) { p.addParameter().setName("tx-resource").setResource(r); } @@ -499,7 +538,7 @@ private String validateCS(String id, ITerminologyClient tx, List setup if (tcode != null && !httpCodeOk(tcode, code)) { return "Response Code fail: should be '"+tcode+"' but is '"+code+"'"; } - String diff = CompareUtilities.checkJsonSrcIsSame(id, resp, pj, false, ext); + String diff = new CompareUtilities(ext, vars()).checkJsonSrcIsSame(id, resp, pj, false); if (diff != null) { Utilities.createDirectory(Utilities.getDirectoryForFile(fp)); TextFile.stringToFile(pj, fp); @@ -508,6 +547,13 @@ private String validateCS(String id, ITerminologyClient tx, List setup } + private Map vars() { + Map vars = new HashMap(); + vars.put("version", tx.getActualVersion().toCode()); + return vars; + + } + private List loadSetupResources(JsonObject suite) throws FHIRFormatError, FileNotFoundException, IOException { List res = new ArrayList<>(); for (String s : suite.getStrings("setup")) { diff --git a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/special/TxTesterScrubbers.java b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/special/TxTesterScrubbers.java index 1a578c945c..1e25d06c8b 100644 --- a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/special/TxTesterScrubbers.java +++ b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/special/TxTesterScrubbers.java @@ -1,5 +1,7 @@ package org.hl7.fhir.validation.special; +import org.hl7.fhir.r5.model.CapabilityStatement; +import org.hl7.fhir.r5.model.CapabilityStatement.CapabilityStatementRestComponent; import org.hl7.fhir.r5.model.DomainResource; import org.hl7.fhir.r5.model.Element; import org.hl7.fhir.r5.model.Extension; @@ -7,6 +9,7 @@ import org.hl7.fhir.r5.model.OperationOutcome.OperationOutcomeIssueComponent; import org.hl7.fhir.r5.model.Parameters; import org.hl7.fhir.r5.model.Resource; +import org.hl7.fhir.r5.model.TerminologyCapabilities; import org.hl7.fhir.r5.model.ValueSet; import org.hl7.fhir.r5.utils.ElementVisitor; import org.hl7.fhir.r5.utils.ElementVisitor.ElementVisitorInstruction; @@ -98,4 +101,12 @@ public static void scrubOO(OperationOutcome po, boolean tight) { } } + public static void scrubCapStmt(CapabilityStatement cs, boolean tight) { + // nothing yet? + } + + public static void scrubTermCaps(TerminologyCapabilities cs, boolean tight) { + // nothing yet? + } + } diff --git a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/special/TxTesterSorters.java b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/special/TxTesterSorters.java index b93f05d8b6..bc232417f0 100644 --- a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/special/TxTesterSorters.java +++ b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/special/TxTesterSorters.java @@ -8,18 +8,34 @@ import java.util.Comparator; import java.util.List; - import org.hl7.fhir.r5.formats.IParser.OutputStyle; import org.hl7.fhir.r5.formats.JsonParser; - +import org.hl7.fhir.r5.model.CanonicalType; +import org.hl7.fhir.r5.model.CapabilityStatement; import org.hl7.fhir.r5.model.Extension; import org.hl7.fhir.r5.model.OperationOutcome; import org.hl7.fhir.r5.model.OperationOutcome.OperationOutcomeIssueComponent; import org.hl7.fhir.r5.model.Parameters; import org.hl7.fhir.r5.model.Parameters.ParametersParameterComponent; +import org.hl7.fhir.r5.model.TerminologyCapabilities.TerminologyCapabilitiesCodeSystemComponent; +import org.hl7.fhir.r5.model.TerminologyCapabilities.TerminologyCapabilitiesCodeSystemVersionComponent; +import org.hl7.fhir.r5.model.TerminologyCapabilities.TerminologyCapabilitiesCodeSystemVersionFilterComponent; +import org.hl7.fhir.r5.model.TerminologyCapabilities.TerminologyCapabilitiesExpansionParameterComponent; import org.hl7.fhir.r5.model.Resource; import org.hl7.fhir.r5.model.StringType; +import org.hl7.fhir.r5.model.TerminologyCapabilities; import org.hl7.fhir.r5.model.ValueSet; +import org.hl7.fhir.r5.model.CapabilityStatement.CapabilityStatementRestComponent; +import org.hl7.fhir.r5.model.CapabilityStatement.CapabilityStatementRestResourceComponent; +import org.hl7.fhir.r5.model.CapabilityStatement.CapabilityStatementRestResourceOperationComponent; +import org.hl7.fhir.r5.model.CapabilityStatement.CapabilityStatementRestResourceSearchParamComponent; +import org.hl7.fhir.r5.model.CapabilityStatement.ResourceInteractionComponent; +import org.hl7.fhir.r5.model.CapabilityStatement.SystemInteractionComponent; +import org.hl7.fhir.r5.model.Enumerations.CommonLanguages; +import org.hl7.fhir.r5.model.CodeType; +import org.hl7.fhir.r5.model.CodeableConcept; +import org.hl7.fhir.r5.model.Coding; +import org.hl7.fhir.r5.model.Enumeration; import org.hl7.fhir.r5.model.ValueSet.ConceptPropertyComponent; import org.hl7.fhir.r5.model.ValueSet.ConceptReferenceDesignationComponent; import org.hl7.fhir.r5.model.ValueSet.ValueSetExpansionContainsComponent; @@ -27,9 +43,11 @@ import org.hl7.fhir.r5.model.ValueSet.ValueSetExpansionPropertyComponent; import org.hl7.fhir.utilities.CommaSeparatedStringBuilder; import org.hl7.fhir.utilities.json.JsonException; +import org.hl7.fhir.validation.special.TxTesterSorters.CodeTypeSorter; public class TxTesterSorters { + public static void main(String[] args) throws JsonException, IOException { Resource r = new JsonParser().parse(new FileInputStream(args[0])); switch (r.fhirType()) { @@ -234,7 +252,205 @@ public int compare(ParametersParameterComponent o1, ParametersParameterComponent } } + + public static void sortCapStmt(CapabilityStatement cs) { + Collections.sort(cs.getFormat(), new CodeTypeSorter()); + Collections.sort(cs.getInstantiates(), new CanonicalTypeSorter()); + Collections.sort(cs.getImports(), new CanonicalTypeSorter()); + Collections.sort(cs.getAcceptLanguage(), new CodeTypeSorter()); + Collections.sort(cs.getRest(), new CSRestSorter()); + for (CapabilityStatementRestComponent r : cs.getRest()) { + if (r.hasSecurity()) { + for (CodeableConcept cc : r.getSecurity().getService()) { + Collections.sort(cc.getCoding(), new CodingSorter()); + } + Collections.sort(r.getSecurity().getService(), new CodeableConceptSorter()); + } + Collections.sort(r.getResource(), new CSRestResourceSorter()); + for (CapabilityStatementRestResourceComponent res : r.getResource()) { + Collections.sort(res.getSupportedProfile(), new CanonicalTypeSorter()); + Collections.sort(res.getInteraction(), new CSRestResourceInteractionSorter()); + Collections.sort(res.getSearchInclude(), new StringTypeSorter()); + Collections.sort(res.getSearchRevInclude(), new StringTypeSorter()); + Collections.sort(res.getSearchParam(), new SearchParamSorter()); + Collections.sort(res.getOperation(), new CSRestResourceOperationSorter()); + } + Collections.sort(r.getInteraction(), new CSRestInteractionSorter()); + Collections.sort(r.getSearchParam(), new SearchParamSorter()); + Collections.sort(r.getOperation(), new CSRestResourceOperationSorter()); + Collections.sort(r.getCompartment(), new CanonicalTypeSorter()); + } + } + + public static class CodeTypeSorter implements Comparator { + + @Override + public int compare(CodeType o1, CodeType o2) { + return o1.asStringValue().compareTo(o2.asStringValue()); + } + + } + + public static class StringTypeSorter implements Comparator { + + @Override + public int compare(StringType o1, StringType o2) { + return o1.asStringValue().compareTo(o2.asStringValue()); + } + + } + + public static class CanonicalTypeSorter implements Comparator { + + @Override + public int compare(CanonicalType o1, CanonicalType o2) { + return o1.asStringValue().compareTo(o2.asStringValue()); + } + + } + + public static class CodingSorter implements Comparator { + + @Override + public int compare(Coding c1, Coding c2) { + if (c1.getSystem().equals(c2.getSystem())) { + return c1.getCode().compareTo(c2.getCode()); + } else { + return c1.getSystem().compareTo(c2.getSystem()); + } + } + + } + public static class CodeableConceptSorter implements Comparator { + + @Override + public int compare(CodeableConcept o1, CodeableConcept o2) { + if (o1.hasCoding() && o2.hasCoding()) { + Coding c1 = o1.getCodingFirstRep(); + Coding c2 = o2.getCodingFirstRep(); + if (c1.getSystem().equals(c2.getSystem())) { + return c1.getCode().compareTo(c2.getCode()); + } else { + return c1.getSystem().compareTo(c2.getSystem()); + } + } else { + return o1.getText().compareTo(o2.getText()); + } + } + + } + + public static class CSRestSorter implements Comparator { + + @Override + public int compare(CapabilityStatementRestComponent o1, CapabilityStatementRestComponent o2) { + return o1.getMode().compareTo(o2.getMode()); + } + + } + + public static class CSRestResourceSorter implements Comparator { + + @Override + public int compare(CapabilityStatementRestResourceComponent o1, CapabilityStatementRestResourceComponent o2) { + return o1.getType().compareTo(o2.getType()); + } + + } + + public static class CSRestResourceInteractionSorter implements Comparator { + + @Override + public int compare(ResourceInteractionComponent o1, ResourceInteractionComponent o2) { + return o1.getCode().toCode().compareTo(o2.getCode().toCode()); + } + + } + + public static class CSRestInteractionSorter implements Comparator { + + @Override + public int compare(SystemInteractionComponent o1, SystemInteractionComponent o2) { + return o1.getCode().compareTo(o2.getCode()); + } + + } - + public static class SearchParamSorter implements Comparator { + + @Override + public int compare(CapabilityStatementRestResourceSearchParamComponent o1, CapabilityStatementRestResourceSearchParamComponent o2) { + return o1.getName().compareTo(o2.getName()); + } + + } + + public static class CSRestResourceOperationSorter implements Comparator { + + @Override + public int compare(CapabilityStatementRestResourceOperationComponent o1, CapabilityStatementRestResourceOperationComponent o2) { + return o1.getName().compareTo(o2.getName()); + } + + } + + public static void sortTermCaps(TerminologyCapabilities tc) { + Collections.sort(tc.getCodeSystem(), new TCCodeSystemSorter()); + for (TerminologyCapabilitiesCodeSystemComponent t : tc.getCodeSystem()) { + Collections.sort(t.getVersion(), new TCCodeSystemVersionSorter()); + for (TerminologyCapabilitiesCodeSystemVersionComponent v : t.getVersion()) { + Collections.sort(v.getLanguage(), new LanguageSorter()); + Collections.sort(v.getProperty(), new CodeTypeSorter()); + Collections.sort(v.getFilter(), new TCCodeSystemVersionFilterSorter()); + } + } + Collections.sort(tc.getExpansion().getParameter(), new TCExpansionParameterSorter()); + } + + + public static class LanguageSorter implements Comparator> { + + @Override + public int compare(Enumeration o1, Enumeration o2) { + return o1.asStringValue().compareTo(o2.asStringValue()); + } + + } + public static class TCCodeSystemSorter implements Comparator { + + @Override + public int compare(TerminologyCapabilitiesCodeSystemComponent o1, TerminologyCapabilitiesCodeSystemComponent o2) { + return o1.getUri().compareTo(o2.getUri()); + } + + } + + public static class TCCodeSystemVersionSorter implements Comparator { + + @Override + public int compare(TerminologyCapabilitiesCodeSystemVersionComponent o1, TerminologyCapabilitiesCodeSystemVersionComponent o2) { + return o1.getCode() == null || o2.getCode() == null ? 0 : o1.getCode().compareTo(o2.getCode()); + } + + } + + public static class TCCodeSystemVersionFilterSorter implements Comparator { + + @Override + public int compare(TerminologyCapabilitiesCodeSystemVersionFilterComponent o1, TerminologyCapabilitiesCodeSystemVersionFilterComponent o2) { + return o1.getCode().compareTo(o2.getCode()); + } + } + + public static class TCExpansionParameterSorter implements Comparator { + + @Override + public int compare(TerminologyCapabilitiesExpansionParameterComponent o1, TerminologyCapabilitiesExpansionParameterComponent o2) { + return o1.getName().compareTo(o2.getName()); + } + + } + + } diff --git a/org.hl7.fhir.validation/src/test/java/org/hl7/fhir/comparison/tests/ComparisonTests.java b/org.hl7.fhir.validation/src/test/java/org/hl7/fhir/comparison/tests/ComparisonTests.java index 9f1a7bb7c6..c3c662c92f 100644 --- a/org.hl7.fhir.validation/src/test/java/org/hl7/fhir/comparison/tests/ComparisonTests.java +++ b/org.hl7.fhir.validation/src/test/java/org/hl7/fhir/comparison/tests/ComparisonTests.java @@ -245,7 +245,7 @@ private void checkOutput(String id, String name, CanonicalResource right) throws String en = Utilities.path("[tmp]", "comparison", Utilities.changeFileExt(name, ".expected.html")); TextFile.stringToFile(expected, en); - String msg = CompareUtilities.checkXMLIsSame(id, en, an); + String msg = new CompareUtilities().checkXMLIsSame(id, en, an); Assertions.assertTrue(msg == null, "Output does not match expected: "+msg); } diff --git a/org.hl7.fhir.validation/src/test/java/org/hl7/fhir/terminology/tests/LocalTerminologyServiceTests.java b/org.hl7.fhir.validation/src/test/java/org/hl7/fhir/terminology/tests/LocalTerminologyServiceTests.java index fb175b81f9..054d2560a8 100644 --- a/org.hl7.fhir.validation/src/test/java/org/hl7/fhir/terminology/tests/LocalTerminologyServiceTests.java +++ b/org.hl7.fhir.validation/src/test/java/org/hl7/fhir/terminology/tests/LocalTerminologyServiceTests.java @@ -20,7 +20,9 @@ import org.hl7.fhir.r5.model.Resource; import org.hl7.fhir.r5.test.utils.TestingUtilities; import org.hl7.fhir.utilities.Utilities; +import org.hl7.fhir.utilities.VersionUtil; import org.hl7.fhir.utilities.filesystem.ManagedFileAccess; +import org.hl7.fhir.utilities.json.JsonException; import org.hl7.fhir.utilities.json.model.JsonObject; import org.hl7.fhir.utilities.settings.FhirSettings; import org.hl7.fhir.utilities.tests.TestConfig; @@ -81,6 +83,7 @@ public static Iterable data() throws IOException { for (String id : names) { objects.add(new Object[]{id, examples.get(id)}); } + objects.add(new Object[]{"final", null}); return objects; } @@ -90,6 +93,7 @@ public static Iterable data() throws IOException { private String version = "5.0.0"; private static TxTester tester; private List modes = new ArrayList<>(); + private boolean error = false; public LocalTerminologyServiceTests(String name, JsonObjectPair setup) { this.setup = setup; @@ -107,17 +111,29 @@ public void test() throws Exception { logTestSkip("No local terminology server available."); return; } - if (SERVER != null) { - if (tester == null) { - tester = new TxTester(this, SERVER, true, externals); + if (setup == null) { + if (!error) { + System.out.println("tx.fhir.org passed all HL7 terminology service tests (mode 'tx.fhir.org', tests v"+loadVersion()+", runner v"+VersionUtil.getBaseVersion()+")"); } - String err = tester.executeTest(setup.suite, setup.test, modes); - Assertions.assertTrue(err == null, err); + Assertions.assertTrue(!error); } else { - Assertions.assertTrue(true); + if (SERVER != null) { + if (tester == null) { + tester = new TxTester(this, SERVER, true, externals); + } + String err = tester.executeTest(setup.suite, setup.test, modes); + error = error || err != null; + Assertions.assertTrue(err == null, err); + } else { + Assertions.assertTrue(true); + } } } + private String loadVersion() throws JsonException, IOException { + return TxTester.processHistoryMarkdown(TestingUtilities.loadTestResourceBytes("tx", "history.md")); + } + private void logTestSkip(String reason) { System.out.println("Skipping test: " + setup.suite.asString("name") + " " + setup.test.asString("name") + " reason: " + reason); } diff --git a/org.hl7.fhir.validation/src/test/java/org/hl7/fhir/terminology/tests/TerminologyServiceTests.java b/org.hl7.fhir.validation/src/test/java/org/hl7/fhir/terminology/tests/TerminologyServiceTests.java index f3a20c54f7..a6e617e94d 100644 --- a/org.hl7.fhir.validation/src/test/java/org/hl7/fhir/terminology/tests/TerminologyServiceTests.java +++ b/org.hl7.fhir.validation/src/test/java/org/hl7/fhir/terminology/tests/TerminologyServiceTests.java @@ -92,7 +92,8 @@ public void test() throws Exception { if (setup.getSuite().asBoolean("disabled") || setup.getTest().asBoolean("disabled")) { return; } - Resource req = loadResource(setup.getTest().asString("request")); + String reqFile = setup.getTest().asString("request"); + Resource req = reqFile == null ? null : loadResource(reqFile); String fn = setup.getTest().has("response:tx.fhir.org") ? setup.getTest().asString("response:tx.fhir.org") : setup.getTest().asString("response"); String resp = TestingUtilities.loadTestResource("tx", fn); String fp = Utilities.path("[tmp]", "tx", fn); @@ -114,7 +115,7 @@ public void test() throws Exception { } else if (setup.getTest().asString("operation").equals("cs-validate-code")) { String diff = TxServiceTestHelper.getDiffForValidation(setup.getTest().str("name"), engine.getContext(), setup.getTest().asString("name"), req, resp, setup.getTest().asString("Content-Language"), fp, ext, true); assertNull(diff, diff); - } else if (Utilities.existsInList(setup.getTest().asString("operation"), "lookup", "translate")) { + } else if (Utilities.existsInList(setup.getTest().asString("operation"), "lookup", "translate", "metadata", "term-caps")) { Assertions.assertTrue(true); // we don't test these for the internal server } else { Assertions.fail("Unknown Operation "+ setup.getTest().asString("operation")); @@ -140,7 +141,7 @@ private void expand(String id, ValidationEngine engine, Resource req, String res TxTesterSorters.sortValueSet(vse.getValueset()); TxTesterScrubbers.scrubVS(vse.getValueset(), false); String vsj = new JsonParser().setOutputStyle(OutputStyle.PRETTY).composeString(vse.getValueset()); - String diff = CompareUtilities.checkJsonSrcIsSame(id, resp, vsj, ext); + String diff = new CompareUtilities(ext).checkJsonSrcIsSame(id, resp, vsj); if (diff != null) { Utilities.createDirectory(Utilities.getDirectoryForFile(fp)); TextFile.stringToFile(vsj, fp); @@ -189,7 +190,7 @@ private void expand(String id, ValidationEngine engine, Resource req, String res TxTesterScrubbers.scrubOO(oo, false); String ooj = new JsonParser().setOutputStyle(OutputStyle.PRETTY).composeString(oo); - String diff = CompareUtilities.checkJsonSrcIsSame(id, resp, ooj, ext); + String diff = new CompareUtilities(ext).checkJsonSrcIsSame(id, resp, ooj); if (diff != null) { Utilities.createDirectory(Utilities.getDirectoryForFile(fp)); TextFile.stringToFile(ooj, fp); diff --git a/org.hl7.fhir.validation/src/test/java/org/hl7/fhir/validation/tests/StructureMappingTests.java b/org.hl7.fhir.validation/src/test/java/org/hl7/fhir/validation/tests/StructureMappingTests.java index acc1c4b4b2..c6268dfd63 100644 --- a/org.hl7.fhir.validation/src/test/java/org/hl7/fhir/validation/tests/StructureMappingTests.java +++ b/org.hl7.fhir.validation/src/test/java/org/hl7/fhir/validation/tests/StructureMappingTests.java @@ -121,11 +121,11 @@ public void test(String name, String source, String map, String output) throws E fail(e.getMessage()); } if (output.endsWith("json")) { - msg = CompareUtilities.checkJsonSrcIsSame(name, s.toString(), outputJson, null); + msg = new CompareUtilities().checkJsonSrcIsSame(name, s.toString(), outputJson); } else { TextFile.bytesToFile(s.toByteArray(), fileOutputRes); TextFile.bytesToFile(outputJson.getBytes(), fileOutputResOrig); - msg = CompareUtilities.checkXMLIsSame(name, ManagedFileAccess.inStream(fileOutputResOrig), ManagedFileAccess.inStream(fileOutputRes)); + msg = new CompareUtilities().checkXMLIsSame(name, ManagedFileAccess.inStream(fileOutputResOrig), ManagedFileAccess.inStream(fileOutputRes)); } if (!Utilities.noString(msg)) { System.out.print(s.toString());