add flat mode to tests, and add experimental functionality

This commit is contained in:
Grahame Grieve 2023-08-11 12:11:22 +10:00
parent cce9d9cdac
commit 5aefd6a268
13 changed files with 97 additions and 30 deletions

View File

@ -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); 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())); iss.getDetails().setText(formatMessage(I18nConstants.MSG_RETIRED, ((PrimitiveType<?>) p.getValue()).asStringValue()));
issues.add(iss); 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")) { } else if (p.getName().equals("cause")) {
try { try {
IssueType it = IssueType.fromCode(((StringType) p.getValue()).getValue()); IssueType it = IssueType.fromCode(((StringType) p.getValue()).getValue());

View File

@ -309,7 +309,7 @@ public class CompareUtilities extends BaseTestingUtilities {
int expectedMin = countExpectedMin(expectedArray); int expectedMin = countExpectedMin(expectedArray);
if (actualArray.size() > expectedArray.size() || actualArray.size() < expectedMin) 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; int c = 0;
for (int i = 0; i < expectedArray.size(); i++) { for (int i = 0; i < expectedArray.size(); i++) {
if (c >= actualArray.size()) { if (c >= actualArray.size()) {

View File

@ -8,8 +8,8 @@ import org.hl7.fhir.r5.model.Resource;
public class ElementVisitor { public class ElementVisitor {
public interface IElementVisitor { public interface IElementVisitor {
public void visit(Resource resource); public void visit(Object context, Resource resource);
public void visit(Element element); public void visit(Object context, Element element);
} }
private IElementVisitor visitor; private IElementVisitor visitor;
@ -18,28 +18,28 @@ public class ElementVisitor {
this.visitor = visitor; this.visitor = visitor;
} }
private void visitBase(Base base) { private void visitBase(Object context, Base base) {
for (Property p : base.children()) { for (Property p : base.children()) {
if (p.hasValues()) { if (p.hasValues()) {
for (Base b : p.getValues()) { for (Base b : p.getValues()) {
if (b instanceof Resource) { if (b instanceof Resource) {
visit((Resource) b); visit(context, (Resource) b);
} else { } else {
visit((Element) b); visit(context, (Element) b);
} }
} }
} }
} }
} }
public void visit(Resource res) { public void visit(Object context, Resource res) {
visitor.visit(res); visitor.visit(context, res);
visitBase(res); visitBase(context, res);
} }
public void visit(Element e) { public void visit(Object context, Element e) {
visitor.visit(e); visitor.visit(context, e);
visitBase(e); visitBase(context, e);
} }
} }

View File

@ -956,6 +956,15 @@ public class I18nConstants {
public static final String MSG_RETIRED = "MSG_RETIRED"; public static final String MSG_RETIRED = "MSG_RETIRED";
public static final String INACTIVE_CODE_WARNING = "INACTIVE_CODE_WARNING"; 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 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";
} }

View File

@ -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_DEPRECATED = Reference to deprecated item {0}
MSG_WITHDRAWN = Reference to withdrawn item {0} MSG_WITHDRAWN = Reference to withdrawn item {0}
MSG_RETIRED = Reference to retired 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 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} 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

View File

@ -101,6 +101,8 @@ public class CliContext {
private List<String> sources = new ArrayList<String>(); private List<String> sources = new ArrayList<String>();
@JsonProperty("inputs") @JsonProperty("inputs")
private List<String> inputs = new ArrayList<String>(); private List<String> inputs = new ArrayList<String>();
@JsonProperty("modeParams")
private List<String> modeParams = new ArrayList<String>();
@JsonProperty("mode") @JsonProperty("mode")
private EngineMode mode = EngineMode.VALIDATION; private EngineMode mode = EngineMode.VALIDATION;
@ -428,6 +430,12 @@ public class CliContext {
return inputs; return inputs;
} }
@JsonProperty("modeParams")
public List<String> getModeParams() {
return modeParams;
}
@JsonProperty("sources") @JsonProperty("sources")
public CliContext setSources(List<String> sources) { public CliContext setSources(List<String> sources) {
this.sources = sources; this.sources = sources;

View File

@ -41,7 +41,7 @@ public class TxTestsTask extends StandaloneTask{
final String version = Params.getParam(args, Params.VERSION); final String version = Params.getParam(args, Params.VERSION);
final String tx = Params.getParam(args, Params.TERMINOLOGY); final String tx = Params.getParam(args, Params.TERMINOLOGY);
final String filter = Params.getParam(args, Params.FILTER); 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.setError(ok ? 1 : 0);
SystemExitManager.finish(); SystemExitManager.finish();
} }

View File

@ -99,6 +99,7 @@ public class Params {
public static final String SOURCE = "-source"; public static final String SOURCE = "-source";
public static final String INPUT = "-input"; public static final String INPUT = "-input";
public static final String FILTER = "-filter"; 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 FHIR_SETTINGS_PARAM = "-fhir-settings";
private static final String WATCH_MODE_PARAM = "-watch-mode"; private static final String WATCH_MODE_PARAM = "-watch-mode";
private static final String WATCH_SCAN_DELAY = "-watch-scan-delay"; private static final String WATCH_SCAN_DELAY = "-watch-scan-delay";
@ -203,6 +204,13 @@ public class Params {
String q = args[++i]; String q = args[++i];
cliContext.setLevel(ValidationLevel.fromCode(q)); 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)) { } else if (args[i].equals(INPUT)) {
if (i + 1 == args.length) if (i + 1 == args.length)
throw new Error("Specified -input without providing value"); throw new Error("Specified -input without providing value");

View File

@ -65,10 +65,10 @@ public class TxTester {
} }
public static void main(String[] args) throws Exception { 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<String> modes, String filter) throws IOException, URISyntaxException {
if (output == null) { if (output == null) {
output = Utilities.path("[tmp]", serverId()); output = Utilities.path("[tmp]", serverId());
} }
@ -77,6 +77,7 @@ public class TxTester {
System.out.println(" Source for tests: "+loader.describe()); System.out.println(" Source for tests: "+loader.describe());
System.out.println(" Output Directory: "+output); System.out.println(" Output Directory: "+output);
System.out.println(" Term Service Url: "+server); System.out.println(" Term Service Url: "+server);
System.out.println(" Test Exec Modes: "+modes.toString());
if (version != null) { if (version != null) {
System.out.println(" Tx FHIR Version: "+version); System.out.println(" Tx FHIR Version: "+version);
} }
@ -91,7 +92,7 @@ public class TxTester {
ITerminologyClient tx = connectToServer(); ITerminologyClient tx = connectToServer();
boolean ok = checkClient(tx); boolean ok = checkClient(tx);
for (JsonObject suite : tests.getJsonObjects("suites")) { 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")); TextFile.stringToFile(JsonParser.compose(json, true), Utilities.path(output, "test-results.json"));
if (ok) { 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<String> modes) throws URISyntaxException, FHIRFormatError, FileNotFoundException, IOException {
error = null; error = null;
if (tx == null) { if (tx == null) {
tx = connectToServer(); tx = connectToServer();
checkClient(tx); checkClient(tx);
} }
List<Resource> setup = loadSetupResources(suite); List<Resource> setup = loadSetupResources(suite);
if (runTest(test, tx, setup, "*", null)) { if (runTest(test, tx, setup, modes, "*", null)) {
return null; return null;
} else { } else {
return error; 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<String> modes, String filter, JsonArray output) throws FHIRFormatError, FileNotFoundException, IOException {
System.out.println("Group "+suite.asString("name")); System.out.println("Group "+suite.asString("name"));
JsonObject outputS = new JsonObject(); JsonObject outputS = new JsonObject();
if (output != null) { if (output != null) {
@ -160,12 +161,12 @@ public class TxTester {
List<Resource> setup = loadSetupResources(suite); List<Resource> setup = loadSetupResources(suite);
boolean ok = true; boolean ok = true;
for (JsonObject test : suite.getJsonObjects("tests")) { 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; return ok;
} }
private boolean runTest(JsonObject test, ITerminologyClient tx, List<Resource> setup, String filter, JsonArray output) throws FHIRFormatError, DefinitionException, FileNotFoundException, FHIRException, IOException { private boolean runTest(JsonObject test, ITerminologyClient tx, List<Resource> setup, List<String> modes, String filter, JsonArray output) throws FHIRFormatError, DefinitionException, FileNotFoundException, FHIRException, IOException {
JsonObject outputT = new JsonObject(); JsonObject outputT = new JsonObject();
if (output != null) { if (output != null) {
output.add(outputT); output.add(outputT);
@ -175,9 +176,9 @@ public class TxTester {
if (Utilities.noString(filter) || filter.equals("*") || test.asString("name").contains(filter)) { if (Utilities.noString(filter) || filter.equals("*") || test.asString("name").contains(filter)) {
System.out.print(" Test "+test.asString("name")+": "); System.out.print(" Test "+test.asString("name")+": ");
try { 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 resp = TextFile.bytesToString(loader.loadContent(fn));
String fp = Utilities.path("[tmp]", serverId(), fn); String fp = Utilities.path("[tmp]", serverId(), fn);
File fo = new File(fp); File fo = new File(fp);
@ -217,6 +218,15 @@ public class TxTester {
} }
} }
private String chooseParam(JsonObject test, String name, List<String> 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 { private Parameters loadProfile(JsonObject test) throws FHIRFormatError, DefinitionException, FileNotFoundException, FHIRException, IOException {
if (test.has("profile")) { if (test.has("profile")) {
return (Parameters) loader.loadResource(test.asString("profile")); return (Parameters) loader.loadResource(test.asString("profile"));

View File

@ -53,7 +53,7 @@ public class TxTesterScrubbers {
} }
@Override @Override
public void visit(Resource resource) { public void visit(Object context, Resource resource) {
if (resource instanceof DomainResource) { if (resource instanceof DomainResource) {
DomainResource dr = (DomainResource) resource; DomainResource dr = (DomainResource) resource;
dr.getExtension().removeIf(ext -> !isManagedExtension(ext)); dr.getExtension().removeIf(ext -> !isManagedExtension(ext));
@ -61,7 +61,7 @@ public class TxTesterScrubbers {
} }
@Override @Override
public void visit(Element element) { public void visit(Object context, Element element) {
element.getExtension().removeIf(ext -> !isManagedExtension(ext)); element.getExtension().removeIf(ext -> !isManagedExtension(ext));
} }
} }
@ -69,7 +69,7 @@ public class TxTesterScrubbers {
public static void scrubDR(DomainResource dr, boolean tight) { public static void scrubDR(DomainResource dr, boolean tight) {
dr.setText(null); dr.setText(null);
dr.setMeta(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) { public static void scrubVS(ValueSet vs, boolean tight) {

View File

@ -46,8 +46,8 @@ public class ExternalTerminologyServiceTests implements ITxTesterLoader {
private JsonObject test; private JsonObject test;
} }
private static final String SERVER = FhirSettings.getTxFhirDevelopment(); // private static final String SERVER = FhirSettings.getTxFhirDevelopment();
// private static final String SERVER = FhirSettings.getTxFhirLocal(); private static final String SERVER = FhirSettings.getTxFhirLocal();
// private static final String SERVER = "https://r4.ontoserver.csiro.au/fhir"; // private static final String SERVER = "https://r4.ontoserver.csiro.au/fhir";
@ -81,6 +81,7 @@ public class ExternalTerminologyServiceTests implements ITxTesterLoader {
private JsonObjectPair setup; private JsonObjectPair setup;
private String version = "5.0.0"; private String version = "5.0.0";
private static TxTester tester; private static TxTester tester;
private List<String> modes = new ArrayList<>();
public ExternalTerminologyServiceTests(String name, JsonObjectPair setup) { public ExternalTerminologyServiceTests(String name, JsonObjectPair setup) {
this.setup = setup; this.setup = setup;
@ -93,7 +94,7 @@ public class ExternalTerminologyServiceTests implements ITxTesterLoader {
if (tester == null) { if (tester == null) {
tester = new TxTester(this, SERVER, true); 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); Assertions.assertTrue(err == null, err);
} else { } else {
Assertions.assertTrue(true); Assertions.assertTrue(true);

View File

@ -117,7 +117,6 @@ public class TerminologyServiceTests {
public void test() throws Exception { public void test() throws Exception {
if (baseEngine == null) { if (baseEngine == null) {
baseEngine = TestUtilities.getValidationEngineNoTxServer("hl7.fhir.r5.core#5.0.0", FhirPublication.R5, "5.0.0"); baseEngine = TestUtilities.getValidationEngineNoTxServer("hl7.fhir.r5.core#5.0.0", FhirPublication.R5, "5.0.0");
} }
ValidationEngine engine = new ValidationEngine(this.baseEngine); ValidationEngine engine = new ValidationEngine(this.baseEngine);
for (String s : setup.suite.forceArray("setup").asStrings()) { for (String s : setup.suite.forceArray("setup").asStrings()) {

View File

@ -143,3 +143,18 @@ v: {
"system" : "http://unstats.un.org/unsd/methods/m49/m49.htm" "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"
}
-------------------------------------------------------------------------------------