Add support for external strings for tx tests

This commit is contained in:
Grahame Grieve 2023-08-17 11:14:34 +10:00
parent 4d7ecec87c
commit eacffd11df
11 changed files with 248 additions and 90 deletions

View File

@ -2,20 +2,22 @@ package org.hl7.fhir.r5.test.utils;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.lang3.StringUtils;
import org.hl7.fhir.exceptions.FHIRException;
import org.hl7.fhir.utilities.*;
import org.hl7.fhir.utilities.json.JsonUtilities;
import org.hl7.fhir.utilities.json.model.JsonArray;
import org.hl7.fhir.utilities.json.model.JsonElement;
import org.hl7.fhir.utilities.json.model.JsonNull;
import org.hl7.fhir.utilities.json.model.JsonObject;
import org.hl7.fhir.utilities.json.model.JsonPrimitive;
import org.hl7.fhir.utilities.json.model.JsonProperty;
import org.hl7.fhir.utilities.json.parser.JsonParser;
import org.hl7.fhir.utilities.settings.FhirSettings;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonNull;
import com.google.gson.JsonObject;
import com.google.gson.JsonPrimitive;
import com.google.gson.JsonSyntaxException;
import org.hl7.fhir.utilities.tests.BaseTestingUtilities;
import javax.xml.parsers.DocumentBuilder;
@ -28,21 +30,52 @@ import java.util.Map;
public class CompareUtilities extends BaseTestingUtilities {
private static final boolean SHOW_DIFF = true;
public static String createNotEqualMessage(final String message, final String expected, final String actual) {
private JsonObject externals;
public String createNotEqualMessage(final String message, final String expected, final String actual) {
return new StringBuilder()
.append(message).append('\n')
.append("Expected :").append(expected).append('\n')
.append("Actual :").append(actual).toString();
.append("Expected :").append(presentExpected(expected)).append('\n')
.append("Actual :").append("\""+actual+"\"").toString();
}
private String presentExpected(String expected) {
if (expected.startsWith("$") && expected.endsWith("$")) {
if (expected.startsWith("$choice:")) {
return "Contains one of "+readChoices(8, expected).toString();
} else if (expected.startsWith("$fragments:")) {
List<String> fragments = readChoices(11, expected);
return "Contains all of "+fragments.toString();
} else if (expected.startsWith("$external:")) {
String[] cmd = expected.substring(1, expected.length() - 1).split("\\:");
if (externals != null) {
String s = externals.asString(cmd[1]);
return "\""+s+"\" (Ext)";
} else {
return "Contains \""+cmd[2]+"\"";
}
} else {
switch (expected) {
case "$$" : return "$$";
case "$instant$": return "\"An Instant\"";
case "$uuid$": return "\"A Uuid\"";
default: return "Unhandled template: "+expected;
}
}
} else {
return "\""+expected+"\"";
}
}
public static String checkXMLIsSame(InputStream expected, InputStream actual) throws Exception {
String result = compareXml(expected, actual);
CompareUtilities self = new CompareUtilities();
String result = self.compareXml(expected, actual);
return result;
}
public static String checkXMLIsSame(String expected, String actual) throws Exception {
String result = compareXml(expected, actual);
CompareUtilities self = new CompareUtilities();
String result = self.compareXml(expected, actual);
if (result != null && SHOW_DIFF) {
String diff = getDiffTool();
if (diff != null && new File(diff).exists() || Utilities.isToken(diff)) {
@ -52,7 +85,7 @@ public class CompareUtilities extends BaseTestingUtilities {
return result;
}
private static String getDiffTool() throws IOException {
private static String getDiffTool() throws IOException {
if (FhirSettings.hasDiffToolPath()) {
return FhirSettings.getDiffToolPath();
} else if (System.getenv("ProgramFiles") != null) {
@ -62,15 +95,15 @@ public class CompareUtilities extends BaseTestingUtilities {
}
}
private static String compareXml(InputStream expected, InputStream actual) throws Exception {
private String compareXml(InputStream expected, InputStream actual) throws Exception {
return compareElements("", loadXml(expected).getDocumentElement(), loadXml(actual).getDocumentElement());
}
private static String compareXml(String expected, String actual) throws Exception {
private String compareXml(String expected, String actual) throws Exception {
return compareElements("", loadXml(expected).getDocumentElement(), loadXml(actual).getDocumentElement());
}
private static String compareElements(String path, Element expectedElement, Element actualElement) {
private String compareElements(String path, Element expectedElement, Element actualElement) {
if (!namespacesMatch(expectedElement.getNamespaceURI(), actualElement.getNamespaceURI()))
return createNotEqualMessage("Namespaces differ at " + path, expectedElement.getNamespaceURI(), actualElement.getNamespaceURI());
if (!expectedElement.getLocalName().equals(actualElement.getLocalName()))
@ -109,18 +142,18 @@ public class CompareUtilities extends BaseTestingUtilities {
return null;
}
private static boolean namespacesMatch(String ns1, String ns2) {
private boolean namespacesMatch(String ns1, String ns2) {
return ns1 == null ? ns2 == null : ns1.equals(ns2);
}
private static Object normalise(String text) {
private String normalise(String text) {
String result = text.trim().replace('\r', ' ').replace('\n', ' ').replace('\t', ' ');
while (result.contains(" "))
result = result.replace(" ", " ");
return result;
}
private static String compareAttributes(String path, NamedNodeMap expected, NamedNodeMap actual) {
private String compareAttributes(String path, NamedNodeMap expected, NamedNodeMap actual) {
for (int i = 0; i < expected.getLength(); i++) {
Node expectedNode = expected.item(i);
@ -140,7 +173,7 @@ public class CompareUtilities extends BaseTestingUtilities {
return null;
}
private static boolean sameBytes(byte[] b1, byte[] b2) {
private boolean sameBytes(byte[] b1, byte[] b2) {
if (b1.length == 0 || b2.length == 0)
return false;
if (b1.length != b2.length)
@ -151,21 +184,21 @@ public class CompareUtilities extends BaseTestingUtilities {
return true;
}
private static byte[] unBase64(String text) {
private byte[] unBase64(String text) {
return Base64.decodeBase64(text);
}
private static Node skipBlankText(Node node) {
private Node skipBlankText(Node node) {
while (node != null && (((node.getNodeType() == Node.TEXT_NODE) && StringUtils.isWhitespace(node.getTextContent())) || (node.getNodeType() == Node.COMMENT_NODE)))
node = node.getNextSibling();
return node;
}
private static Document loadXml(String fn) throws Exception {
private Document loadXml(String fn) throws Exception {
return loadXml(new FileInputStream(fn));
}
private static Document loadXml(InputStream fn) throws Exception {
private Document loadXml(InputStream fn) throws Exception {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
factory.setFeature("http://xml.org/sax/features/external-general-entities", false);
@ -179,12 +212,14 @@ public class CompareUtilities extends BaseTestingUtilities {
return builder.parse(fn);
}
public static String checkJsonSrcIsSame(String expected, String actual) throws JsonSyntaxException, FileNotFoundException, IOException {
return checkJsonSrcIsSame(expected, actual, true);
public static String checkJsonSrcIsSame(String expected, String actual, JsonObject externals) throws FileNotFoundException, IOException {
return checkJsonSrcIsSame(expected, actual, true, externals);
}
public static String checkJsonSrcIsSame(String expectedString, String actualString, boolean showDiff) throws JsonSyntaxException, FileNotFoundException, IOException {
String result = compareJsonSrc(expectedString, actualString);
public static String checkJsonSrcIsSame(String expectedString, String actualString, boolean showDiff, JsonObject externals) throws FileNotFoundException, IOException {
CompareUtilities self = new CompareUtilities();
self.externals = externals;
String result = self.compareJsonSrc(expectedString, actualString);
if (result != null && SHOW_DIFF && showDiff) {
String diff = null;
if (System.getProperty("os.name").contains("Linux"))
@ -217,8 +252,9 @@ public class CompareUtilities extends BaseTestingUtilities {
return result;
}
public static String checkJsonIsSame(String expected, String actual) throws JsonSyntaxException, FileNotFoundException, IOException {
String result = compareJson(expected, actual);
public static String checkJsonIsSame(String expected, String actual) throws FileNotFoundException, IOException {
CompareUtilities self = new CompareUtilities();
String result = self.compareJson(expected, actual);
if (result != null && SHOW_DIFF) {
String diff = Utilities.path(System.getenv("ProgramFiles(X86)"), "WinMerge", "WinMergeU.exe");
List<String> command = new ArrayList<String>();
@ -232,22 +268,22 @@ public class CompareUtilities extends BaseTestingUtilities {
return result;
}
private static String compareJsonSrc(String expected, String actual) throws JsonSyntaxException, FileNotFoundException, IOException {
JsonObject actualJsonObject = (JsonObject) new com.google.gson.JsonParser().parse(actual);
JsonObject expectedJsonObject = (JsonObject) new com.google.gson.JsonParser().parse(expected);
private String compareJsonSrc(String expected, String actual) throws FileNotFoundException, IOException {
JsonObject actualJsonObject = JsonParser.parseObject(actual);
JsonObject expectedJsonObject = JsonParser.parseObject(expected);
return compareObjects("", expectedJsonObject, actualJsonObject);
}
private static String compareJson(String expected, String actual) throws JsonSyntaxException, FileNotFoundException, IOException {
JsonObject actualJsonObject = (JsonObject) new com.google.gson.JsonParser().parse(TextFile.fileToString(actual));
JsonObject expectedJsonObject = (JsonObject) new com.google.gson.JsonParser().parse(TextFile.fileToString(expected));
private String compareJson(String expected, String actual) throws FileNotFoundException, IOException {
JsonObject actualJsonObject = JsonParser.parseObject(TextFile.fileToString(actual));
JsonObject expectedJsonObject = JsonParser.parseObject(TextFile.fileToString(expected));
return compareObjects("", expectedJsonObject, actualJsonObject);
}
private static String compareObjects(String path, JsonObject expectedJsonObject, JsonObject actualJsonObject) {
private String compareObjects(String path, JsonObject expectedJsonObject, JsonObject actualJsonObject) {
List<String> optionals = listOptionals(expectedJsonObject);
for (Map.Entry<String, JsonElement> en : actualJsonObject.entrySet()) {
String n = en.getKey();
for (JsonProperty en : actualJsonObject.getProperties()) {
String n = en.getName();
if (!n.equals("fhir_comments")) {
if (expectedJsonObject.has(n)) {
String s = compareNodes(path + '.' + n, expectedJsonObject.get(n), en.getValue());
@ -257,8 +293,8 @@ public class CompareUtilities extends BaseTestingUtilities {
return "properties differ at " + path + ": missing property " + n;
}
}
for (Map.Entry<String, JsonElement> en : expectedJsonObject.entrySet()) {
String n = en.getKey();
for (JsonProperty en : expectedJsonObject.getProperties()) {
String n = en.getName();
if (!n.equals("fhir_comments") && !n.equals("$optional$") && !optionals.contains(n)) {
if (!actualJsonObject.has(n))
return "properties differ at " + path + ": missing property " + n;
@ -267,38 +303,38 @@ public class CompareUtilities extends BaseTestingUtilities {
return null;
}
private static List<String> listOptionals(JsonObject expectedJsonObject) {
private List<String> listOptionals(JsonObject expectedJsonObject) {
List<String> res = new ArrayList<>();
if (expectedJsonObject.has("$optional-properties$")) {
res.add("$optional-properties$");
for (String s : JsonUtilities.strings(expectedJsonObject.getAsJsonArray("$optional-properties$"))) {
for (String s : expectedJsonObject.getStrings("$optional-properties$")) {
res.add(s);
}
}
return res;
}
private static String compareNodes(String path, JsonElement expectedJsonElement, JsonElement actualJsonElement) {
private String compareNodes(String path, JsonElement expectedJsonElement, JsonElement actualJsonElement) {
if (actualJsonElement.getClass() != expectedJsonElement.getClass())
return createNotEqualMessage("properties differ at " + path, expectedJsonElement.getClass().getName(), actualJsonElement.getClass().getName());
else if (actualJsonElement instanceof JsonPrimitive) {
JsonPrimitive actualJsonPrimitive = (JsonPrimitive) actualJsonElement;
JsonPrimitive expectedJsonPrimitive = (JsonPrimitive) expectedJsonElement;
if (actualJsonPrimitive.isBoolean() && expectedJsonPrimitive.isBoolean()) {
if (actualJsonPrimitive.getAsBoolean() != expectedJsonPrimitive.getAsBoolean())
return createNotEqualMessage("boolean property values differ at " + path , expectedJsonPrimitive.getAsString(), actualJsonPrimitive.getAsString());
} else if (actualJsonPrimitive.isString() && expectedJsonPrimitive.isString()) {
String actualJsonString = actualJsonPrimitive.getAsString();
String expectedJsonString = expectedJsonPrimitive.getAsString();
if (actualJsonPrimitive.isJsonBoolean() && expectedJsonPrimitive.isJsonBoolean()) {
if (actualJsonPrimitive.asBoolean() != expectedJsonPrimitive.asBoolean())
return createNotEqualMessage("boolean property values differ at " + path , expectedJsonPrimitive.asString(), actualJsonPrimitive.asString());
} else if (actualJsonPrimitive.isJsonString() && expectedJsonPrimitive.isJsonString()) {
String actualJsonString = actualJsonPrimitive.asString();
String expectedJsonString = expectedJsonPrimitive.asString();
if (!(actualJsonString.contains("<div") && expectedJsonString.contains("<div")))
if (!matches(actualJsonString, expectedJsonString))
if (!sameBytes(unBase64(actualJsonString), unBase64(expectedJsonString)))
return createNotEqualMessage("string property values differ at " + path, expectedJsonString, actualJsonString);
} else if (actualJsonPrimitive.isNumber() && expectedJsonPrimitive.isNumber()) {
if (!actualJsonPrimitive.getAsString().equals(expectedJsonPrimitive.getAsString()))
return createNotEqualMessage("number property values differ at " + path, expectedJsonPrimitive.getAsString(), actualJsonPrimitive.getAsString());
} else if (actualJsonPrimitive.isJsonNumber() && expectedJsonPrimitive.isJsonNumber()) {
if (!actualJsonPrimitive.asString().equals(expectedJsonPrimitive.asString()))
return createNotEqualMessage("number property values differ at " + path, expectedJsonPrimitive.asString(), actualJsonPrimitive.asString());
} else
return createNotEqualMessage("property types differ at " + path, expectedJsonPrimitive.getAsString(), actualJsonPrimitive.getAsString());
return createNotEqualMessage("property types differ at " + path, expectedJsonPrimitive.asString(), actualJsonPrimitive.asString());
} else if (actualJsonElement instanceof JsonObject) {
String s = compareObjects(path, (JsonObject) expectedJsonElement, (JsonObject) actualJsonElement);
if (!Utilities.noString(s))
@ -334,11 +370,11 @@ public class CompareUtilities extends BaseTestingUtilities {
return null;
}
private static boolean isOptional(JsonElement e) {
return e.isJsonObject() && e.getAsJsonObject().has("$optional$");
private boolean isOptional(JsonElement e) {
return e.isJsonObject() && e.asJsonObject().has("$optional$");
}
private static int countExpectedMin(JsonArray array) {
private int countExpectedMin(JsonArray array) {
int count = array.size();
for (JsonElement e : array) {
if (isOptional(e)) {
@ -348,7 +384,7 @@ public class CompareUtilities extends BaseTestingUtilities {
return count;
}
private static boolean matches(String actualJsonString, String expectedJsonString) {
private boolean matches(String actualJsonString, String expectedJsonString) {
if (expectedJsonString.startsWith("$") && expectedJsonString.endsWith("$")) {
if (expectedJsonString.startsWith("$choice:")) {
return Utilities.existsInList(actualJsonString, readChoices(8, expectedJsonString));
@ -361,6 +397,14 @@ public class CompareUtilities extends BaseTestingUtilities {
}
}
return true;
} else if (expectedJsonString.startsWith("$external:")) {
String[] cmd = expectedJsonString.substring(1, expectedJsonString.length() - 1).split("\\:");
if (externals != null) {
String s = externals.asString(cmd[1]);
return actualJsonString.equals(s);
} else {
return actualJsonString.contains(cmd[2]);
}
} else {
switch (expectedJsonString) {
case "$$" : return true;
@ -375,7 +419,7 @@ public class CompareUtilities extends BaseTestingUtilities {
}
}
private static List<String> readChoices(int offset, String s) {
private List<String> readChoices(int offset, String s) {
List<String> list = new ArrayList<>();
s = s.substring(offset, s.length()-1);
for (String p : s.split("\\|")) {
@ -384,12 +428,13 @@ public class CompareUtilities extends BaseTestingUtilities {
return list;
}
public static String checkTextIsSame(String expected, String actual) throws JsonSyntaxException, FileNotFoundException, IOException {
public static String checkTextIsSame(String expected, String actual) throws FileNotFoundException, IOException {
return checkTextIsSame(expected, actual, true);
}
public static String checkTextIsSame(String expectedString, String actualString, boolean showDiff) throws JsonSyntaxException, FileNotFoundException, IOException {
String result = compareText(expectedString, actualString);
public static String checkTextIsSame(String expectedString, String actualString, boolean showDiff) throws FileNotFoundException, IOException {
CompareUtilities self = new CompareUtilities();
String result = self.compareText(expectedString, actualString);
if (result != null && SHOW_DIFF && showDiff) {
String diff = null;
if (System.getProperty("os.name").contains("Linux"))
@ -423,7 +468,7 @@ public class CompareUtilities extends BaseTestingUtilities {
}
private static String compareText(String expectedString, String actualString) {
private String compareText(String expectedString, String actualString) {
for (int i = 0; i < Integer.min(expectedString.length(), actualString.length()); i++) {
if (expectedString.charAt(i) != actualString.charAt(i))
return createNotEqualMessage("Strings differ at character " + Integer.toString(i), String.valueOf(expectedString.charAt(i)), String.valueOf(actualString.charAt(i)));

View File

@ -60,7 +60,7 @@ public class ParsingTests {
r = new XmlParser().parse(b);
b = new JsonParser().setOutputStyle(OutputStyle.PRETTY).composeBytes(r);
String output = new String(b);
String msg = CompareUtilities.checkJsonSrcIsSame(src, output);
String msg = CompareUtilities.checkJsonSrcIsSame(src, output, null);
Assertions.assertTrue(msg == null, msg);
}

View File

@ -91,7 +91,7 @@ public class CompareUtilitiesTests implements ResourceLoaderTests {
final String expectedJSONPath = ROOT_JSON_TEST_PATH.resolve(expectedFileName).toString();
final String actualJSONPath = ROOT_JSON_TEST_PATH.resolve(actualFileName).toString();
final String actualOutput = CompareUtilities.checkJsonSrcIsSame(getResourceAsString(expectedJSONPath), getResourceAsString(actualJSONPath), false);
final String actualOutput = CompareUtilities.checkJsonSrcIsSame(getResourceAsString(expectedJSONPath), getResourceAsString(actualJSONPath), false, null);
if (expectedOutputFileName == null) {
assertNull(actualOutput);
} else {

View File

@ -7,4 +7,8 @@ public abstract class JsonPrimitive extends JsonElement {
public String toJson() {
return getValue();
}
public boolean asBoolean() {
return "true".equals(getValue());
}
}

View File

@ -1,9 +1,13 @@
package org.hl7.fhir.validation.cli.tasks;
import java.io.IOException;
import java.io.PrintStream;
import org.hl7.fhir.utilities.SystemExitManager;
import org.hl7.fhir.utilities.TimeTracker;
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.validation.cli.model.CliContext;
import org.hl7.fhir.validation.cli.utils.Params;
import org.hl7.fhir.validation.special.TxTester;
@ -41,8 +45,17 @@ 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, cliContext.getModeParams(), filter);
final String externals = Params.getParam(args, Params.EXTERNALS);
boolean ok = new TxTester(new TxTester.InternalTxLoader(source, output), tx, false, loadExternals(externals)).setOutput(output).execute(version, cliContext.getModeParams(), filter);
SystemExitManager.setError(ok ? 1 : 0);
SystemExitManager.finish();
}
private JsonObject loadExternals(String externals) throws JsonException, IOException {
if (externals == null) {
return null;
} else {
return JsonParser.parseObjectFromFile(externals);
}
}
}

View File

@ -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 EXTERNALS = "-externals";
public static final String MODE = "-mode";
private static final String FHIR_SETTINGS_PARAM = "-fhir-settings";
private static final String WATCH_MODE_PARAM = "-watch-mode";

View File

@ -55,17 +55,19 @@ public class TxTester {
private String output;
private ITerminologyClient tx;
private boolean tight;
private JsonObject externals;
public TxTester(ITxTesterLoader loader, String server, boolean tight) {
public TxTester(ITxTesterLoader loader, String server, boolean tight, JsonObject externals) {
super();
this.server = server;
this.loader = loader;
this.tight = tight;
this.externals = externals;
}
public static void main(String[] args) throws Exception {
new TxTester(new InternalTxLoader(args[0]), args[1], "true".equals(args[2])).execute(args[2], new ArrayList<>(), args[3]);
new TxTester(new InternalTxLoader(args[0]), args[1], "true".equals(args[2]), args.length == 5 ? JsonParser.parseObjectFromFile(args[4]) : null).execute(args[2], new ArrayList<>(), args[3]);
}
public boolean execute(String version, List<String> modes, String filter) throws IOException, URISyntaxException {
@ -77,6 +79,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(" External Strings: "+(externals != null));
System.out.println(" Test Exec Modes: "+modes.toString());
if (version != null) {
System.out.println(" Tx FHIR Version: "+version);
@ -185,12 +188,13 @@ public class TxTester {
if (fo.exists()) {
fo.delete();
}
JsonObject ext = externals == null ? null : externals.getJsonObject(fn);
String msg = null;
if (test.asString("operation").equals("expand")) {
msg = expand(tx, setup, req, resp, fp, profile);
msg = expand(tx, setup, req, resp, fp, profile, ext);
} else if (test.asString("operation").equals("validate-code")) {
msg = validate(tx, setup, req, resp, fp, profile);
msg = validate(tx, setup, req, resp, fp, profile, ext);
} else {
throw new Exception("Unknown Operation "+test.asString("operation"));
}
@ -239,7 +243,7 @@ public class TxTester {
return new URI(server).getHost();
}
private String expand(ITerminologyClient tx, List<Resource> setup, Parameters p, String resp, String fp, Parameters profile) throws IOException {
private String expand(ITerminologyClient tx, List<Resource> setup, Parameters p, String resp, String fp, Parameters profile, JsonObject ext) throws IOException {
for (Resource r : setup) {
p.addParameter().setName("tx-resource").setResource(r);
}
@ -255,7 +259,7 @@ public class TxTester {
TxTesterScrubbers.scrubOO(oo, tight);
vsj = new org.hl7.fhir.r5.formats.JsonParser().setOutputStyle(OutputStyle.PRETTY).composeString(oo);
}
String diff = CompareUtilities.checkJsonSrcIsSame(resp, vsj);
String diff = CompareUtilities.checkJsonSrcIsSame(resp, vsj, ext);
if (diff != null) {
Utilities.createDirectory(Utilities.getDirectoryForFile(fp));
TextFile.stringToFile(vsj, fp);
@ -263,7 +267,7 @@ public class TxTester {
return diff;
}
private String validate(ITerminologyClient tx, List<Resource> setup, Parameters p, String resp, String fp, Parameters profile) throws IOException {
private String validate(ITerminologyClient tx, List<Resource> setup, Parameters p, String resp, String fp, Parameters profile, JsonObject ext) throws IOException {
for (Resource r : setup) {
p.addParameter().setName("tx-resource").setResource(r);
}
@ -279,7 +283,7 @@ public class TxTester {
oo.setText(null);
pj = new org.hl7.fhir.r5.formats.JsonParser().setOutputStyle(OutputStyle.PRETTY).composeString(oo);
}
String diff = CompareUtilities.checkJsonSrcIsSame(resp, pj);
String diff = CompareUtilities.checkJsonSrcIsSame(resp, pj, ext);
if (diff != null) {
Utilities.createDirectory(Utilities.getDirectoryForFile(fp));
TextFile.stringToFile(pj, fp);

View File

@ -14,6 +14,7 @@ import java.util.Map;
import java.util.stream.Stream;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.NotImplementedException;
import org.hl7.fhir.convertors.factory.VersionConvertorFactory_10_50;
import org.hl7.fhir.convertors.factory.VersionConvertorFactory_14_50;
import org.hl7.fhir.convertors.factory.VersionConvertorFactory_30_50;
@ -32,6 +33,8 @@ import org.hl7.fhir.r5.comparison.StructureDefinitionComparer;
import org.hl7.fhir.r5.comparison.StructureDefinitionComparer.ProfileComparison;
import org.hl7.fhir.r5.comparison.ValueSetComparer;
import org.hl7.fhir.r5.comparison.ValueSetComparer.ValueSetComparison;
import org.hl7.fhir.r5.conformance.profile.BindingResolution;
import org.hl7.fhir.r5.conformance.profile.ProfileKnowledgeProvider;
import org.hl7.fhir.r5.conformance.profile.ProfileUtilities;
import org.hl7.fhir.r5.context.BaseWorkerContext;
import org.hl7.fhir.r5.context.IWorkerContext;
@ -45,6 +48,7 @@ import org.hl7.fhir.r5.model.Constants;
import org.hl7.fhir.r5.model.Resource;
import org.hl7.fhir.r5.model.StructureDefinition;
import org.hl7.fhir.r5.model.ValueSet;
import org.hl7.fhir.r5.model.ElementDefinition.ElementDefinitionBindingComponent;
import org.hl7.fhir.r5.renderers.CodeSystemRenderer;
import org.hl7.fhir.r5.renderers.StructureDefinitionRenderer;
import org.hl7.fhir.r5.renderers.ValueSetRenderer;
@ -155,6 +159,7 @@ public class ComparisonTests {
}
RenderingContext lrc = new RenderingContext(context, new MarkDownProcessor(Dialect.COMMON_MARK), null, "http://hl7.org/fhir", "", "en", ResourceRendererMode.TECHNICAL, GenerationRules.IG_PUBLISHER);
lrc.setDestDir(Utilities.path("[tmp]", "comparison"));
lrc.setPkp(new TestProfileKnowledgeProvider(context));
if (left instanceof CodeSystem && right instanceof CodeSystem) {
CodeSystemComparer cs = new CodeSystemComparer(session);
@ -199,14 +204,15 @@ public class ComparisonTests {
// String xml3 = new XhtmlComposer(true).compose(cs.renderExpansion(csc, "", ""));
TextFile.stringToFile(HEADER + hd("Messages") + xmle + BREAK + hd("Metadata") + xml1 + BREAK + hd("Structure") + xml2 + FOOTER, Utilities.path("[tmp]", "comparison", name + ".html"));
checkOutcomes(csc.getMessages(), content);
lrc.setStructureMode(StructureDefinitionRendererMode.DATA_DICT);
new StructureDefinitionRenderer(lrc).render(right);
checkOutput(content.getJsonObject("version").asString("filename-dd"), right);
lrc.setStructureMode(StructureDefinitionRendererMode.SUMMARY);
new StructureDefinitionRenderer(lrc).render(right);
checkOutput(content.getJsonObject("version").asString("filename-tree"), right);
lrc.setStructureMode(StructureDefinitionRendererMode.DATA_DICT);
new StructureDefinitionRenderer(lrc).render(right);
checkOutput(content.getJsonObject("version").asString("filename-dd"), right);
} else if (left instanceof CapabilityStatement && right instanceof CapabilityStatement) {
CapabilityStatementComparer pc = new CapabilityStatementComparer(session);
CapabilityStatementComparison csc = pc.compare((CapabilityStatement) left, (CapabilityStatement) right);
@ -322,4 +328,83 @@ public class ComparisonTests {
Assertions.assertEquals(output.asInteger("infoCount"), hc, "Expected " + Integer.toString(output.asInteger("infoCount")) + " hints, but found " + Integer.toString(hc) + ".");
}
public class TestProfileKnowledgeProvider implements ProfileKnowledgeProvider {
private IWorkerContext context;
public TestProfileKnowledgeProvider(IWorkerContext context) {
this.context = context;
}
@Override
public boolean isDatatype(String typeSimple) {
throw new NotImplementedException();
}
@Override
public boolean isPrimitiveType(String typeSimple) {
throw new NotImplementedException();
}
@Override
public boolean isResource(String typeSimple) {
throw new NotImplementedException();
}
@Override
public boolean hasLinkFor(String typeSimple) {
return getLinkFor(null, typeSimple) != null;
}
@Override
public String getLinkFor(String corePath, String typeSimple) {
StructureDefinition sd = context.fetchTypeDefinition(typeSimple);
if (sd != null) {
return sd.getWebPath();
}
return null;
}
@Override
public BindingResolution resolveBinding(StructureDefinition def, ElementDefinitionBindingComponent binding, String path) throws FHIRException {
ValueSet vs = context.fetchResource(ValueSet.class, binding.getValueSet());
if (vs != null) {
return new BindingResolution(vs.present(), vs.getWebPath());
} else {
return new BindingResolution(binding.getValueSet(), null);
}
}
@Override
public BindingResolution resolveBinding(StructureDefinition def, String url, String path) throws FHIRException {
ValueSet vs = context.fetchResource(ValueSet.class, url);
if (vs != null) {
if (vs.hasWebPath()) {
return new BindingResolution(vs.present(), vs.getWebPath());
} else {
return new BindingResolution(vs.present(), "valueset-"+vs.getIdBase()+".html");
}
}
throw new NotImplementedException();
}
@Override
public String getLinkForProfile(StructureDefinition profile, String url) {
if ("http://hl7.org/fhir/StructureDefinition/Composition".equals(url)) {
return "http://hl7.org/fhir/composition.html|TestComposition";
}
throw new NotImplementedException();
}
@Override
public boolean prependLinks() {
return false;
}
@Override
public String getLinkForUrl(String corePath, String s) {
throw new NotImplementedException();
}
}
}

View File

@ -120,7 +120,7 @@ public class StructureMappingTests {
fail(e.getMessage());
}
if (output.endsWith("json")) {
msg = CompareUtilities.checkJsonSrcIsSame(s.toString(), outputJson);
msg = CompareUtilities.checkJsonSrcIsSame(s.toString(), outputJson, null);
} else {
TextFile.bytesToFile(s.toByteArray(), fileOutputRes);
TextFile.bytesToFile(outputJson.getBytes(), fileOutputResOrig);

View File

@ -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";
@ -55,6 +55,7 @@ public class ExternalTerminologyServiceTests implements ITxTesterLoader {
public static Iterable<Object[]> data() throws IOException {
String contents = TestingUtilities.loadTestResource("tx", "test-cases.json");
externals = org.hl7.fhir.utilities.json.parser.JsonParser.parseObject(TestingUtilities.loadTestResource("tx", "messages-tx.fhir.org.json"));
Map<String, JsonObjectPair> examples = new HashMap<String, JsonObjectPair>();
manifest = org.hl7.fhir.utilities.json.parser.JsonParser.parseObject(contents);
@ -78,6 +79,7 @@ public class ExternalTerminologyServiceTests implements ITxTesterLoader {
}
private static org.hl7.fhir.utilities.json.model.JsonObject manifest;
private static org.hl7.fhir.utilities.json.model.JsonObject externals;
private JsonObjectPair setup;
private String version = "5.0.0";
private static TxTester tester;
@ -92,7 +94,7 @@ public class ExternalTerminologyServiceTests implements ITxTesterLoader {
public void test() throws Exception {
if (SERVER != null) {
if (tester == null) {
tester = new TxTester(this, SERVER, true);
tester = new TxTester(this, SERVER, true, externals);
}
String err = tester.executeTest(setup.suite, setup.test, modes);
Assertions.assertTrue(err == null, err);

View File

@ -76,7 +76,9 @@ public class TerminologyServiceTests {
public static Iterable<Object[]> data() throws IOException {
String contents = TestingUtilities.loadTestResource("tx", "test-cases.json");
String externalSource = TestingUtilities.loadTestResource("tx", "messages-tx.fhir.org.json");
externals = org.hl7.fhir.utilities.json.parser.JsonParser.parseObject(externalSource);
Map<String, JsonObjectPair> examples = new HashMap<String, JsonObjectPair>();
manifest = org.hl7.fhir.utilities.json.parser.JsonParser.parseObject(contents);
for (org.hl7.fhir.utilities.json.model.JsonObject suite : manifest.getJsonObjects("suites")) {
@ -99,6 +101,7 @@ public class TerminologyServiceTests {
}
private static org.hl7.fhir.utilities.json.model.JsonObject manifest;
private static org.hl7.fhir.utilities.json.model.JsonObject externals;
private JsonObjectPair setup;
private String version;
private String name;
@ -128,6 +131,7 @@ public class TerminologyServiceTests {
String fn = setup.test.asString("response");
String resp = TestingUtilities.loadTestResource("tx", fn);
String fp = Utilities.path("[tmp]", "tx", fn);
JsonObject ext = externals == null ? null : externals.getJsonObject(fn);
File fo = new File(fp);
if (fo.exists()) {
fo.delete();
@ -138,15 +142,15 @@ public class TerminologyServiceTests {
engine.getContext().setExpansionProfile((org.hl7.fhir.r5.model.Parameters) loadResource("parameters-default.json"));
}
if (setup.test.asString("operation").equals("expand")) {
expand(engine, req, resp, fp);
expand(engine, req, resp, fp, ext);
} else if (setup.test.asString("operation").equals("validate-code")) {
validate(engine, setup.test.asString("name"), req, resp, fp);
validate(engine, setup.test.asString("name"), req, resp, fp, ext);
} else {
Assertions.fail("Unknown Operation "+setup.test.asString("operation"));
}
}
private void expand(ValidationEngine engine, Resource req, String resp, String fp) throws IOException {
private void expand(ValidationEngine engine, Resource req, String resp, String fp, JsonObject ext) throws IOException {
org.hl7.fhir.r5.model.Parameters p = ( org.hl7.fhir.r5.model.Parameters) req;
ValueSet vs = engine.getContext().fetchResource(ValueSet.class, p.getParameterValue("url").primitiveValue());
boolean hierarchical = p.hasParameter("excludeNested") ? p.getParameterBool("excludeNested") == false : true;
@ -162,7 +166,7 @@ public class TerminologyServiceTests {
TxTesterSorters.sortValueSet(vse.getValueset());
TxTesterScrubbers.scrubVS(vse.getValueset(), false);
String vsj = new JsonParser().setOutputStyle(OutputStyle.PRETTY).composeString(vse.getValueset());
String diff = CompareUtilities.checkJsonSrcIsSame(resp, vsj);
String diff = CompareUtilities.checkJsonSrcIsSame(resp, vsj, ext);
if (diff != null) {
Utilities.createDirectory(Utilities.getDirectoryForFile(fp));
TextFile.stringToFile(vsj, fp);
@ -207,7 +211,7 @@ public class TerminologyServiceTests {
TxTesterScrubbers.scrubOO(oo, false);
String ooj = new JsonParser().setOutputStyle(OutputStyle.PRETTY).composeString(oo);
String diff = CompareUtilities.checkJsonSrcIsSame(resp, ooj);
String diff = CompareUtilities.checkJsonSrcIsSame(resp, ooj, ext);
if (diff != null) {
Utilities.createDirectory(Utilities.getDirectoryForFile(fp));
TextFile.stringToFile(ooj, fp);
@ -225,7 +229,7 @@ public class TerminologyServiceTests {
}
}
private void validate(ValidationEngine engine, String name, Resource req, String resp, String fp) throws JsonSyntaxException, FileNotFoundException, IOException {
private void validate(ValidationEngine engine, String name, Resource req, String resp, String fp, JsonObject ext) throws JsonSyntaxException, FileNotFoundException, IOException {
org.hl7.fhir.r5.model.Parameters p = (org.hl7.fhir.r5.model.Parameters) req;
ValueSet vs = null;
if (p.hasParameter("valueSetVersion")) {
@ -299,7 +303,7 @@ public class TerminologyServiceTests {
TxTesterScrubbers.scrubParams(res);
String pj = new JsonParser().setOutputStyle(OutputStyle.PRETTY).composeString(res);
String diff = CompareUtilities.checkJsonSrcIsSame(resp, pj);
String diff = CompareUtilities.checkJsonSrcIsSame(resp, pj, ext);
if (diff != null) {
Utilities.createDirectory(Utilities.getDirectoryForFile(fp));
TextFile.stringToFile(pj, fp);