Add support for external strings for tx tests
This commit is contained in:
parent
4d7ecec87c
commit
eacffd11df
|
@ -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)));
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -7,4 +7,8 @@ public abstract class JsonPrimitive extends JsonElement {
|
|||
public String toJson() {
|
||||
return getValue();
|
||||
}
|
||||
|
||||
public boolean asBoolean() {
|
||||
return "true".equals(getValue());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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";
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue