From 5aefd6a268de9c8f38e078750009f5911247d8e6 Mon Sep 17 00:00:00 2001 From: Grahame Grieve Date: Fri, 11 Aug 2023 12:11:22 +1000 Subject: [PATCH] add flat mode to tests, and add experimental functionality --- .../fhir/r5/context/BaseWorkerContext.java | 8 +++++ .../fhir/r5/test/utils/CompareUtilities.java | 2 +- .../org/hl7/fhir/r5/utils/ElementVisitor.java | 22 +++++++------- .../fhir/utilities/i18n/I18nConstants.java | 9 ++++++ .../src/main/resources/Messages.properties | 9 ++++++ .../fhir/validation/cli/model/CliContext.java | 8 +++++ .../validation/cli/tasks/TxTestsTask.java | 2 +- .../hl7/fhir/validation/cli/utils/Params.java | 8 +++++ .../hl7/fhir/validation/special/TxTester.java | 30 ++++++++++++------- .../validation/special/TxTesterScrubbers.java | 6 ++-- .../ExternalTerminologyServiceTests.java | 7 +++-- .../tests/TerminologyServiceTests.java | 1 - .../5.0.0/all-systems.cache | 15 ++++++++++ 13 files changed, 97 insertions(+), 30 deletions(-) diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/context/BaseWorkerContext.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/context/BaseWorkerContext.java index 2962e8908..401a126b5 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/context/BaseWorkerContext.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/context/BaseWorkerContext.java @@ -1521,6 +1521,14 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte OperationOutcomeIssueComponent iss = new OperationOutcomeIssueComponent(org.hl7.fhir.r5.model.OperationOutcome.IssueSeverity.INFORMATION, org.hl7.fhir.r5.model.OperationOutcome.IssueType.EXPIRED); iss.getDetails().setText(formatMessage(I18nConstants.MSG_RETIRED, ((PrimitiveType) p.getValue()).asStringValue())); issues.add(iss); + } else if (p.getName().equals("warning-experimental")) { + OperationOutcomeIssueComponent iss = new OperationOutcomeIssueComponent(org.hl7.fhir.r5.model.OperationOutcome.IssueSeverity.INFORMATION, org.hl7.fhir.r5.model.OperationOutcome.IssueType.BUSINESSRULE); + iss.getDetails().setText(formatMessage(I18nConstants.MSG_EXPERIMENTAL, ((PrimitiveType) p.getValue()).asStringValue())); + issues.add(iss); + } else if (p.getName().equals("warning-draft")) { + OperationOutcomeIssueComponent iss = new OperationOutcomeIssueComponent(org.hl7.fhir.r5.model.OperationOutcome.IssueSeverity.INFORMATION, org.hl7.fhir.r5.model.OperationOutcome.IssueType.BUSINESSRULE); + iss.getDetails().setText(formatMessage(I18nConstants.MSG_DRAFT, ((PrimitiveType) p.getValue()).asStringValue())); + issues.add(iss); } else if (p.getName().equals("cause")) { try { IssueType it = IssueType.fromCode(((StringType) p.getValue()).getValue()); 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 2d19973a8..f1744648e 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 @@ -309,7 +309,7 @@ public class CompareUtilities extends BaseTestingUtilities { int expectedMin = countExpectedMin(expectedArray); if (actualArray.size() > expectedArray.size() || actualArray.size() < expectedMin) - return createNotEqualMessage("array properties count differs at " + path, Integer.toString(expectedArray.size()), Integer.toString(actualArray.size())); + return createNotEqualMessage("array item count differs at " + path, Integer.toString(expectedArray.size()), Integer.toString(actualArray.size())); int c = 0; for (int i = 0; i < expectedArray.size(); i++) { if (c >= actualArray.size()) { diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/ElementVisitor.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/ElementVisitor.java index 0ae4b1a56..b2e6504a8 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/ElementVisitor.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/ElementVisitor.java @@ -8,8 +8,8 @@ import org.hl7.fhir.r5.model.Resource; public class ElementVisitor { public interface IElementVisitor { - public void visit(Resource resource); - public void visit(Element element); + public void visit(Object context, Resource resource); + public void visit(Object context, Element element); } private IElementVisitor visitor; @@ -18,28 +18,28 @@ public class ElementVisitor { this.visitor = visitor; } - private void visitBase(Base base) { + private void visitBase(Object context, Base base) { for (Property p : base.children()) { if (p.hasValues()) { for (Base b : p.getValues()) { if (b instanceof Resource) { - visit((Resource) b); + visit(context, (Resource) b); } else { - visit((Element) b); + visit(context, (Element) b); } } } } } - public void visit(Resource res) { - visitor.visit(res); - visitBase(res); + public void visit(Object context, Resource res) { + visitor.visit(context, res); + visitBase(context, res); } - public void visit(Element e) { - visitor.visit(e); - visitBase(e); + public void visit(Object context, Element e) { + visitor.visit(context, e); + visitBase(context, e); } } diff --git a/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/i18n/I18nConstants.java b/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/i18n/I18nConstants.java index c4494e86a..b1e238661 100644 --- a/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/i18n/I18nConstants.java +++ b/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/i18n/I18nConstants.java @@ -956,6 +956,15 @@ public class I18nConstants { public static final String MSG_RETIRED = "MSG_RETIRED"; public static final String INACTIVE_CODE_WARNING = "INACTIVE_CODE_WARNING"; public static final String SD_EXTENSION_URL_MISSING = "SD_EXTENSION_URL_MISSING"; + public static final String MSG_EXPERIMENTAL = "MSG_EXPERIMENTAL"; + public static final String MSG_DRAFT = "MSG_DRAFT"; + public static final String MSG_DEPENDS_ON_DEPRECATED = "MSG_DEPENDS_ON_DEPRECATED"; + public static final String MSG_DEPENDS_ON_WITHDRAWN = "MSG_DEPENDS_ON_WITHDRAWN"; + public static final String MSG_DEPENDS_ON_RETIRED = "MSG_DEPENDS_ON_RETIRED"; + public static final String MSG_DEPENDS_ON_EXPERIMENTAL = "MSG_DEPENDS_ON_EXPERIMENTAL"; + public static final String MSG_DEPENDS_ON_DRAFT = "MSG_DEPENDS_ON_DRAFT"; + public static final String MSG_DEPENDS_ON_EXTENSION = "MSG_DEPENDS_ON_EXTENSION"; + public static final String MSG_DEPENDS_ON_PROFILE = "MSG_DEPENDS_ON_PROFILE"; } diff --git a/org.hl7.fhir.utilities/src/main/resources/Messages.properties b/org.hl7.fhir.utilities/src/main/resources/Messages.properties index c77643f3d..2ab215b84 100644 --- a/org.hl7.fhir.utilities/src/main/resources/Messages.properties +++ b/org.hl7.fhir.utilities/src/main/resources/Messages.properties @@ -1012,5 +1012,14 @@ SD_EXTENSION_URL_MISSING = The value of Extension.url is not fixed to the extens MSG_DEPRECATED = Reference to deprecated item {0} MSG_WITHDRAWN = Reference to withdrawn item {0} MSG_RETIRED = Reference to retired item {0} +MSG_EXPERIMENTAL = Reference to experimental item {0} +MSG_DRAFT = Reference to draft item {0} INACTIVE_CODE_WARNING = The code ''{0}'' is valid but is not active SD_ED_TYPE_PROFILE_WRONG_TYPE = The type {0} is not in the list of allowed types {1} in the profile {2} +MSG_DEPENDS_ON_DEPRECATED = The {0} {1} is deprecated +MSG_DEPENDS_ON_WITHDRAWN = The {0} {1} is withdrawn +MSG_DEPENDS_ON_RETIRED = The {0} {1} is retired +MSG_DEPENDS_ON_EXPERIMENTAL = The {0} {1} is an experimental resource +MSG_DEPENDS_ON_DRAFT = The {0} {1} is a draft resource +MSG_DEPENDS_ON_EXTENSION = extension +MSG_DEPENDS_ON_PROFILE = profile diff --git a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/cli/model/CliContext.java b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/cli/model/CliContext.java index e2d391c8e..27b2ac4b7 100644 --- a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/cli/model/CliContext.java +++ b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/cli/model/CliContext.java @@ -101,6 +101,8 @@ public class CliContext { private List sources = new ArrayList(); @JsonProperty("inputs") private List inputs = new ArrayList(); + @JsonProperty("modeParams") + private List modeParams = new ArrayList(); @JsonProperty("mode") private EngineMode mode = EngineMode.VALIDATION; @@ -427,6 +429,12 @@ public class CliContext { public List getInputs() { return inputs; } + + + @JsonProperty("modeParams") + public List getModeParams() { + return modeParams; + } @JsonProperty("sources") public CliContext setSources(List sources) { 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 38246f127..87da870d5 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 @@ -41,7 +41,7 @@ public class TxTestsTask extends StandaloneTask{ final String version = Params.getParam(args, Params.VERSION); final String tx = Params.getParam(args, Params.TERMINOLOGY); final String filter = Params.getParam(args, Params.FILTER); - boolean ok = new TxTester(new TxTester.InternalTxLoader(source, output), tx, false).setOutput(output).execute(version, filter); + boolean ok = new TxTester(new TxTester.InternalTxLoader(source, output), tx, false).setOutput(output).execute(version, cliContext.getModeParams(), filter); SystemExitManager.setError(ok ? 1 : 0); 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 0f73603c2..0e1a9a36e 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 @@ -99,6 +99,7 @@ public class Params { public static final String SOURCE = "-source"; public static final String INPUT = "-input"; public static final String FILTER = "-filter"; + public static final String MODE = "-mode"; private static final String FHIR_SETTINGS_PARAM = "-fhir-settings"; private static final String WATCH_MODE_PARAM = "-watch-mode"; private static final String WATCH_SCAN_DELAY = "-watch-scan-delay"; @@ -203,6 +204,13 @@ public class Params { String q = args[++i]; cliContext.setLevel(ValidationLevel.fromCode(q)); } + } else if (args[i].equals(MODE)) { + if (i + 1 == args.length) + throw new Error("Specified -mode without indicating mode"); + else { + String q = args[++i]; + cliContext.getModeParams().add(q); + } } else if (args[i].equals(INPUT)) { if (i + 1 == args.length) throw new Error("Specified -input without providing value"); 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 38e89c5a8..70ac919b2 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 @@ -65,10 +65,10 @@ public class TxTester { } public static void main(String[] args) throws Exception { - new TxTester(new InternalTxLoader(args[0]), args[1], "true".equals(args[2])).execute(args[2], args[3]); + new TxTester(new InternalTxLoader(args[0]), args[1], "true".equals(args[2])).execute(args[2], new ArrayList<>(), args[3]); } - public boolean execute(String version, String filter) throws IOException, URISyntaxException { + public boolean execute(String version, List modes, String filter) throws IOException, URISyntaxException { if (output == null) { output = Utilities.path("[tmp]", serverId()); } @@ -77,6 +77,7 @@ public class TxTester { System.out.println(" Source for tests: "+loader.describe()); System.out.println(" Output Directory: "+output); System.out.println(" Term Service Url: "+server); + System.out.println(" Test Exec Modes: "+modes.toString()); if (version != null) { System.out.println(" Tx FHIR Version: "+version); } @@ -91,7 +92,7 @@ public class TxTester { ITerminologyClient tx = connectToServer(); boolean ok = checkClient(tx); for (JsonObject suite : tests.getJsonObjects("suites")) { - ok = runSuite(suite, tx, filter, json.forceArray("suites")) && ok; + ok = runSuite(suite, tx, modes, filter, json.forceArray("suites")) && ok; } TextFile.stringToFile(JsonParser.compose(json, true), Utilities.path(output, "test-results.json")); if (ok) { @@ -137,20 +138,20 @@ public class TxTester { } - public String executeTest(JsonObject suite, JsonObject test) throws URISyntaxException, FHIRFormatError, FileNotFoundException, IOException { + public String executeTest(JsonObject suite, JsonObject test, List modes) throws URISyntaxException, FHIRFormatError, FileNotFoundException, IOException { error = null; if (tx == null) { tx = connectToServer(); checkClient(tx); } List setup = loadSetupResources(suite); - if (runTest(test, tx, setup, "*", null)) { + if (runTest(test, tx, setup, modes, "*", null)) { return null; } else { return error; } } - private boolean runSuite(JsonObject suite, ITerminologyClient tx, String filter, JsonArray output) throws FHIRFormatError, FileNotFoundException, IOException { + private boolean runSuite(JsonObject suite, ITerminologyClient tx, List modes, String filter, JsonArray output) throws FHIRFormatError, FileNotFoundException, IOException { System.out.println("Group "+suite.asString("name")); JsonObject outputS = new JsonObject(); if (output != null) { @@ -160,12 +161,12 @@ public class TxTester { List setup = loadSetupResources(suite); boolean ok = true; for (JsonObject test : suite.getJsonObjects("tests")) { - ok = runTest(test, tx, setup, filter, outputS.forceArray("tests")) && ok; + ok = runTest(test, tx, setup, modes, filter, outputS.forceArray("tests")) && ok; } return ok; } - private boolean runTest(JsonObject test, ITerminologyClient tx, List setup, String filter, JsonArray output) throws FHIRFormatError, DefinitionException, FileNotFoundException, FHIRException, IOException { + private boolean runTest(JsonObject test, ITerminologyClient tx, List setup, List modes, String filter, JsonArray output) throws FHIRFormatError, DefinitionException, FileNotFoundException, FHIRException, IOException { JsonObject outputT = new JsonObject(); if (output != null) { output.add(outputT); @@ -175,9 +176,9 @@ public class TxTester { if (Utilities.noString(filter) || filter.equals("*") || test.asString("name").contains(filter)) { System.out.print(" Test "+test.asString("name")+": "); try { - Parameters req = (Parameters) loader.loadResource(test.asString("request")); + Parameters req = (Parameters) loader.loadResource(chooseParam(test, "request", modes)); - String fn = test.asString("response"); + String fn = chooseParam(test, "response", modes); String resp = TextFile.bytesToString(loader.loadContent(fn)); String fp = Utilities.path("[tmp]", serverId(), fn); File fo = new File(fp); @@ -217,6 +218,15 @@ public class TxTester { } } + private String chooseParam(JsonObject test, String name, List modes) { + for (String mode : modes) { + if (test.has(name+":"+mode)) { + return test.asString(name+":"+mode); + } + } + return test.asString(name); + } + private Parameters loadProfile(JsonObject test) throws FHIRFormatError, DefinitionException, FileNotFoundException, FHIRException, IOException { if (test.has("profile")) { return (Parameters) loader.loadResource(test.asString("profile")); 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 b5e7f8729..f23d0fed5 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 @@ -53,7 +53,7 @@ public class TxTesterScrubbers { } @Override - public void visit(Resource resource) { + public void visit(Object context, Resource resource) { if (resource instanceof DomainResource) { DomainResource dr = (DomainResource) resource; dr.getExtension().removeIf(ext -> !isManagedExtension(ext)); @@ -61,7 +61,7 @@ public class TxTesterScrubbers { } @Override - public void visit(Element element) { + public void visit(Object context, Element element) { element.getExtension().removeIf(ext -> !isManagedExtension(ext)); } } @@ -69,7 +69,7 @@ public class TxTesterScrubbers { public static void scrubDR(DomainResource dr, boolean tight) { dr.setText(null); dr.setMeta(null); - new ElementVisitor(new TxTesterScrubberVisitor(tight)).visit(dr); + new ElementVisitor(new TxTesterScrubberVisitor(tight)).visit(null, dr); } public static void scrubVS(ValueSet vs, boolean tight) { 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 99ba5e71c..11eb70b1d 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 @@ -46,8 +46,8 @@ public class ExternalTerminologyServiceTests implements ITxTesterLoader { private JsonObject test; } - private static final String SERVER = FhirSettings.getTxFhirDevelopment(); -// private static final String SERVER = FhirSettings.getTxFhirLocal(); +// private static final String SERVER = FhirSettings.getTxFhirDevelopment(); + private static final String SERVER = FhirSettings.getTxFhirLocal(); // private static final String SERVER = "https://r4.ontoserver.csiro.au/fhir"; @@ -81,6 +81,7 @@ public class ExternalTerminologyServiceTests implements ITxTesterLoader { private JsonObjectPair setup; private String version = "5.0.0"; private static TxTester tester; + private List modes = new ArrayList<>(); public ExternalTerminologyServiceTests(String name, JsonObjectPair setup) { this.setup = setup; @@ -93,7 +94,7 @@ public class ExternalTerminologyServiceTests implements ITxTesterLoader { if (tester == null) { tester = new TxTester(this, SERVER, true); } - String err = tester.executeTest(setup.suite, setup.test); + String err = tester.executeTest(setup.suite, setup.test, modes); Assertions.assertTrue(err == null, err); } else { Assertions.assertTrue(true); 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 d9fe67d7b..7035ce849 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 @@ -117,7 +117,6 @@ public class TerminologyServiceTests { public void test() throws Exception { if (baseEngine == null) { baseEngine = TestUtilities.getValidationEngineNoTxServer("hl7.fhir.r5.core#5.0.0", FhirPublication.R5, "5.0.0"); - } ValidationEngine engine = new ValidationEngine(this.baseEngine); for (String s : setup.suite.forceArray("setup").asStrings()) { diff --git a/org.hl7.fhir.validation/src/test/resources/txCache/org.hl7.fhir.validation/5.0.0/all-systems.cache b/org.hl7.fhir.validation/src/test/resources/txCache/org.hl7.fhir.validation/5.0.0/all-systems.cache index f71ba85ea..438753f0f 100644 --- a/org.hl7.fhir.validation/src/test/resources/txCache/org.hl7.fhir.validation/5.0.0/all-systems.cache +++ b/org.hl7.fhir.validation/src/test/resources/txCache/org.hl7.fhir.validation/5.0.0/all-systems.cache @@ -143,3 +143,18 @@ v: { "system" : "http://unstats.un.org/unsd/methods/m49/m49.htm" } ------------------------------------------------------------------------------------- +{"code" : { + "code" : "json" +}, "url": "http://hl7.org/fhir/ValueSet/mimetypes", "version": "5.0.0", "langs":"[en]", "useServer":"true", "useClient":"true", "guessSystem":"true", "valueSetMode":"ALL_CHECKS", "displayWarningMode":"false", "versionFlexible":"false", "profile": { + "resourceType" : "Parameters", + "parameter" : [{ + "name" : "profile-url", + "valueString" : "http://hl7.org/fhir/ExpansionProfile/dc8fd4bc-091a-424a-8a3b-6198ef146891" + }] +}}#### +v: { + "display" : "json", + "code" : "json", + "system" : "urn:ietf:bcp:13" +} +-------------------------------------------------------------------------------------