From 6b52ee52914a9a35efa564494ce861b683926aac Mon Sep 17 00:00:00 2001 From: Grahame Grieve Date: Sun, 12 Jan 2025 23:02:40 +1100 Subject: [PATCH] rework txTester to support additional test files, and better R4/R5 logging --- .../txClient/TerminologyClientR2.java | 6 + .../txClient/TerminologyClientR3.java | 6 + .../txClient/TerminologyClientR4.java | 95 ++++++-- .../client/ITerminologyClient.java | 6 + .../client/TerminologyClientR5.java | 6 + .../org/hl7/fhir/utilities/Utilities.java | 5 + .../fhir/utilities/json/model/JsonObject.java | 22 ++ .../fhir/validation/cli/tasks/TxPackTask.java | 3 +- .../validation/cli/tasks/TxTestsTask.java | 6 +- .../hl7/fhir/validation/cli/utils/Params.java | 2 +- .../special/TxServiceTestHelper.java | 7 +- .../fhir/validation/special/TxTestData.java | 107 ++++++++- .../hl7/fhir/validation/special/TxTester.java | 210 +++++++++++++----- .../ExternalTerminologyServiceTests.java | 20 +- .../tests/LocalTerminologyServiceTests.java | 42 +++- .../terminology/tests/OntoserverTests.java | 28 ++- .../tests/TerminologyServiceTests.java | 2 +- 17 files changed, 458 insertions(+), 115 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 e6ba510b0..6efce79ec 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 @@ -265,4 +265,10 @@ public class TerminologyClientR2 implements ITerminologyClient { return (Parameters) VersionConvertorFactory_10_50.convertResource(client.translate((org.hl7.fhir.dstu2.model.Parameters) VersionConvertorFactory_10_50.convertResource(params))); } + @Override + public void setConversionLogger(ITerminologyConversionLogger logger) { + // TODO Auto-generated method stub + + } + } \ No newline at end of file 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 de07084d6..8856067a2 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 @@ -268,4 +268,10 @@ public class TerminologyClientR3 implements ITerminologyClient { return (Parameters) VersionConvertorFactory_30_50.convertResource(client.transform((org.hl7.fhir.dstu3.model.Parameters) VersionConvertorFactory_30_50.convertResource(params))); } + @Override + public void setConversionLogger(ITerminologyConversionLogger logger) { + // TODO Auto-generated method stub + + } + } \ No newline at end of file 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 b4aaa69f0..bfcd9267d 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 @@ -11,6 +11,8 @@ import org.hl7.fhir.exceptions.FHIRException; import org.hl7.fhir.r4.model.Resource; import org.hl7.fhir.r4.utils.client.EFhirClientException; import org.hl7.fhir.r4.utils.client.FHIRToolingClient; +import org.hl7.fhir.r5.formats.IParser.OutputStyle; +import org.hl7.fhir.r5.formats.JsonParser; import org.hl7.fhir.r5.model.Bundle; import org.hl7.fhir.r5.model.CanonicalResource; import org.hl7.fhir.r5.model.CapabilityStatement; @@ -28,9 +30,10 @@ import org.hl7.fhir.utilities.http.HTTPHeader; public class TerminologyClientR4 implements ITerminologyClient { - private final FHIRToolingClient client; // todo: use the R2 client + private final FHIRToolingClient client; private ClientHeaders clientHeaders; private String id; + private ITerminologyConversionLogger logger; public TerminologyClientR4(String id, String address, String userAgent) throws URISyntaxException { this.client = new FHIRToolingClient(address, userAgent); @@ -71,7 +74,7 @@ public class TerminologyClientR4 implements ITerminologyClient { @Override public TerminologyCapabilities getTerminologyCapabilities() throws FHIRException { - return (TerminologyCapabilities) VersionConvertorFactory_40_50.convertResource(client.getTerminologyCapabilities()); + return (TerminologyCapabilities) convertResource("getTerminologyCapabilities.response", client.getTerminologyCapabilities()); } @Override @@ -81,29 +84,30 @@ public class TerminologyClientR4 implements ITerminologyClient { @Override public ValueSet expandValueset(ValueSet vs, Parameters p) throws FHIRException { - org.hl7.fhir.r4.model.ValueSet vs2 = vs == null ? null : (org.hl7.fhir.r4.model.ValueSet) VersionConvertorFactory_40_50.convertResource(vs); - org.hl7.fhir.r4.model.Parameters p2 = p == null ? null : (org.hl7.fhir.r4.model.Parameters) VersionConvertorFactory_40_50.convertResource(p); + org.hl7.fhir.r4.model.ValueSet vs2 = vs == null ? null : (org.hl7.fhir.r4.model.ValueSet) convertResource("expandValueset.valueset", vs); + org.hl7.fhir.r4.model.Parameters p2 = p == null ? null : (org.hl7.fhir.r4.model.Parameters) convertResource("expandValueset.parameters", p); try { vs2 = client.expandValueset(vs2, p2); // todo: second parameter - return (ValueSet) VersionConvertorFactory_40_50.convertResource(vs2); + return (ValueSet) convertResource("expandValueset.response", vs2); } catch (org.hl7.fhir.r4.utils.client.EFhirClientException e) { if (e.getServerErrors().size() > 0) { - throw new org.hl7.fhir.r5.utils.client.EFhirClientException(e.getCode(), e.getMessage(), (org.hl7.fhir.r5.model.OperationOutcome) VersionConvertorFactory_40_50.convertResource(e.getServerErrors().get(0))); + throw new org.hl7.fhir.r5.utils.client.EFhirClientException(e.getCode(), e.getMessage(), (org.hl7.fhir.r5.model.OperationOutcome) convertResource("expandValueset.error", e.getServerErrors().get(0))); } else { throw new org.hl7.fhir.r5.utils.client.EFhirClientException(e.getCode(), e.getMessage()); } } } + @Override public Parameters validateCS(Parameters pin) throws FHIRException { try { - org.hl7.fhir.r4.model.Parameters p2 = (org.hl7.fhir.r4.model.Parameters) VersionConvertorFactory_40_50.convertResource(pin); + org.hl7.fhir.r4.model.Parameters p2 = (org.hl7.fhir.r4.model.Parameters) convertResource("validateCS.request", pin); p2 = client.operateType(org.hl7.fhir.r4.model.CodeSystem.class, "validate-code", p2); - return (Parameters) VersionConvertorFactory_40_50.convertResource(p2); + return (Parameters) convertResource("validateCS.response", p2); } catch (EFhirClientException e) { if (e.getServerErrors().size() == 1) { - OperationOutcome op = (OperationOutcome) VersionConvertorFactory_40_50.convertResource(e.getServerErrors().get(0)); + OperationOutcome op = (OperationOutcome) convertResource("validateCS.error", e.getServerErrors().get(0)); throw new org.hl7.fhir.r5.utils.client.EFhirClientException(e.getCode(), e.getMessage(), op, e); } else { throw new org.hl7.fhir.r5.utils.client.EFhirClientException(e.getCode(), e.getMessage(), e); @@ -117,12 +121,12 @@ public class TerminologyClientR4 implements ITerminologyClient { @Override public Parameters subsumes(Parameters pin) throws FHIRException { try { - org.hl7.fhir.r4.model.Parameters p2 = (org.hl7.fhir.r4.model.Parameters) VersionConvertorFactory_40_50.convertResource(pin); + org.hl7.fhir.r4.model.Parameters p2 = (org.hl7.fhir.r4.model.Parameters) convertResource("subsumes.request", pin); p2 = client.operateType(org.hl7.fhir.r4.model.CodeSystem.class, "subsumes", p2); - return (Parameters) VersionConvertorFactory_40_50.convertResource(p2); + return (Parameters) convertResource("subsumes.response", p2); } catch (EFhirClientException e) { if (e.getServerErrors().size() == 1) { - OperationOutcome op = (OperationOutcome) VersionConvertorFactory_40_50.convertResource(e.getServerErrors().get(0)); + OperationOutcome op = (OperationOutcome) convertResource("subsumes.error", e.getServerErrors().get(0)); throw new org.hl7.fhir.r5.utils.client.EFhirClientException(e.getCode(), e.getMessage(), op, e); } else { throw new org.hl7.fhir.r5.utils.client.EFhirClientException(e.getCode(), e.getMessage(), e); @@ -135,12 +139,12 @@ public class TerminologyClientR4 implements ITerminologyClient { @Override public Parameters validateVS(Parameters pin) throws FHIRException { try { - org.hl7.fhir.r4.model.Parameters p2 = (org.hl7.fhir.r4.model.Parameters) VersionConvertorFactory_40_50.convertResource(pin); + org.hl7.fhir.r4.model.Parameters p2 = (org.hl7.fhir.r4.model.Parameters) convertResource("validateVS.request", pin); p2 = client.operateType(org.hl7.fhir.r4.model.ValueSet.class, "validate-code", p2); - return (Parameters) VersionConvertorFactory_40_50.convertResource(p2); + return (Parameters) convertResource("validateVS.response", p2); } catch (EFhirClientException e) { if (e.getServerErrors().size() == 1) { - OperationOutcome op = (OperationOutcome) VersionConvertorFactory_40_50.convertResource(e.getServerErrors().get(0)); + OperationOutcome op = (OperationOutcome) convertResource("validateVS.error", e.getServerErrors().get(0)); throw new org.hl7.fhir.r5.utils.client.EFhirClientException(e.getCode(), e.getMessage(), op, e); } else { throw new org.hl7.fhir.r5.utils.client.EFhirClientException(e.getCode(), e.getMessage(), e); @@ -175,22 +179,22 @@ public class TerminologyClientR4 implements ITerminologyClient { @Override public CapabilityStatement getCapabilitiesStatementQuick() throws FHIRException { - return (CapabilityStatement) VersionConvertorFactory_40_50.convertResource(client.getCapabilitiesStatementQuick()); + return (CapabilityStatement) convertResource("getCapabilitiesStatementQuick.response", client.getCapabilitiesStatementQuick()); } @Override public CapabilityStatement getCapabilitiesStatement() throws FHIRException { - return (CapabilityStatement) VersionConvertorFactory_40_50.convertResource(client.getCapabilitiesStatement()); + return (CapabilityStatement) convertResource("getCapabilitiesStatement.response", client.getCapabilitiesStatement()); } @Override public Parameters lookupCode(Map params) throws FHIRException { - return (Parameters) VersionConvertorFactory_40_50.convertResource(client.lookupCode(params)); + return (Parameters) convertResource("lookupCode.response", client.lookupCode(params)); } @Override public Parameters lookupCode(Parameters params) throws FHIRException { - return (Parameters) VersionConvertorFactory_40_50.convertResource(client.lookupCode((org.hl7.fhir.r4.model.Parameters) VersionConvertorFactory_40_50.convertResource(params))); + return (Parameters) convertResource("lookupCode.response", client.lookupCode((org.hl7.fhir.r4.model.Parameters) convertResource("lookupCode.request", params))); } @Override @@ -200,8 +204,8 @@ public class TerminologyClientR4 implements ITerminologyClient { @Override public Bundle validateBatch(Bundle batch) { - org.hl7.fhir.r4.model.Bundle result = client.transaction((org.hl7.fhir.r4.model.Bundle) VersionConvertorFactory_40_50.convertResource(batch)); - return result == null ? null : (Bundle) VersionConvertorFactory_40_50.convertResource(result); + org.hl7.fhir.r4.model.Bundle result = client.transaction((org.hl7.fhir.r4.model.Bundle) convertResource("validateBatch.request", batch)); + return result == null ? null : (Bundle) convertResource("validateBatch.response", result); } @Override @@ -216,7 +220,7 @@ public class TerminologyClientR4 implements ITerminologyClient { if (r4 == null) { throw new FHIRException("Unable to fetch resource " + Utilities.pathURL(getAddress(), type, id)); } - org.hl7.fhir.r5.model.Resource r5 = VersionConvertorFactory_40_50.convertResource(r4); + org.hl7.fhir.r5.model.Resource r5 = convertResource("read.result", r4); if (r5 == null) { throw new FHIRException("Unable to convert resource " + Utilities.pathURL(getAddress(), type, id) + " to R5 (internal representation)"); } @@ -278,12 +282,55 @@ public class TerminologyClientR4 implements ITerminologyClient { @Override public Bundle search(String type, String criteria) { org.hl7.fhir.r4.model.Bundle result = client.search(type, criteria); - return result == null ? null : (Bundle) VersionConvertorFactory_40_50.convertResource(result); + return result == null ? null : (Bundle) convertResource("search.result", result); } @Override public Parameters translate(Parameters params) throws FHIRException { - return (Parameters) VersionConvertorFactory_40_50.convertResource(client.translate((org.hl7.fhir.r4.model.Parameters) VersionConvertorFactory_40_50.convertResource(params))); + return (Parameters) convertResource("translate.response", client.translate((org.hl7.fhir.r4.model.Parameters) convertResource("translate.request", params))); + } + + private org.hl7.fhir.r4.model.Resource convertResource(String name, org.hl7.fhir.r5.model.Resource resource) { + if (logger != null) { + try { + logger.log(name, resource.fhirType(), "r5", new org.hl7.fhir.r5.formats.JsonParser().setOutputStyle(OutputStyle.PRETTY).composeBytes(resource)); + } catch (IOException e) { + throw new FHIRException(e); + } + } + org.hl7.fhir.r4.model.Resource res = VersionConvertorFactory_40_50.convertResource(resource); + if (logger != null) { + try { + logger.log(name, resource.fhirType(), "r4", new org.hl7.fhir.r4.formats.JsonParser().setOutputStyle(org.hl7.fhir.r4.formats.IParser.OutputStyle.PRETTY).composeBytes(res)); + } catch (IOException e) { + throw new FHIRException(e); + } + } + return res; + } + + private org.hl7.fhir.r5.model.Resource convertResource(String name, org.hl7.fhir.r4.model.Resource resource) { + if (logger != null && name != null) { + try { + logger.log(name, resource.fhirType(), "r4", new org.hl7.fhir.r4.formats.JsonParser().setOutputStyle(org.hl7.fhir.r4.formats.IParser.OutputStyle.PRETTY).composeBytes(resource)); + } catch (IOException e) { + throw new FHIRException(e); + } + } + org.hl7.fhir.r5.model.Resource res = VersionConvertorFactory_40_50.convertResource(resource); + if (logger != null && name != null) { + try { + logger.log(name, resource.fhirType(), "r5", new org.hl7.fhir.r5.formats.JsonParser().setOutputStyle(OutputStyle.PRETTY).composeBytes(res)); + } catch (IOException e) { + throw new FHIRException(e); + } + } + return res; + } + + @Override + public void setConversionLogger(ITerminologyConversionLogger logger) { + this.logger = logger; } } \ No newline at end of file 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 fec587dce..0cddd0e98 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 @@ -76,4 +76,10 @@ public interface ITerminologyClient { String getUserAgent(); int getUseCount(); Bundle search(String type, String criteria); + + // internal conversion logging + public interface ITerminologyConversionLogger { + void log(String name, String resourceType, String version, byte[] cnt); + } + void setConversionLogger(ITerminologyConversionLogger logger); } \ No newline at end of file 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 9946c583b..a3baf66fb 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 @@ -275,5 +275,11 @@ public class TerminologyClientR5 implements ITerminologyClient { return client.translate(params); } + @Override + public void setConversionLogger(ITerminologyConversionLogger logger) { + // TODO Auto-generated method stub + + } + } \ No newline at end of file diff --git a/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/Utilities.java b/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/Utilities.java index d9baeb931..d3efecee4 100644 --- a/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/Utilities.java +++ b/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/Utilities.java @@ -477,6 +477,11 @@ public class Utilities { return ManagedFileAccess.file(path); } + public static File createDirectoryNC(String path) throws IOException { + ManagedFileAccess.file(path).mkdirs(); + return ManagedFileAccess.file(path); + } + public static String changeFileExt(String name, String ext) { if (name.lastIndexOf('.') > -1) return name.substring(0, name.lastIndexOf('.')) + ext; diff --git a/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/json/model/JsonObject.java b/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/json/model/JsonObject.java index c64b6d0e2..31ee4859e 100644 --- a/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/json/model/JsonObject.java +++ b/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/json/model/JsonObject.java @@ -35,6 +35,18 @@ public class JsonObject extends JsonElement { propMap.put(name, p); return this; } + + public JsonObject add(int index, String name, JsonElement value) throws JsonException { + check(name != null, "Json Property Name is null"); + check(value != null, "Json Property Value is null"); + if (get(name) != null) { + check(false, "Name '"+name+"' already exists (value = "+get(name).toString()+")"); + } + JsonProperty p = new JsonProperty(name, value); + properties.add(index, p); + propMap.put(name, p); + return this; + } public JsonObject addIfNotNull(String name, JsonElement value) throws JsonException { if (value != null) { @@ -347,6 +359,16 @@ public class JsonObject extends JsonElement { } return getJsonArray(name); } + + public JsonArray forceArray(int index, String name) throws JsonException { + if (has(name) && !hasArray(name)) { + remove(name); + } + if (!has(name)) { + add(index, name, new JsonArray()); + } + return getJsonArray(name); + } public List getJsonObjects(String name) { List res = new ArrayList<>(); diff --git a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/cli/tasks/TxPackTask.java b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/cli/tasks/TxPackTask.java index c79439399..efb8067f4 100644 --- a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/cli/tasks/TxPackTask.java +++ b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/cli/tasks/TxPackTask.java @@ -6,6 +6,7 @@ import java.io.PrintStream; import org.hl7.fhir.r5.context.IWorkerContext; import org.hl7.fhir.r5.elementmodel.Manager.FhirFormat; import org.hl7.fhir.utilities.TimeTracker; +import org.hl7.fhir.utilities.filesystem.ManagedFileAccess; import org.hl7.fhir.validation.ValidationEngine; import org.hl7.fhir.validation.cli.model.CliContext; import org.hl7.fhir.validation.cli.services.ValidationService; @@ -47,7 +48,7 @@ public class TxPackTask extends ValidationEngineTask { String pid = cliContext.getPackageName(); boolean json = cliContext.getFormat() != FhirFormat.XML; String output = cliContext.getOutput(); - File f = new File(output); + File f = ManagedFileAccess.file(output); ExpansionPackageGeneratorOutputType t = ExpansionPackageGeneratorOutputType.FOLDER; if (f.exists() && f.isDirectory()) { t = ExpansionPackageGeneratorOutputType.FOLDER; diff --git a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/cli/tasks/TxTestsTask.java b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/cli/tasks/TxTestsTask.java index 3a9ce8891..d6aba79d2 100644 --- a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/cli/tasks/TxTestsTask.java +++ b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/cli/tasks/TxTestsTask.java @@ -49,7 +49,11 @@ public class TxTestsTask extends StandaloneTask{ if (output == null ) { output = Utilities.path("[tmp]"); } - boolean ok = new TxTester(new TxTester.InternalTxLoader(version), tx, false, loadExternals(externals)).setOutput(output).execute(cliContext.getModeParams(), filter); + TxTester txTester = new TxTester(new TxTester.InternalTxLoader(version), tx, false, loadExternals(externals)); + for (String input : cliContext.getInputs()) { + txTester.addLoader(new TxTester.InternalTxLoader(input, true)); + } + boolean ok = txTester.setOutput(output).execute(cliContext.getModeParams(), filter); SystemExitManager.setError(ok ? 0 : 1); SystemExitManager.finish(); } diff --git a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/cli/utils/Params.java b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/cli/utils/Params.java index 05eb8304f..61d69fb0f 100644 --- a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/cli/utils/Params.java +++ b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/cli/utils/Params.java @@ -405,7 +405,7 @@ public class Params { cliContext.setOutputStyle(args[++i]); } else if (args[i].equals(ADVSIOR_FILE)) { cliContext.setAdvisorFile(args[++i]); - File f = new File(cliContext.getAdvisorFile()); + File f = ManagedFileAccess.file(cliContext.getAdvisorFile()); if (!f.exists()) { throw new Error("Cannot find advisor file "+cliContext.getAdvisorFile()); } else if (!Utilities.existsInList(Utilities.getFileExtension(f.getName()), "json", "txt")) { 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 cb8a0040d..2947ba3f7 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 @@ -12,6 +12,7 @@ import org.hl7.fhir.r5.test.utils.CompareUtilities; import org.hl7.fhir.utilities.FhirPublication; import org.hl7.fhir.utilities.TextFile; import org.hl7.fhir.utilities.Utilities; +import org.hl7.fhir.utilities.filesystem.ManagedFileAccess; import org.hl7.fhir.utilities.i18n.I18nConstants; import org.hl7.fhir.utilities.json.model.JsonObject; import org.hl7.fhir.utilities.validation.ValidationOptions; @@ -174,7 +175,7 @@ public class TxServiceTestHelper { parameters.addParameter(validationResult.getErrorClass() == TerminologyServiceErrorClass.CODESYSTEM_UNSUPPORTED ? "x-caused-by-unknown-system" : "x-unknown-system", new CanonicalType(s)); } } - if (validationResult.getIssues().size() > 0) { + if (validationResult.getIssues().size() > 0) { operationOutcome = new OperationOutcome(); operationOutcome.getIssue().addAll(validationResult.getIssues()); parameters.addParameter().setName("issues").setResource(operationOutcome); @@ -205,12 +206,12 @@ public class TxServiceTestHelper { } String fullExpected = rootDirectory + "/expected/"; String fullActual = rootDirectory + "/actual/"; - File expectedDirectory = new File(fullExpected); + File expectedDirectory = ManagedFileAccess.file(fullExpected); if (!expectedDirectory.exists()) { expectedDirectory.mkdirs(); } - File actualDirectory = new File(fullActual); + File actualDirectory = ManagedFileAccess.file(fullActual); if (!actualDirectory.exists()) { actualDirectory.mkdirs(); } diff --git a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/special/TxTestData.java b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/special/TxTestData.java index 42dbcc0d3..b6311d5ec 100644 --- a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/special/TxTestData.java +++ b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/special/TxTestData.java @@ -3,13 +3,17 @@ package org.hl7.fhir.validation.special; import lombok.Getter; import org.hl7.fhir.r5.test.utils.TestingUtilities; import org.hl7.fhir.utilities.TextFile; +import org.hl7.fhir.utilities.Utilities; +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.json.parser.JsonParser; import org.hl7.fhir.utilities.npm.FilesystemPackageCacheManager; import org.hl7.fhir.utilities.npm.NpmPackage; +import java.io.File; import java.io.IOException; +import java.io.InputStream; import java.util.*; public class TxTestData { @@ -24,17 +28,74 @@ public class TxTestData { private final List testData; private final NpmPackage npm; + private final File folder; + private final String code; + private final String version; + private final String testFileName; - private TxTestData(List testData, JsonObject manifest, JsonObject externals, NpmPackage npm) throws IOException { + private TxTestData(List testData, JsonObject manifest, JsonObject externals, NpmPackage npm, String code, String version) throws IOException { this.testData = testData; this.manifest = manifest; this.externals = externals; this.npm = npm; + this.folder = null; + this.code = code; + this.version = version; + this.testFileName = "test-cases.json"; + } + + private TxTestData(List testData, JsonObject manifest, JsonObject externals, File folder, String filename, String code, String version) throws IOException { + this.testData = testData; + this.manifest = manifest; + this.externals = externals; + this.npm = null; + this.folder = folder; + this.code = code; + this.version = version; + this.testFileName = filename; } - public static TxTestData loadTestDataFromPackage(String version) throws IOException { + public static TxTestData loadTestDataFromFolder(File folder, String name) throws IOException { + + String contents = TextFile.streamToString(loadFile(folder, name)); + String externalSource = ManagedFileAccess.file(folder.getAbsolutePath(), "messages-tx.fhir.org.json").exists() ? + TextFile.streamToString(loadFile(folder, "messages-tx.fhir.org.json")) : null; + JsonObject externals = externalSource == null ? new JsonObject() : org.hl7.fhir.utilities.json.parser.JsonParser.parseObject(externalSource); + + Map examples = new HashMap(); + JsonObject manifest = org.hl7.fhir.utilities.json.parser.JsonParser.parseObject(contents); + + for (JsonObject suite : manifest.getJsonObjects("suites")) { + if (!"tx.fhir.org".equals(suite.asString("mode"))) { + String sn = suite.asString("name"); + for (JsonObject test : suite.getJsonObjects("tests")) { + String tn = test.asString("name"); + examples.put(sn + "." + tn, new TxTestSetup(suite, test)); + } + } + } + + List names = new ArrayList(examples.size()); + names.addAll(examples.keySet()); + Collections.sort(names); + + List testData = new ArrayList(examples.size()); + for (String id : names) { + testData.add(new Object[]{id, examples.get(id)}); + } + + return new TxTestData(testData, manifest, externals, folder, name, manifest.asString("code"), manifest.asString("version")); + } + + private static InputStream loadFile(File folder, String filename) throws IOException { + File f = ManagedFileAccess.file(Utilities.path(folder.getAbsolutePath(), filename)); + + return ManagedFileAccess.inStream(f); + } + + public static TxTestData loadTestDataFromPackage(String source) throws IOException { FilesystemPackageCacheManager pcm = new FilesystemPackageCacheManager.Builder().build(); - NpmPackage npm = pcm.loadPackage("hl7.fhir.uv.tx-ecosystem", version); + NpmPackage npm = pcm.loadPackage(source); String contents = TextFile.streamToString(npm.load("tests", "test-cases.json")); String externalSource = TextFile.streamToString(npm.load("tests", "messages-tx.fhir.org.json")); @@ -61,23 +122,39 @@ public class TxTestData { testData.add(new Object[]{id, examples.get(id)}); } - return new TxTestData(testData, manifest, externals, npm); + return new TxTestData(testData, manifest, externals, npm, manifest.asString("code"), manifest.asString("version")); } public String load(String fn) throws IOException { - return TextFile.streamToString(npm.load("tests", fn)); + if (folder != null) { + return TextFile.streamToString(loadFile(folder, fn)); + } else { + return TextFile.streamToString(npm.load("tests", fn)); + } } public byte[] loadBytes(String fn) throws IOException { - return TextFile.streamToBytes(npm.load("tests", fn)); + if (folder != null) { + return TextFile.streamToBytes(loadFile(folder, fn)); + } else { + return TextFile.streamToBytes(npm.load("tests", fn)); + } } public boolean hasFile(String filename) throws IOException { - return npm.hasFile("tests", filename); + if (folder != null) { + return ManagedFileAccess.file(Utilities.path(folder.getAbsolutePath(), filename)).exists(); + } else { + return npm.hasFile("tests", filename); + } } public String loadVersion() throws JsonException, IOException { - return readHistory(loadBytes("history.json")); + if (version == null) { + return readHistory(loadBytes("history.json")); + } else { + return version; + } } private String readHistory(byte[] content) throws JsonException, IOException { @@ -86,7 +163,19 @@ public class TxTestData { } public String describe() { - return npm.name()+"#"+npm.version(); + if (folder != null) { + return folder.getAbsolutePath(); + } else { + return npm.name()+"#"+npm.version(); + } + } + + public String code() { + return code; + } + + public String testFileName() { + return testFileName; } 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 428657315..5cab0c76a 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 @@ -38,6 +38,7 @@ 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.terminologies.client.ITerminologyClient.ITerminologyConversionLogger; import org.hl7.fhir.r5.test.utils.CompareUtilities; import org.hl7.fhir.r5.utils.client.EFhirClientException; import org.hl7.fhir.r5.utils.client.network.ClientHeaders; @@ -73,12 +74,42 @@ public class TxTester { public Resource loadResource(String filename) throws IOException, FHIRFormatError, FileNotFoundException, FHIRException, DefinitionException; public byte[] loadContent(String filename) throws FileNotFoundException, IOException; public boolean hasContent(String filename) throws IOException; + public String code(); + public String version() throws JsonException, IOException; + public String testFileName(); + } + + private class TxTesterConversionLogger implements ITerminologyConversionLogger { + + public String suiteName; + public String testName; + + @Override + public void log(String name, String resourceType, String version, byte[] cnt) { + if (!"expandValueset.response".equals(name)) { + return; + } + + String base; + try { + base = Utilities.path(outputDir, "conversions"); + if (ManagedFileAccess.file(base).exists()) { + String dir = Utilities.path(base, version, suiteName); + Utilities.createDirectory(dir); + String filename = Utilities.path(dir, testName+"."+resourceType+".json"); + TextFile.bytesToFile(cnt, filename); + } + } catch (IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } } private String server; - private ITxTesterLoader loader; + private List loaders = new ArrayList<>(); private String error; - private String output; + private String outputDir; private ITerminologyClient terminologyClient; private boolean tight; private JsonObject externals; @@ -86,33 +117,44 @@ public class TxTester { private List fails = new ArrayList<>(); private CapabilityStatement cstmt; private TerminologyCapabilities tc; + private TxTesterConversionLogger conversionLogger; public TxTester(ITxTesterLoader loader, String server, boolean tight, JsonObject externals) { super(); this.server = server; - this.loader = loader; + this.loaders.add(loader); this.tight = tight; this.externals = externals; + conversionLogger = new TxTesterConversionLogger(); } public static void main(String[] args) throws Exception { new TxTester(new InternalTxLoader(args[0]), args[1], "true".equals(args[2]), args.length == 5 ? JsonParser.parseObjectFromFile(args[4]) : null).execute(new ArrayList<>(), args[3]); } + public void addLoader(ITxTesterLoader loader) { + this.loaders.add(loader); + } + public boolean execute(List modes, String filter) throws IOException, URISyntaxException { - if (output == null) { - output = Utilities.path("[tmp]", serverId()); + if (outputDir == null) { + outputDir = Utilities.path("[tmp]", serverId()); } System.out.println("Run terminology service Tests"); - System.out.println(" Source for tests: "+loader.describe()); - System.out.println(" Output Directory: "+output); - if (!new File(output).exists()) { - Utilities.createDirectory(output); + System.out.println(" Source for tests: "+loaders.get(0).describe()); + for (ITxTesterLoader loader : loaders) { + if (loader != loaders.get(0)) { + System.out.println(" Additional Tests: "+loader.describe()); + } } - if (!new File(output).exists()) { - throw new IOException("Unable to create output directory "+output); + System.out.println(" Output Directory: "+outputDir); + if (!ManagedFileAccess.file(outputDir).exists()) { + Utilities.createDirectory(outputDir); + } + if (!ManagedFileAccess.file(outputDir).exists()) { + throw new IOException("Unable to create output directory "+outputDir); } System.out.println(" Term Service Url: "+server); System.out.println(" External Strings: "+(externals != null)); @@ -121,32 +163,37 @@ public class TxTester { if (filter != null) { System.out.println(" Filter Parameter: "+filter); } - + IntHolder counter = new IntHolder(); + IntHolder errCount = new IntHolder(); JsonObject json = new JsonObject(); + List versions = new ArrayList(); json.add("date", new SimpleDateFormat("EEE, MMM d, yyyy HH:mmZ", new Locale("en", "US")).format(Calendar.getInstance().getTime()) + timezone()); try { - JsonObject tests = loadTests(); terminologyClient = 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, modes, filter, json.forceArray("suites"), counter) && ok; + for (ITxTesterLoader loader : loaders) { + JsonObject tests = loadTests(loader); + versions.add(new StringPair(loader.code(), loader.version())); + for (JsonObject suite : tests.getJsonObjects("suites")) { + if ((!suite.has("mode") || modes.contains(suite.asString("mode")))) { + if (suite.asBoolean("disabled")) { + // ok = true; + } else { + ok = runSuite(loader, suite, modes, filter, json.forceArray("suites"), counter, errCount) && ok; + } } } } - TextFile.stringToFile(JsonParser.compose(json, true), Utilities.path(output, "test-results.json")); + TextFile.stringToFile(JsonParser.compose(json, true), Utilities.path(outputDir, "test-results.json")); if (filter == null) { String m = modes.isEmpty() ? "[none]" : CommaSeparatedStringBuilder.join(";", modes); if (ok) { - System.out.println(software+" passed all "+counter.total()+" HL7 terminology service tests ("+Utilities.pluralize("mode", modes.size())+" "+m+", tests v"+loadVersion()+", runner v"+VersionUtil.getBaseVersion()+")"); + System.out.println(software+" passed all "+counter.total()+" HL7 terminology service tests ("+Utilities.pluralize("mode", modes.size())+" "+m+", tests v"+vString(versions)+", runner v"+VersionUtil.getBaseVersion()+")"); return true; } else { - System.out.println(software+" did not pass all "+counter.total()+" HL7 terminology service tests ("+Utilities.pluralize("mode", modes.size())+" "+m+", tests v"+loadVersion()+", runner v"+VersionUtil.getBaseVersion()+")"); + System.out.println(software+" failed "+errCount.total()+" of "+counter.total()+" HL7 terminology service tests ("+Utilities.pluralize("mode", modes.size())+" "+m+", tests v"+vString(versions)+", runner v"+VersionUtil.getBaseVersion()+")"); System.out.println("Failed Tests: "+ CommaSeparatedStringBuilder.join(",", fails )); return false; } @@ -162,6 +209,24 @@ public class TxTester { } + private String vString(List versions) { + StringBuilder b = new StringBuilder(); + b.append(versions.get(0).getValue()); + if (versions.size() > 1) { + b.append("["); + for (int i = 1; i < versions.size(); i++) { + if (i > 1) { + b.append(","); + } + b.append(versions.get(i).getName()); + b.append(":"); + b.append(versions.get(i).getValue()); + } + b.append("]"); + } + return b.toString(); + } + private String timezone() { TimeZone tz = TimeZone.getDefault(); Calendar cal = GregorianCalendar.getInstance(tz); @@ -174,6 +239,8 @@ public class TxTester { } private boolean checkClient() { + conversionLogger.suiteName = "connect"; + conversionLogger.testName = "checkClient"; cstmt = terminologyClient.getCapabilitiesStatement(); if (cstmt.hasSoftware()) { software = cstmt.getSoftware().getName()+" v"+cstmt.getSoftware().getVersion(); @@ -182,75 +249,76 @@ public class TxTester { return true; } - private JsonObject loadTests() throws JsonException, IOException { + private JsonObject loadTests(ITxTesterLoader loader) throws JsonException, IOException { System.out.println("Load Tests from "+loader.describe()); - return JsonParser.parseObject(loader.loadContent("test-cases.json")); + return JsonParser.parseObject(loader.loadContent(loader.testFileName())); } - public String loadVersion() throws JsonException, IOException { - if (loader.hasContent("history.json")) { - return readHistory(loader.loadContent("history.json")); - } else { - throw new Error("history.md is no longer supported"); - } - } - - private String readHistory(byte[] content) throws JsonException, IOException { - JsonObject json = JsonParser.parseObject(content); - return json.getJsonObjects("versions").get(0).asString("version"); - } private ITerminologyClient connectToServer(List modes) throws URISyntaxException, IOException { System.out.println("Connect to "+server); software = server; + + if (outputDir == null) { + outputDir = Utilities.path("[tmp]", serverId()); + } + + // todo: we don't necessarily want R4: + Utilities.createDirectory(Utilities.path(outputDir, "conversions", "r4")); + Utilities.createDirectory(Utilities.path(outputDir, "conversions", "r5")); ITerminologyClient client = new TerminologyClientFactory(FhirPublication.R4).makeClient("Test-Server", server, "Tools/Java", null); + client.setConversionLogger(conversionLogger); return client; } - public String executeTest(JsonObject suite, JsonObject test, List modes) throws URISyntaxException, FHIRFormatError, FileNotFoundException, IOException { + public String executeTest(ITxTesterLoader loader, JsonObject suite, JsonObject test, List modes) throws URISyntaxException, FHIRFormatError, FileNotFoundException, IOException { error = null; if (terminologyClient == null) { terminologyClient = connectToServer(modes); checkClient(); } - List setup = loadSetupResources(suite); + List setup = loadSetupResources(loader, suite); - if (runTest(suite, test, setup, modes, "*", null, new IntHolder())) { + if (runTest(loader, suite, test, setup, modes, "*", null, new IntHolder())) { return null; } else { return error; } } - private boolean runSuite(JsonObject suite, List modes, String filter, JsonArray output, IntHolder counter) throws FHIRFormatError, FileNotFoundException, IOException { + private boolean runSuite(ITxTesterLoader loader, JsonObject suite, List modes, String filter, JsonArray output, IntHolder counter, IntHolder errCount) throws FHIRFormatError, FileNotFoundException, IOException { System.out.println("Group "+suite.asString("name")); JsonObject outputS = new JsonObject(); if (output != null) { output.add(outputS); } outputS.add("name", suite.asString("name")); - List setup = loadSetupResources(suite); + List setup = loadSetupResources(loader, suite); boolean ok = true; for (JsonObject test : suite.getJsonObjects("tests")) { if ((!test.has("mode") || modes.contains(test.asString("mode")))) { if (test.asBoolean("disabled")) { ok = true; } else { - ok = runTest(suite, test, setup, modes, filter, outputS.forceArray("tests"), counter) && ok; + boolean tok = runTest(loader, suite, test, setup, modes, filter, outputS.forceArray("tests"), counter); + if (!tok) { + errCount.count(); + } + ok = tok && ok; } } } return ok; } - private boolean runTest(JsonObject suite, JsonObject test, List setup, List modes, String filter, JsonArray output, IntHolder counter) throws FHIRFormatError, DefinitionException, FileNotFoundException, FHIRException, IOException { + private boolean runTest(ITxTesterLoader loader, JsonObject suite, JsonObject test, List setup, List modes, String filter, JsonArray output, IntHolder counter) throws FHIRFormatError, DefinitionException, FileNotFoundException, FHIRException, IOException { JsonObject outputT = new JsonObject(); if (output != null) { output.add(outputT); } long start = System.currentTimeMillis(); - Parameters profile = loadProfile(test); + Parameters profile = loadProfile(loader, test); outputT.add("name", test.asString("name")); if (Utilities.noString(filter) || filter.equals("*") || test.asString("name").contains(filter)) { System.out.print(" Test "+test.asString("name")+": "); @@ -264,13 +332,14 @@ public class TxTester { terminologyClient.setClientHeaders(new ClientHeaders(List.of(header))); } } - + conversionLogger.suiteName = suite.asString("name"); + conversionLogger.testName = test.asString("name"); 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)); - String fp = this.output == null ? Utilities.path("[tmp]", serverId(), fn) : Utilities.path(this.output, fn); + String fp = this.outputDir == null ? Utilities.path("[tmp]", serverId(), fn) : Utilities.path(this.outputDir, fn); File fo = ManagedFileAccess.file(fp); if (fo.exists()) { fo.delete(); @@ -373,7 +442,7 @@ public class TxTester { return test.asString(name); } - private Parameters loadProfile(JsonObject test) throws FHIRFormatError, DefinitionException, FileNotFoundException, FHIRException, IOException { + private Parameters loadProfile(ITxTesterLoader loader, JsonObject test) throws FHIRFormatError, DefinitionException, FileNotFoundException, FHIRException, IOException { if (test.has("profile")) { return (Parameters) loader.loadResource(test.asString("profile")); } else { @@ -560,7 +629,7 @@ public class TxTester { } - private List loadSetupResources(JsonObject suite) throws FHIRFormatError, FileNotFoundException, IOException { + private List loadSetupResources(ITxTesterLoader loader, JsonObject suite) throws FHIRFormatError, FileNotFoundException, IOException { List res = new ArrayList<>(); for (String s : suite.getStrings("setup")) { res.add(loader.loadResource(s)); @@ -569,27 +638,44 @@ public class TxTester { } public String getOutput() { - return output; + return outputDir; } public TxTester setOutput(String output) { - this.output = output; + this.outputDir = output; return this; } public static class InternalTxLoader implements ITxTesterLoader { - TxTestData txtests; + private TxTestData txtests; + private boolean additional; public InternalTxLoader(String version) throws IOException { - load(version); + File f = ManagedFileAccess.file(version); + if (f.exists() && f.isDirectory()) { + txtests = TxTestData.loadTestDataFromFolder(f, "test-cases.json"); + } else { + load(version); + } + } + + public InternalTxLoader(String source, boolean additional) throws IOException { + this.additional = additional; + File f = ManagedFileAccess.file(source); + if (f.exists() && f.isDirectory()) { + txtests = TxTestData.loadTestDataFromFolder(f, "test-cases.json"); + } else if (f.exists()) { + txtests = TxTestData.loadTestDataFromFolder(ManagedFileAccess.file(Utilities.getDirectoryForFile(source)), f.getName()); + } else { + load(source); + } } private void load(String version) throws IOException { - txtests = TxTestData.loadTestDataFromPackage(version); + txtests = TxTestData.loadTestDataFromPackage("hl7.fhir.uv.tx-ecosystem#"+version); } - @Override public String describe() { return txtests.describe(); @@ -617,6 +703,22 @@ public class TxTester { public boolean hasContent(String filename) throws IOException { return txtests.hasFile(filename); } + + @Override + public String code() { + return txtests.code(); + } + + @Override + public String version() throws JsonException, IOException { + return txtests.loadVersion(); + } + + @Override + public String testFileName() { + return txtests.testFileName(); + } } + } diff --git a/org.hl7.fhir.validation/src/test/java/org/hl7/fhir/terminology/tests/ExternalTerminologyServiceTests.java b/org.hl7.fhir.validation/src/test/java/org/hl7/fhir/terminology/tests/ExternalTerminologyServiceTests.java index 02b5b6a15..e7fa225f9 100644 --- a/org.hl7.fhir.validation/src/test/java/org/hl7/fhir/terminology/tests/ExternalTerminologyServiceTests.java +++ b/org.hl7.fhir.validation/src/test/java/org/hl7/fhir/terminology/tests/ExternalTerminologyServiceTests.java @@ -21,6 +21,7 @@ import org.hl7.fhir.r5.formats.JsonParser; import org.hl7.fhir.r5.formats.XmlParser; import org.hl7.fhir.r5.model.Constants; import org.hl7.fhir.r5.model.Resource; +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.validation.special.TxTestData; @@ -52,7 +53,7 @@ public class ExternalTerminologyServiceTests implements ITxTesterLoader { @Parameters(name = "{index}: id {0}") public static Iterable data() throws IOException { - txtests = TxTestData.loadTestDataFromPackage("dev"); + txtests = TxTestData.loadTestDataFromPackage("hl7.fhir.uv.tx-ecosystem#dev"); String contents = txtests.load("test-cases.json"); externals = org.hl7.fhir.utilities.json.parser.JsonParser.parseObject(txtests.load("messages-tx.fhir.org.json")); @@ -101,7 +102,7 @@ public class ExternalTerminologyServiceTests implements ITxTesterLoader { if (setup.suite.asBoolean("disabled") || setup.test.asBoolean("disabled")) { return; } - String err = tester.executeTest(setup.suite, setup.test, modes); + String err = tester.executeTest(this, setup.suite, setup.test, modes); Assertions.assertTrue(err == null, err); } else { Assertions.assertTrue(true); @@ -155,4 +156,19 @@ public class ExternalTerminologyServiceTests implements ITxTesterLoader { public boolean hasContent(String filename) throws IOException { return txtests.hasFile(filename); } + + @Override + public String code() { + return "external"; + } + + @Override + public String version() throws JsonException, IOException { + return txtests.loadVersion(); + } + + @Override + public String testFileName() { + return txtests.testFileName(); + } } \ No newline at end of file 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 284590b1b..c38edfe11 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 @@ -62,7 +62,7 @@ public class LocalTerminologyServiceTests implements ITxTesterLoader { @Parameters(name = "{index}: id {0}") public static Iterable data() throws IOException { - txtests = TxTestData.loadTestDataFromPackage("dev"); + txtests = TxTestData.loadTestDataFromPackage("hl7.fhir.uv.tx-ecosystem#dev"); String contents = txtests.load("test-cases.json"); externals = org.hl7.fhir.utilities.json.parser.JsonParser.parseObject(txtests.load("messages-tx.fhir.org.json")); @@ -95,7 +95,8 @@ public class LocalTerminologyServiceTests implements ITxTesterLoader { private String version = "5.0.0"; private static TxTester tester; private List modes = new ArrayList<>(); - private boolean error = false; + private static int error = 0; + private static int count = 0; private static TxTestData txtests; public LocalTerminologyServiceTests(String name, JsonObjectPair setup) { @@ -115,17 +116,23 @@ public class LocalTerminologyServiceTests implements ITxTesterLoader { return; } 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()+")"); + count++; + if (error == 0) { + System.out.println("tx.fhir.org passed all "+count+" HL7 terminology service tests (mode 'tx.fhir.org', tests v"+loadVersion()+", runner v"+VersionUtil.getBaseVersion()+")"); + } else { + System.out.println("tx.fhir.org failed "+error+" of "+count+" HL7 terminology service tests (mode 'tx.fhir.org', tests v"+loadVersion()+", runner v"+VersionUtil.getBaseVersion()+")"); } - Assertions.assertTrue(!error); + Assertions.assertTrue(error == 0); } else { + count++; 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; + String err = tester.executeTest(this, setup.suite, setup.test, modes); + if (err != null) { + error++; + } Assertions.assertTrue(err == null, err); } else { Assertions.assertTrue(true); @@ -175,10 +182,6 @@ public class LocalTerminologyServiceTests implements ITxTesterLoader { throw new FHIRException("unknown version " + version); } } -// org.hl7.fhir.r4.model.Resource r4 = VersionConvertorFactory_40_50.convertResource(res); -// String p = Utilities.path(FhirSettings.getFhirTestCasesPath(), "tx", "r4", filename); -// Utilities.createDirectory(Utilities.getDirectoryForFile(p)); -// new org.hl7.fhir.r4.formats.JsonParser().compose(ManagedFileAccess.outStream(p), r4); return res; } @@ -196,4 +199,21 @@ public class LocalTerminologyServiceTests implements ITxTesterLoader { public boolean hasContent(String filename) throws IOException { return txtests.hasFile(filename); } + + @Override + public String code() { + return "local"; + } + + @Override + public String version() throws JsonException, IOException { + return txtests.loadVersion(); + } + + + + @Override + public String testFileName() { + return txtests.testFileName(); + } } \ No newline at end of file diff --git a/org.hl7.fhir.validation/src/test/java/org/hl7/fhir/terminology/tests/OntoserverTests.java b/org.hl7.fhir.validation/src/test/java/org/hl7/fhir/terminology/tests/OntoserverTests.java index e5b9017cf..1bba73505 100644 --- a/org.hl7.fhir.validation/src/test/java/org/hl7/fhir/terminology/tests/OntoserverTests.java +++ b/org.hl7.fhir.validation/src/test/java/org/hl7/fhir/terminology/tests/OntoserverTests.java @@ -20,6 +20,7 @@ import org.hl7.fhir.r5.model.Constants; import org.hl7.fhir.r5.model.Resource; import org.hl7.fhir.utilities.Utilities; 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; @@ -54,12 +55,10 @@ public class OntoserverTests implements ITxTesterLoader { return ManagedFileAccess.file("/Users/grahamegrieve/work/server/server").exists(); } - - @Parameters(name = "{index}: id {0}") public static Iterable data() throws IOException { - txtests = TxTestData.loadTestDataFromPackage("dev"); + txtests = TxTestData.loadTestDataFromPackage("hl7.fhir.uv.tx-ecosystem#dev"); String contents = txtests.load("test-cases.json"); externals = org.hl7.fhir.utilities.json.parser.JsonParser.parseObject(txtests.load("messages-ontoserver.csiro.au.json")); @@ -117,7 +116,7 @@ public class OntoserverTests implements ITxTesterLoader { if (tester == null) { tester = new TxTester(this, SERVER, false, externals); } - String err = tester.executeTest(setup.suite, setup.test, modes); + String err = tester.executeTest(this, setup.suite, setup.test, modes); if (err != null) { System.out.println(err); } @@ -161,10 +160,6 @@ public class OntoserverTests implements ITxTesterLoader { throw new FHIRException("unknown version " + version); } } -// org.hl7.fhir.r4.model.Resource r4 = VersionConvertorFactory_40_50.convertResource(res); -// String p = Utilities.path(FhirSettings.getFhirTestCasesPath(), "tx", "r4", filename); -// Utilities.createDirectory(Utilities.getDirectoryForFile(p)); -// new org.hl7.fhir.r4.formats.JsonParser().compose(ManagedFileAccess.outStream(p), r4); return res; } @@ -182,4 +177,21 @@ public class OntoserverTests implements ITxTesterLoader { public boolean hasContent(String filename) throws IOException { return txtests.hasFile(filename); } + + + + @Override + public String code() { + return "onto"; + } + + @Override + public String version() throws JsonException, IOException { + return txtests.loadVersion(); + } + + @Override + public String testFileName() { + return txtests.testFileName(); + } } \ No newline at end of file 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 182dad9af..bcddc4f69 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 @@ -59,7 +59,7 @@ private static TxTestData testData; @Parameters(name = "{index}: id {0}") public static Iterable data() throws IOException { - testData = TxTestData.loadTestDataFromPackage("dev"); + testData = TxTestData.loadTestDataFromPackage("hl7.fhir.uv.tx-ecosystem#dev"); return testData.getTestData(); }