Merge pull request #1806 from hapifhir/2024-11-gg-tx-test-metadata

Start testing metadata in tx tests, and consequent bugs and library u…
This commit is contained in:
Grahame Grieve 2024-11-12 15:54:54 +10:30 committed by GitHub
commit 82cbb6067f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
27 changed files with 520 additions and 142 deletions

View File

@ -163,6 +163,11 @@ public class TerminologyClientR2 implements ITerminologyClient {
return (CapabilityStatement) VersionConvertorFactory_10_50.convertResource(client.getConformanceStatementQuick());
}
@Override
public CapabilityStatement getCapabilitiesStatement() throws FHIRException {
return (CapabilityStatement) VersionConvertorFactory_10_50.convertResource(client.getConformanceStatement());
}
@Override
public Parameters lookupCode(Map<String, String> params) throws FHIRException {
return (Parameters) VersionConvertorFactory_10_50.convertResource(client.lookupCode(params));

View File

@ -153,6 +153,11 @@ public class TerminologyClientR3 implements ITerminologyClient {
return (CapabilityStatement) VersionConvertorFactory_30_50.convertResource(client.getCapabilitiesStatementQuick());
}
@Override
public CapabilityStatement getCapabilitiesStatement() throws FHIRException {
return (CapabilityStatement) VersionConvertorFactory_30_50.convertResource(client.getCapabilitiesStatement());
}
@Override
public Parameters lookupCode(Map<String, String> params) throws FHIRException {
return (Parameters) VersionConvertorFactory_30_50.convertResource(client.lookupCode(params));

View File

@ -64,7 +64,7 @@ public class TerminologyClientR4 implements ITerminologyClient {
}
public FhirPublication getActualVersion() {
return FhirPublication.STU3;
return FhirPublication.R4;
}
@ -177,6 +177,11 @@ public class TerminologyClientR4 implements ITerminologyClient {
return (CapabilityStatement) VersionConvertorFactory_40_50.convertResource(client.getCapabilitiesStatementQuick());
}
@Override
public CapabilityStatement getCapabilitiesStatement() throws FHIRException {
return (CapabilityStatement) VersionConvertorFactory_40_50.convertResource(client.getCapabilitiesStatement());
}
@Override
public Parameters lookupCode(Map<String, String> params) throws FHIRException {
return (Parameters) VersionConvertorFactory_40_50.convertResource(client.lookupCode(params));

View File

@ -71,7 +71,6 @@ public class FHIRToolingClient extends FHIRBaseToolingClient {
@Setter
private ResourceFormat preferredResourceFormat;
private int maxResultSetSize = -1;// _count
private CapabilityStatement capabilities;
@Getter
@Setter
private Client client = new Client();
@ -100,13 +99,6 @@ public class FHIRToolingClient extends FHIRBaseToolingClient {
this.maxResultSetSize = -1;
}
private void checkCapabilities() {
try {
capabilities = getCapabilitiesStatementQuick();
} catch (Throwable e) {
}
}
public String getPreferredResourceFormat() {
return preferredResourceFormat.getHeader();
}
@ -130,10 +122,10 @@ public class FHIRToolingClient extends FHIRBaseToolingClient {
return capabilities;
}
public CapabilityStatement getCapabilitiesStatement() {
public CapabilityStatement getCapabilitiesStatementQuick() {
CapabilityStatement conformance = null;
try {
conformance = (CapabilityStatement) client.issueGetResourceRequest(resourceAddress.resolveMetadataUri(false),
conformance = (CapabilityStatement) client.issueGetResourceRequest(resourceAddress.resolveMetadataUri(true),
withVer(getPreferredResourceFormat(), "4.0"), generateHeaders(false), "CapabilitiesStatement", timeoutNormal).getReference();
} catch (Exception e) {
throw new FHIRException("Error fetching the server's conformance statement", e);
@ -141,18 +133,15 @@ public class FHIRToolingClient extends FHIRBaseToolingClient {
return conformance;
}
public CapabilityStatement getCapabilitiesStatementQuick() throws EFhirClientException {
if (capabilities != null)
return capabilities;
try {
capabilities = (CapabilityStatement) client.issueGetResourceRequest(resourceAddress.resolveMetadataUri(true),
withVer(getPreferredResourceFormat(), "4.0"), generateHeaders(false), "CapabilitiesStatement-Quick", timeoutNormal)
.getReference();
} catch (Exception e) {
throw new FHIRException("Error fetching the server's capability statement: " + e.getMessage(), e);
}
return capabilities;
}
public CapabilityStatement getCapabilitiesStatement() throws EFhirClientException {
try {
return (CapabilityStatement) client.issueGetResourceRequest(resourceAddress.resolveMetadataUri(false),
withVer(getPreferredResourceFormat(), "4.0"), generateHeaders(false), "CapabilitiesStatement-Quick", timeoutNormal)
.getReference();
} catch (Exception e) {
throw new FHIRException("Error fetching the server's capability statement: " + e.getMessage(), e);
}
}
public Resource read(String resourceClass, String id) {// TODO Change this to AddressableResource
recordUse();
@ -562,8 +551,7 @@ public class FHIRToolingClient extends FHIRBaseToolingClient {
}
public String getServerVersion() {
checkCapabilities();
return capabilities == null ? null : capabilities.getSoftware().getVersion();
return getCapabilitiesStatementQuick().getSoftware().getVersion();
}
public Bundle search(String type, String criteria) {

View File

@ -61,11 +61,11 @@ public class TextClientLogger extends BaseLogger implements ToolingClientLogger
file.println("\r\n--- " + id + " -----------------\r\nRequest: \r\n");
file.println(method + " " + url + " HTTP/1.0");
for (String s : headers)
file.println(Utilities.escapeXml(s));
file.println(s);
if (body != null) {
file.println("");
try {
file.println(Utilities.escapeXml(new String(body, "UTF-8")));
file.println(new String(body, "UTF-8"));
} catch (UnsupportedEncodingException e) {
}
}
@ -82,7 +82,7 @@ public class TextClientLogger extends BaseLogger implements ToolingClientLogger
if (body != null) {
file.println("");
try {
file.println(Utilities.escapeXml(new String(body, "UTF-8")));
file.println(new String(body, "UTF-8"));
} catch (UnsupportedEncodingException e) {
}
}

View File

@ -60,6 +60,7 @@ public interface ITerminologyClient {
ITerminologyClient setLogger(ToolingClientLogger txLog) throws FHIRException;
int getRetryCount() throws FHIRException;
ITerminologyClient setRetryCount(int retryCount) throws FHIRException;
CapabilityStatement getCapabilitiesStatement() throws FHIRException;
CapabilityStatement getCapabilitiesStatementQuick() throws FHIRException;
Parameters lookupCode(Map<String, String> params) throws FHIRException;
Parameters lookupCode(Parameters params) throws FHIRException;

View File

@ -165,6 +165,11 @@ public class TerminologyClientR5 implements ITerminologyClient {
return client.getCapabilitiesStatementQuick();
}
@Override
public CapabilityStatement getCapabilitiesStatement() {
return client.getCapabilitiesStatement();
}
@Override
public Parameters lookupCode(Map<String, String> params) {
return client.lookupCode(params);

View File

@ -3,6 +3,7 @@ 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.r5.model.Constants;
import org.hl7.fhir.utilities.*;
import org.hl7.fhir.utilities.filesystem.CSFile;
import org.hl7.fhir.utilities.filesystem.ManagedFileAccess;
@ -27,6 +28,7 @@ import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import java.io.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@ -34,12 +36,51 @@ public class CompareUtilities extends BaseTestingUtilities {
private static final boolean SHOW_DIFF = false;
private JsonObject externals;
private Map<String, String> variables;
private boolean patternMode;
public CompareUtilities() {
super();
this.variables = new HashMap<String, String>();
}
public CompareUtilities(JsonObject externals) {
super();
this.externals = externals;
this.variables = new HashMap<String, String>();
}
public CompareUtilities(JsonObject externals, Map<String, String> variables) {
super();
this.externals = externals;
this.variables = variables;
}
/**
* in pattern mode, the comparison is only looking to find the expected properties. anything else is ignored
* @return
*/
public boolean isPatternMode() {
return patternMode;
}
public CompareUtilities setPatternMode(boolean patternMode) {
this.patternMode = patternMode;
return this;
}
public String createNotEqualMessage(String id, final String message, final String expected, final String actual) {
if (patternMode) {
return new StringBuilder()
.append(message).append('\n')
.append("Expected:").append(presentExpected(expected)).append(" for "+id).append('\n')
.append(message).append(". ")
.append("Expected:").append(presentExpected(expected)).append(" for "+id).append(". ")
.append("Actual :").append("\""+actual+"\"").toString();
} else {
return new StringBuilder()
.append(message).append('\n')
.append("Expected:").append(presentExpected(expected)).append(" for "+id).append('\n')
.append("Actual :").append("\""+actual+"\"").toString();
}
}
private String presentExpected(String expected) {
@ -64,8 +105,13 @@ public class CompareUtilities extends BaseTestingUtilities {
switch (expected) {
case "$$" : return "$$";
case "$instant$": return "\"An Instant\"";
case "$date$": return "\"A date\"";
case "$uuid$": return "\"A Uuid\"";
case "$string$": return "\"A string\"";
case "$id$": return "\"An Id\"";
case "$url$": return "\"A URL\"";
case "$token$": return "\"A Token\"";
case "$version$": return variables.containsKey("version") ? variables.get("version") : "(anything)";
default: return "Unhandled template: "+expected;
}
}
@ -74,15 +120,13 @@ public class CompareUtilities extends BaseTestingUtilities {
}
}
public static String checkXMLIsSame(String id, InputStream expected, InputStream actual) throws Exception {
CompareUtilities self = new CompareUtilities();
String result = self.compareXml(id, expected, actual);
public String checkXMLIsSame(String id, InputStream expected, InputStream actual) throws Exception {
String result = compareXml(id, expected, actual);
return result;
}
public static String checkXMLIsSame(String id, String expected, String actual) throws Exception {
CompareUtilities self = new CompareUtilities();
String result = self.compareXml(id, expected, actual);
public String checkXMLIsSame(String id, String expected, String actual) throws Exception {
String result = compareXml(id, expected, actual);
if (result != null && SHOW_DIFF) {
String diff = getDiffTool();
if (diff != null && ManagedFileAccess.file(diff).exists() || Utilities.isToken(diff)) {
@ -92,7 +136,7 @@ public class CompareUtilities extends BaseTestingUtilities {
return result;
}
private static String getDiffTool() throws IOException {
private String getDiffTool() throws IOException {
if (FhirSettings.hasDiffToolPath()) {
return FhirSettings.getDiffToolPath();
} else if (System.getenv("ProgramFiles") != null) {
@ -219,14 +263,12 @@ public class CompareUtilities extends BaseTestingUtilities {
return builder.parse(fn);
}
public static String checkJsonSrcIsSame(String id, String expected, String actual, JsonObject externals) throws FileNotFoundException, IOException {
return checkJsonSrcIsSame(id, expected, actual, true, externals);
public String checkJsonSrcIsSame(String id, String expected, String actual) throws FileNotFoundException, IOException {
return checkJsonSrcIsSame(id, expected, actual, true);
}
public static String checkJsonSrcIsSame(String id, String expectedString, String actualString, boolean showDiff, JsonObject externals) throws FileNotFoundException, IOException {
CompareUtilities self = new CompareUtilities();
self.externals = externals;
String result = self.compareJsonSrc(id, expectedString, actualString);
public String checkJsonSrcIsSame(String id, String expectedString, String actualString, boolean showDiff) throws FileNotFoundException, IOException {
String result = compareJsonSrc(id, expectedString, actualString);
if (result != null && SHOW_DIFF && showDiff) {
String diff = null;
if (System.getProperty("os.name").contains("Linux"))
@ -259,9 +301,8 @@ public class CompareUtilities extends BaseTestingUtilities {
return result;
}
public static String checkJsonIsSame(String id, String expected, String actual) throws FileNotFoundException, IOException {
CompareUtilities self = new CompareUtilities();
String result = self.compareJson(id, expected, actual);
public String checkJsonIsSame(String id, String expected, String actual) throws FileNotFoundException, IOException {
String result = compareJson(id, expected, actual);
if (result != null && SHOW_DIFF) {
String diff = Utilities.path(System.getenv("ProgramFiles(X86)"), "WinMerge", "WinMergeU.exe");
List<String> command = new ArrayList<String>();
@ -294,16 +335,17 @@ public class CompareUtilities extends BaseTestingUtilities {
String n = en.getName();
if (!n.equals("fhir_comments")) {
if (expectedJsonObject.has(n)) {
String s = compareNodes(id, path + '.' + n, expectedJsonObject.get(n), en.getValue(), countOnlys.contains(n));
String s = compareNodes(id, path + '.' + n, expectedJsonObject.get(n), en.getValue(), countOnlys.contains(n), n, actualJsonObject);
if (!Utilities.noString(s))
return s;
} else
return "properties differ at " + path + ": missing property " + n;
} else if (!patternMode) {
return "properties differ at " + path + ": unexpected property " + n;
}
}
}
for (JsonProperty en : expectedJsonObject.getProperties()) {
String n = en.getName();
if (!n.equals("fhir_comments") && !n.equals("$optional$") && !optionals.contains(n)) {
if (!n.equals("fhir_comments") && !isOptional(n, optionals)) {
if (!actualJsonObject.has(n) && !allOptional(en.getValue()))
return "properties differ at " + path + ": missing property " + n;
}
@ -311,6 +353,10 @@ public class CompareUtilities extends BaseTestingUtilities {
return null;
}
private boolean isOptional(String n, List<String> optionals) {
return n.equals("$optional$") || optionals.contains("*") || optionals.contains(n);
}
private boolean allOptional(JsonElement value) {
if (value.isJsonArray()) {
JsonArray a = value.asJsonArray();
@ -352,7 +398,7 @@ public class CompareUtilities extends BaseTestingUtilities {
return res;
}
private String compareNodes(String id, String path, JsonElement expectedJsonElement, JsonElement actualJsonElement, boolean countOnly) {
private String compareNodes(String id, String path, JsonElement expectedJsonElement, JsonElement actualJsonElement, boolean countOnly, String name, JsonObject parent) {
if (!(expectedJsonElement instanceof JsonPrimitive && actualJsonElement instanceof JsonPrimitive)) {
if (actualJsonElement.getClass() != expectedJsonElement.getClass()) {
return createNotEqualMessage(id, "properties differ at " + path, expectedJsonElement.getClass().getName(), actualJsonElement.getClass().getName());
@ -394,30 +440,51 @@ public class CompareUtilities extends BaseTestingUtilities {
return createNotEqualMessage(id, "array item count differs at " + path, Integer.toString(es), Integer.toString(as));
}
} else {
int expectedMin = countExpectedMin(expectedArray);
int oc = optionalCount(expectedArray);
int expectedMin = countExpectedMin(expectedArray, name, parent);
int oc = optionalCount(expectedArray, name, parent);
if (as > es || as < expectedMin)
return createNotEqualMessage(id, "array item count differs at " + path, Integer.toString(es), Integer.toString(as));
int c = 0;
for (int i = 0; i < es; i++) {
if (c >= as) {
if (i >= es - oc && isOptional(expectedArray.get(i))) {
return null; // this is OK
} else {
return "One or more array items did not match at "+path+" starting at index "+i;
if (patternMode) {
int c = 0;
for (int i = 0; i < expectedArray.size(); i++) {
String s = "Doesn't exist";
CommaSeparatedStringBuilder cs = new CommaSeparatedStringBuilder("\r\n");
cs.append("");
while (s != null && c < actualArray.size()) {
s = compareNodes(id, path + "[" + Integer.toString(i) + "]", expectedArray.get(i), actualArray.get(c), false, null, null);
if (s != null) {
cs.append(" "+s);
}
c++;
}
if (s != null) {
return "The expected item at "+path+" at index "+i+" was not found: "+cs.toString();
}
}
String s = compareNodes(id, path + "[" + Integer.toString(i) + "]", expectedArray.get(i), actualArray.get(c), false);
if (!Utilities.noString(s) && !isOptional(expectedArray.get(i))) {
return s;
} else {
if (as > es || as < expectedMin) {
return createNotEqualMessage(id, "array item count differs at " + path, Integer.toString(es), Integer.toString(as));
}
if (Utilities.noString(s)) {
c++;
int c = 0;
for (int i = 0; i < es; i++) {
if (c >= as) {
if (i >= es - oc && isOptional(expectedArray.get(i), name, parent)) {
return null; // this is OK
} else {
return "One or more array items did not match at "+path+" starting at index "+i;
}
}
String s = compareNodes(id, path + "[" + Integer.toString(i) + "]", expectedArray.get(i), actualArray.get(c), false, null, null);
if (!Utilities.noString(s) && !isOptional(expectedArray.get(i), name, parent)) {
return s;
}
if (Utilities.noString(s)) {
c++;
}
}
if (c < as) {
return "Unexpected Node found in array at '"+path+"' at index "+c;
}
}
if (c < as) {
return "Unexpected Node found in array at '"+path+"' at index "+c;
}
}
} else
@ -425,7 +492,7 @@ public class CompareUtilities extends BaseTestingUtilities {
return null;
}
private int optionalCount(JsonArray arr) {
private int optionalCount(JsonArray arr, String name, JsonObject parent) {
int c = 0;
for (JsonElement e : arr) {
if (e.isJsonObject()) {
@ -438,14 +505,14 @@ public class CompareUtilities extends BaseTestingUtilities {
return c;
}
private boolean isOptional(JsonElement e) {
private boolean isOptional(JsonElement e, String name, JsonObject parent) {
return e.isJsonObject() && e.asJsonObject().has("$optional$");
}
private int countExpectedMin(JsonArray array) {
private int countExpectedMin(JsonArray array, String name, JsonObject parent) {
int count = array.size();
for (JsonElement e : array) {
if (isOptional(e)) {
if (isOptional(e, name, parent)) {
count--;
}
}
@ -485,8 +552,13 @@ public class CompareUtilities extends BaseTestingUtilities {
switch (expectedJsonString) {
case "$$" : return true;
case "$instant$": return actualJsonString.matches("([0-9]([0-9]([0-9][1-9]|[1-9]0)|[1-9]00)|[1-9]000)-(0[1-9]|1[0-2])-(0[1-9]|[1-2][0-9]|3[0-1])T([01][0-9]|2[0-3]):[0-5][0-9]:([0-5][0-9]|60)(\\.[0-9]{1,9})?(Z|(\\+|-)((0[0-9]|1[0-3]):[0-5][0-9]|14:00))");
case "$date$": return actualJsonString.matches("([0-9]([0-9]([0-9][1-9]|[1-9]0)|[1-9]00)|[1-9]000)-(0[1-9]|1[0-2])-(0[1-9]|[1-2][0-9]|3[0-1])(T([01][0-9]|2[0-3]):[0-5][0-9]:([0-5][0-9]|60)(\\.[0-9]{1,9})?(Z|(\\+|-)((0[0-9]|1[0-3]):[0-5][0-9]|14:00)))?");
case "$uuid$": return actualJsonString.matches("urn:uuid:[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}");
case "$string$": return actualJsonString.equals(actualJsonString.trim());
case "$id$": return actualJsonString.matches("[A-Za-z0-9\\-\\.]{1,64}");
case "$url$": return actualJsonString.matches("(https?://|www\\.)[-a-zA-Z0-9+&@#/%?=~_|!:.;]*[-a-zA-Z0-9+&@#/%=~_|]");
case "$token$": return actualJsonString.matches("[0-9a-zA-Z_][0-9a-zA-Z_\\.\\-]*");
case "$version$": return matchesVariable(actualJsonString, "version");
default:
throw new Error("Unhandled template: "+expectedJsonString);
}
@ -496,6 +568,14 @@ public class CompareUtilities extends BaseTestingUtilities {
}
}
private boolean matchesVariable(String value, String name) {
if (variables.containsKey(name)) {
return value.equals(variables.get(name));
} else {
return true;
}
}
private List<String> readChoices(String s) {
List<String> list = new ArrayList<>();
for (String p : s.split("\\|")) {
@ -504,13 +584,12 @@ public class CompareUtilities extends BaseTestingUtilities {
return list;
}
public static String checkTextIsSame(String id, String expected, String actual) throws FileNotFoundException, IOException {
public String checkTextIsSame(String id, String expected, String actual) throws FileNotFoundException, IOException {
return checkTextIsSame(id, expected, actual, true);
}
public static String checkTextIsSame(String id, String expectedString, String actualString, boolean showDiff) throws FileNotFoundException, IOException {
CompareUtilities self = new CompareUtilities();
String result = self.compareText(id, expectedString, actualString);
public String checkTextIsSame(String id, String expectedString, String actualString, boolean showDiff) throws FileNotFoundException, IOException {
String result = compareText(id, expectedString, actualString);
if (result != null && SHOW_DIFF && showDiff) {
String diff = null;
if (System.getProperty("os.name").contains("Linux"))

View File

@ -47,7 +47,7 @@ class LanguageUtilsTest implements ResourceLoaderTests {
.lines()
.collect(Collectors.joining("\n"));
String msg = CompareUtilities.checkJsonSrcIsSame("", generatedResource.toString(),text, null);
String msg = new CompareUtilities().checkJsonSrcIsSame("", generatedResource.toString(),text);
Assertions.assertNull(msg);
}

View File

@ -138,7 +138,7 @@ public class SQLOnFhirTests {
// sortResults(rows);
String expS = JsonParser.compose(exp, true);
String rowS = JsonParser.compose(rows, true);
String c = CompareUtilities.checkJsonSrcIsSame(name, expS, rowS, null);
String c = new CompareUtilities().checkJsonSrcIsSame(name, expS, rowS);
Assertions.assertNull(c, c);
} else if (test.testCase.has("expectCount")) {
Assertions.assertEquals(test.testCase.asInteger("expectCount"), results.size());

View File

@ -98,7 +98,7 @@ public class GraphQLEngineTests implements IGraphQLStorageServices {
IOUtils.copy(CompareUtilities.loadTestResourceStream("r5", "graphql", source), ManagedFileAccess.outStream(CompareUtilities.tempFile("graphql", source)));
IOUtils.copy(CompareUtilities.loadTestResourceStream("r5", "graphql", output), ManagedFileAccess.outStream(CompareUtilities.tempFile("graphql", output)));
TextFile.stringToFile(str.toString(), CompareUtilities.tempFile("graphql", output+".out"));
msg = CompareUtilities.checkJsonIsSame(id, CompareUtilities.tempFile("graphql", output), CompareUtilities.tempFile("graphql", output+".out"));
msg = new CompareUtilities().checkJsonIsSame(id, CompareUtilities.tempFile("graphql", output), CompareUtilities.tempFile("graphql", output+".out"));
Assertions.assertTrue(Utilities.noString(msg), msg);
}
else

View File

@ -279,7 +279,7 @@ public class NarrativeGenerationTests {
String actualFileName = CompareUtilities.tempFile("narrative", test.getId() + ".html");
TextFile.stringToFile(expected, expectedFileName);
TextFile.stringToFile(actual, actualFileName);
String msg = CompareUtilities.checkXMLIsSame(id, expectedFileName, actualFileName);
String msg = new CompareUtilities().checkXMLIsSame(id, expectedFileName, actualFileName);
Assertions.assertTrue(msg == null, "Output does not match expected: "+msg);
String disp = RendererFactory.factory(source, rc).buildSummary(ResourceWrapper.forResource(rc.getContextUtilities(), source));
@ -289,7 +289,7 @@ public class NarrativeGenerationTests {
actualFileName = CompareUtilities.tempFile("narrative", test.getId() + ".txt");
TextFile.stringToFile(expected, expectedFileName);
TextFile.stringToFile(actual, actualFileName);
msg = CompareUtilities.checkTextIsSame(id, expected, actual);
msg = new CompareUtilities().checkTextIsSame(id, expected, actual);
Assertions.assertTrue(msg == null, "Summary Output does not match expected: "+msg);
//

View File

@ -58,7 +58,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(name, src, output, null);
String msg = new CompareUtilities().checkJsonSrcIsSame(name, src, output);
Assertions.assertTrue(msg == null, msg);
}

View File

@ -40,7 +40,7 @@ public class ResourceToElementTest {
Element e = p.parse(res);
new org.hl7.fhir.r5.elementmodel.XmlParser(ctxt).compose(e, ManagedFileAccess.outStream(src), OutputStyle.PRETTY, null);
new XmlParser().setOutputStyle(OutputStyle.PRETTY).compose(ManagedFileAccess.outStream(dst), res);
String msg = CompareUtilities.checkXMLIsSame(filename, src, dst);
String msg = new CompareUtilities().checkXMLIsSame(filename, src, dst);
Assertions.assertNull(msg);
}

View File

@ -157,7 +157,7 @@ public class VocabTests {
String actualFileName = CompareUtilities.tempFile("vocab", test.getId() + ".actual.html");
TextFile.stringToFile(expected, expectedFileName);
TextFile.stringToFile(actual, actualFileName);
String msg = CompareUtilities.checkXMLIsSame(test.id, expectedFileName, actualFileName);
String msg = new CompareUtilities().checkXMLIsSame(test.id, expectedFileName, actualFileName);
Assertions.assertTrue(msg == null, "Output does not match expected: "+msg);
} else {
Assertions.fail("Expansion Failed: "+outcome.getError());

View File

@ -68,7 +68,7 @@ public class GeneratedPEModelTest {
Observation tgt = tp.build(ctxt);
new XmlParser().setOutputStyle(OutputStyle.PRETTY).compose(ManagedFileAccess.outStream(Utilities.path("[tmp]", "pe-instance-gen.xml")), tgt);
String msg = CompareUtilities.checkXMLIsSame("PEGEN", TestingUtilities.loadTestResourceStream("r5", "profiles", "pe-instance.xml"), ManagedFileAccess.inStream(Utilities.path("[tmp]", "pe-instance-gen.xml")));
String msg = new CompareUtilities().checkXMLIsSame("PEGEN", TestingUtilities.loadTestResourceStream("r5", "profiles", "pe-instance.xml"), ManagedFileAccess.inStream(Utilities.path("[tmp]", "pe-instance-gen.xml")));
Assertions.assertNull(msg, msg);
}

View File

@ -422,7 +422,7 @@ public class PETests {
private void checkGeneratedJava(String name) throws FileNotFoundException, IOException {
String actual = Utilities.normalize(TextFile.fileToString(Utilities.path("[tmp]", "codegen", name+".java")));
String expected = Utilities.normalize(TestingUtilities.loadTestResource("r5", "profiles", name+".java"));
String msg = CompareUtilities.checkTextIsSame(name, expected, actual);
String msg = new CompareUtilities().checkTextIsSame(name, expected, actual);
if (msg != null) {
Assertions.fail("Generated code for "+name+" is different: "+msg);
}

View File

@ -59,7 +59,7 @@ public class CompareUtilitiesTests implements ResourceLoaderTests {
InputStream expectedXMLStream = classLoader.getResourceAsStream(expectedXMLPath);
InputStream actualXMLStream = classLoader.getResourceAsStream(actualXMLPath);
final String actualOutput = CompareUtilities.checkXMLIsSame(expectedFileName, expectedXMLStream, actualXMLStream);
final String actualOutput = new CompareUtilities().checkXMLIsSame(expectedFileName, expectedXMLStream, actualXMLStream);
if (expectedOutputFileName == null) {
assertNull(actualOutput);
@ -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(expectedFileName, getResourceAsString(expectedJSONPath), getResourceAsString(actualJSONPath), false, null);
final String actualOutput = new CompareUtilities().checkJsonSrcIsSame(expectedFileName, getResourceAsString(expectedJSONPath), getResourceAsString(actualJSONPath), false);
if (expectedOutputFileName == null) {
assertNull(actualOutput);
} else {

View File

@ -1 +1 @@
properties differ at : missing property unexpectedProperty
properties differ at : unexpected property unexpectedProperty

View File

@ -108,7 +108,7 @@ public class TxServiceTestHelper {
writeDiffToFileSystem( name, expectedResponse, actualResponse);
String diff = CompareUtilities.checkJsonSrcIsSame(id, expectedResponse, actualResponse, externals);
String diff = new CompareUtilities(externals).checkJsonSrcIsSame(id, expectedResponse, actualResponse);
if (diff != null) {
Utilities.createDirectory(Utilities.getDirectoryForFile(fp));
TextFile.stringToFile(actualResponse, fp);
@ -182,7 +182,7 @@ public class TxServiceTestHelper {
writeDiffToFileSystem(name, expectedResponse, actualResponse);
String diff = CompareUtilities.checkJsonSrcIsSame(id, expectedResponse, actualResponse, externals);
String diff = new CompareUtilities(externals).checkJsonSrcIsSame(id, expectedResponse, actualResponse);
if (diff != null) {
Utilities.createDirectory(Utilities.getDirectoryForFile(fp));
TextFile.stringToFile(actualResponse, fp);

View File

@ -19,8 +19,10 @@ import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collection;
import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.TimeZone;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
@ -30,11 +32,13 @@ import org.hl7.fhir.convertors.txClient.TerminologyClientFactory;
import org.hl7.fhir.exceptions.DefinitionException;
import org.hl7.fhir.exceptions.FHIRException;
import org.hl7.fhir.exceptions.FHIRFormatError;
import org.hl7.fhir.r4b.context.TextClientLogger;
import org.hl7.fhir.r5.formats.IParser.OutputStyle;
import org.hl7.fhir.r5.model.CapabilityStatement;
import org.hl7.fhir.r5.model.OperationOutcome;
import org.hl7.fhir.r5.model.Parameters;
import org.hl7.fhir.r5.model.Resource;
import org.hl7.fhir.r5.model.TerminologyCapabilities;
import org.hl7.fhir.r5.model.ValueSet;
import org.hl7.fhir.r5.terminologies.client.ITerminologyClient;
import org.hl7.fhir.r5.test.utils.CompareUtilities;
@ -65,6 +69,8 @@ public class TxTester {
private JsonObject externals;
private String software;
private List<String> fails = new ArrayList<>();
private CapabilityStatement cstmt;
private TerminologyCapabilities tc;
public TxTester(ITxTesterLoader loader, String server, boolean tight, JsonObject externals) {
@ -107,14 +113,14 @@ public class TxTester {
json.add("date", new SimpleDateFormat("EEE, MMM d, yyyy HH:mmZ", new Locale("en", "US")).format(Calendar.getInstance().getTime()) + timezone());
try {
JsonObject tests = loadTests();
ITerminologyClient tx = connectToServer(modes);
boolean ok = checkClient(tx);
tx = connectToServer(modes);
boolean ok = checkClient();
for (JsonObject suite : tests.getJsonObjects("suites")) {
if ((!suite.has("mode") || modes.contains(suite.asString("mode")))) {
if (suite.asBoolean("disabled")) {
// ok = true;
} else {
ok = runSuite(suite, tx, modes, filter, json.forceArray("suites")) && ok;
ok = runSuite(suite, modes, filter, json.forceArray("suites")) && ok;
}
}
}
@ -123,10 +129,10 @@ public class TxTester {
if (filter == null) {
String m = modes.isEmpty() ? "[none]" : CommaSeparatedStringBuilder.join(";", modes);
if (ok) {
System.out.println(software+" passed all HL7 terminology service tests (modes "+m+", tests v"+loadVersion()+", runner v"+VersionUtil.getBaseVersion()+")");
System.out.println(software+" passed all HL7 terminology service tests ("+Utilities.pluralize("mode", modes.size())+" "+m+", tests v"+loadVersion()+", runner v"+VersionUtil.getBaseVersion()+")");
return true;
} else {
System.out.println(software+" did not pass all HL7 terminology service tests (modes "+m+", tests v"+loadVersion()+", runner v"+VersionUtil.getBaseVersion()+")");
System.out.println(software+" did not pass all HL7 terminology service tests ("+Utilities.pluralize("mode", modes.size())+" "+m+", tests v"+loadVersion()+", runner v"+VersionUtil.getBaseVersion()+")");
System.out.println("Failed Tests: "+ CommaSeparatedStringBuilder.join(",", fails ));
return false;
}
@ -153,12 +159,12 @@ public class TxTester {
return offset;
}
private boolean checkClient(ITerminologyClient tx) {
CapabilityStatement cstmt = tx.getCapabilitiesStatementQuick();
private boolean checkClient() {
cstmt = tx.getCapabilitiesStatement();
if (cstmt.hasSoftware()) {
software = cstmt.getSoftware().getName()+" v"+cstmt.getSoftware().getVersion();
}
tx.getTerminologyCapabilities();
tc = tx.getTerminologyCapabilities();
return true;
}
@ -171,7 +177,7 @@ public class TxTester {
return processHistoryMarkdown(loader.loadContent("history.md"));
}
private String processHistoryMarkdown(byte[] content) throws IOException {
public static String processHistoryMarkdown(byte[] content) throws IOException {
DataInputStream in = new DataInputStream(new ByteArrayInputStream(content));
BufferedReader br = new BufferedReader(new InputStreamReader(in));
try {
@ -179,7 +185,7 @@ public class TxTester {
//Read File Line By Line
while ((strLine = br.readLine()) != null) {
if (strLine.startsWith("## ")) {
return strLine.substring(3);
return strLine.substring(3).trim();
}
}
} finally {
@ -189,7 +195,7 @@ public class TxTester {
return "<1.6.0";
}
private ITerminologyClient connectToServer(List<String> modes) throws URISyntaxException {
private ITerminologyClient connectToServer(List<String> modes) throws URISyntaxException, IOException {
System.out.println("Connect to "+server);
software = server;
ITerminologyClient client = new TerminologyClientFactory(FhirPublication.R4).makeClient("Test-Server", server, "Tools/Java", null);
@ -201,18 +207,18 @@ public class TxTester {
error = null;
if (tx == null) {
tx = connectToServer(modes);
checkClient(tx);
checkClient();
}
List<Resource> setup = loadSetupResources(suite);
if (runTest(suite, test, tx, setup, modes, "*", null)) {
if (runTest(suite, test, setup, modes, "*", null)) {
return null;
} else {
return error;
}
}
private boolean runSuite(JsonObject suite, ITerminologyClient tx, List<String> modes, String filter, JsonArray output) throws FHIRFormatError, FileNotFoundException, IOException {
private boolean runSuite(JsonObject suite, List<String> modes, String filter, JsonArray output) throws FHIRFormatError, FileNotFoundException, IOException {
System.out.println("Group "+suite.asString("name"));
JsonObject outputS = new JsonObject();
if (output != null) {
@ -226,14 +232,14 @@ public class TxTester {
if (test.asBoolean("disabled")) {
ok = true;
} else {
ok = runTest(suite, test, tx, setup, modes, filter, outputS.forceArray("tests")) && ok;
ok = runTest(suite, test, setup, modes, filter, outputS.forceArray("tests")) && ok;
}
}
}
return ok;
}
private boolean runTest(JsonObject suite, JsonObject test, ITerminologyClient tx, List<Resource> setup, List<String> modes, String filter, JsonArray output) throws FHIRFormatError, DefinitionException, FileNotFoundException, FHIRException, IOException {
private boolean runTest(JsonObject suite, JsonObject test, List<Resource> setup, List<String> modes, String filter, JsonArray output) throws FHIRFormatError, DefinitionException, FileNotFoundException, FHIRException, IOException {
JsonObject outputT = new JsonObject();
if (output != null) {
output.add(outputT);
@ -253,7 +259,8 @@ public class TxTester {
}
}
Parameters req = (Parameters) loader.loadResource(chooseParam(test, "request", modes));
String reqFile = chooseParam(test, "request", modes);
Parameters req = reqFile == null ? null : (Parameters) loader.loadResource(reqFile);
String fn = chooseParam(test, "response", modes);
String resp = TextFile.bytesToString(loader.loadContent(fn));
@ -266,16 +273,20 @@ public class TxTester {
String lang = test.asString("Content-Language");
String msg = null;
if (test.asString("operation").equals("expand")) {
msg = expand(test.str("name"), tx, setup, req, resp, fp, lang, profile, ext, getResponseCode(test));
if (test.asString("operation").equals("metadata")) {
msg = metadata(test.str("name"), setup, resp, fp, lang, profile, ext);
} else if (test.asString("operation").equals("term-caps")) {
msg = termcaps(test.str("name"), setup, resp, fp, lang, profile, ext);
} else if (test.asString("operation").equals("expand")) {
msg = expand(test.str("name"), setup, req, resp, fp, lang, profile, ext, getResponseCode(test));
} else if (test.asString("operation").equals("validate-code")) {
msg = validate(test.str("name"),tx, setup, req, resp, fp, lang, profile, ext, getResponseCode(test));
msg = validate(test.str("name"), setup, req, resp, fp, lang, profile, ext, getResponseCode(test));
} else if (test.asString("operation").equals("cs-validate-code")) {
msg = validateCS(test.str("name"),tx, setup, req, resp, fp, lang, profile, ext, getResponseCode(test));
msg = validateCS(test.str("name"), setup, req, resp, fp, lang, profile, ext, getResponseCode(test));
} else if (test.asString("operation").equals("lookup")) {
msg = lookup(test.str("name"),tx, setup, req, resp, fp, lang, profile, ext, getResponseCode(test));
msg = lookup(test.str("name"), setup, req, resp, fp, lang, profile, ext, getResponseCode(test));
} else if (test.asString("operation").equals("translate")) {
msg = translate(test.str("name"),tx, setup, req, resp, fp, lang, profile, ext, getResponseCode(test));
msg = translate(test.str("name"), setup, req, resp, fp, lang, profile, ext, getResponseCode(test));
} else {
throw new Exception("Unknown Operation "+test.asString("operation"));
}
@ -311,6 +322,34 @@ public class TxTester {
}
}
private String metadata(String id, List<Resource> setup, String resp, String fp, String lang, Parameters profile, JsonObject ext) throws IOException {
CapabilityStatement cs = cstmt.copy();
TxTesterScrubbers.scrubCapStmt(cs, tight);
TxTesterSorters.sortCapStmt(cs);
String csj = new org.hl7.fhir.r5.formats.JsonParser().setOutputStyle(OutputStyle.PRETTY).composeString(cs);
String diff = new CompareUtilities(ext, vars()).setPatternMode(true).checkJsonSrcIsSame(id, resp, csj, false);
if (diff != null) {
Utilities.createDirectory(Utilities.getDirectoryForFile(fp));
TextFile.stringToFile(csj, fp);
}
return diff;
}
private String termcaps(String id, List<Resource> setup, String resp, String fp, String lang, Parameters profile, JsonObject ext) throws IOException {
TerminologyCapabilities cs = tc.copy();
TxTesterScrubbers.scrubTermCaps(cs, tight);
TxTesterSorters.sortTermCaps(cs);
String csj = new org.hl7.fhir.r5.formats.JsonParser().setOutputStyle(OutputStyle.PRETTY).composeString(cs);
String diff = new CompareUtilities(ext, vars()).setPatternMode(true).checkJsonSrcIsSame(id, resp, csj, false);
if (diff != null) {
Utilities.createDirectory(Utilities.getDirectoryForFile(fp));
TextFile.stringToFile(csj, fp);
}
return diff;
}
private String getResponseCode(JsonObject test) {
if (test.has("http-code")) {
return test.asString("http-code");
@ -340,7 +379,7 @@ public class TxTester {
return new URI(server).getHost();
}
private String lookup(String id, ITerminologyClient tx, List<Resource> setup, Parameters p, String resp, String fp, String lang, Parameters profile, JsonObject ext, String tcode) throws IOException {
private String lookup(String id, List<Resource> setup, Parameters p, String resp, String fp, String lang, Parameters profile, JsonObject ext, String tcode) throws IOException {
for (Resource r : setup) {
p.addParameter().setName("tx-resource").setResource(r);
}
@ -363,7 +402,7 @@ public class TxTester {
if (tcode != null && !httpCodeOk(tcode, code)) {
return "Response Code fail: should be '"+tcode+"' but is '"+code+"'";
}
String diff = CompareUtilities.checkJsonSrcIsSame(id, resp, pj, false, ext);
String diff = new CompareUtilities(ext, vars()).checkJsonSrcIsSame(id, resp, pj, false);
if (diff != null) {
Utilities.createDirectory(Utilities.getDirectoryForFile(fp));
TextFile.stringToFile(pj, fp);
@ -371,7 +410,7 @@ public class TxTester {
return diff;
}
private String translate(String id, ITerminologyClient tx, List<Resource> setup, Parameters p, String resp, String fp, String lang, Parameters profile, JsonObject ext, String tcode) throws IOException {
private String translate(String id, List<Resource> setup, Parameters p, String resp, String fp, String lang, Parameters profile, JsonObject ext, String tcode) throws IOException {
for (Resource r : setup) {
p.addParameter().setName("tx-resource").setResource(r);
}
@ -394,7 +433,7 @@ public class TxTester {
if (tcode != null && !httpCodeOk(tcode, code)) {
return "Response Code fail: should be '"+tcode+"' but is '"+code+"'";
}
String diff = CompareUtilities.checkJsonSrcIsSame(id, resp, pj, false, ext);
String diff = new CompareUtilities(ext, vars()).checkJsonSrcIsSame(id, resp, pj, false);
if (diff != null) {
Utilities.createDirectory(Utilities.getDirectoryForFile(fp));
TextFile.stringToFile(pj, fp);
@ -402,7 +441,7 @@ public class TxTester {
return diff;
}
private String expand(String id, ITerminologyClient tx, List<Resource> setup, Parameters p, String resp, String fp, String lang, Parameters profile, JsonObject ext, String tcode) throws IOException {
private String expand(String id, List<Resource> setup, Parameters p, String resp, String fp, String lang, Parameters profile, JsonObject ext, String tcode) throws IOException {
for (Resource r : setup) {
p.addParameter().setName("tx-resource").setResource(r);
}
@ -425,7 +464,7 @@ public class TxTester {
if (tcode != null && !httpCodeOk(tcode, code)) {
return "Response Code fail: should be '"+tcode+"' but is '"+code+"'";
}
String diff = CompareUtilities.checkJsonSrcIsSame(id, resp, vsj, false, ext);
String diff = new CompareUtilities(ext, vars()).checkJsonSrcIsSame(id, resp, vsj, false);
if (diff != null) {
Utilities.createDirectory(Utilities.getDirectoryForFile(fp));
TextFile.stringToFile(vsj, fp);
@ -444,7 +483,7 @@ public class TxTester {
}
}
private String validate(String id, ITerminologyClient tx, List<Resource> setup, Parameters p, String resp, String fp, String lang, Parameters profile, JsonObject ext, String tcode) throws IOException {
private String validate(String id, List<Resource> setup, Parameters p, String resp, String fp, String lang, Parameters profile, JsonObject ext, String tcode) throws IOException {
for (Resource r : setup) {
p.addParameter().setName("tx-resource").setResource(r);
}
@ -468,7 +507,7 @@ public class TxTester {
if (tcode != null && !httpCodeOk(tcode, code)) {
return "Response Code fail: should be '"+tcode+"' but is '"+code+"'";
}
String diff = CompareUtilities.checkJsonSrcIsSame(id, resp, pj, false, ext);
String diff = new CompareUtilities(ext, vars()).checkJsonSrcIsSame(id, resp, pj, false);
if (diff != null) {
Utilities.createDirectory(Utilities.getDirectoryForFile(fp));
TextFile.stringToFile(pj, fp);
@ -476,7 +515,7 @@ public class TxTester {
return diff;
}
private String validateCS(String id, ITerminologyClient tx, List<Resource> setup, Parameters p, String resp, String fp, String lang, Parameters profile, JsonObject ext, String tcode) throws IOException {
private String validateCS(String id, List<Resource> setup, Parameters p, String resp, String fp, String lang, Parameters profile, JsonObject ext, String tcode) throws IOException {
for (Resource r : setup) {
p.addParameter().setName("tx-resource").setResource(r);
}
@ -499,7 +538,7 @@ public class TxTester {
if (tcode != null && !httpCodeOk(tcode, code)) {
return "Response Code fail: should be '"+tcode+"' but is '"+code+"'";
}
String diff = CompareUtilities.checkJsonSrcIsSame(id, resp, pj, false, ext);
String diff = new CompareUtilities(ext, vars()).checkJsonSrcIsSame(id, resp, pj, false);
if (diff != null) {
Utilities.createDirectory(Utilities.getDirectoryForFile(fp));
TextFile.stringToFile(pj, fp);
@ -508,6 +547,13 @@ public class TxTester {
}
private Map<String, String> vars() {
Map<String, String> vars = new HashMap<String, String>();
vars.put("version", tx.getActualVersion().toCode());
return vars;
}
private List<Resource> loadSetupResources(JsonObject suite) throws FHIRFormatError, FileNotFoundException, IOException {
List<Resource> res = new ArrayList<>();
for (String s : suite.getStrings("setup")) {

View File

@ -1,5 +1,7 @@
package org.hl7.fhir.validation.special;
import org.hl7.fhir.r5.model.CapabilityStatement;
import org.hl7.fhir.r5.model.CapabilityStatement.CapabilityStatementRestComponent;
import org.hl7.fhir.r5.model.DomainResource;
import org.hl7.fhir.r5.model.Element;
import org.hl7.fhir.r5.model.Extension;
@ -7,6 +9,7 @@ import org.hl7.fhir.r5.model.OperationOutcome;
import org.hl7.fhir.r5.model.OperationOutcome.OperationOutcomeIssueComponent;
import org.hl7.fhir.r5.model.Parameters;
import org.hl7.fhir.r5.model.Resource;
import org.hl7.fhir.r5.model.TerminologyCapabilities;
import org.hl7.fhir.r5.model.ValueSet;
import org.hl7.fhir.r5.utils.ElementVisitor;
import org.hl7.fhir.r5.utils.ElementVisitor.ElementVisitorInstruction;
@ -98,4 +101,12 @@ public class TxTesterScrubbers {
}
}
public static void scrubCapStmt(CapabilityStatement cs, boolean tight) {
// nothing yet?
}
public static void scrubTermCaps(TerminologyCapabilities cs, boolean tight) {
// nothing yet?
}
}

View File

@ -8,18 +8,34 @@ import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import org.hl7.fhir.r5.formats.IParser.OutputStyle;
import org.hl7.fhir.r5.formats.JsonParser;
import org.hl7.fhir.r5.model.CanonicalType;
import org.hl7.fhir.r5.model.CapabilityStatement;
import org.hl7.fhir.r5.model.Extension;
import org.hl7.fhir.r5.model.OperationOutcome;
import org.hl7.fhir.r5.model.OperationOutcome.OperationOutcomeIssueComponent;
import org.hl7.fhir.r5.model.Parameters;
import org.hl7.fhir.r5.model.Parameters.ParametersParameterComponent;
import org.hl7.fhir.r5.model.TerminologyCapabilities.TerminologyCapabilitiesCodeSystemComponent;
import org.hl7.fhir.r5.model.TerminologyCapabilities.TerminologyCapabilitiesCodeSystemVersionComponent;
import org.hl7.fhir.r5.model.TerminologyCapabilities.TerminologyCapabilitiesCodeSystemVersionFilterComponent;
import org.hl7.fhir.r5.model.TerminologyCapabilities.TerminologyCapabilitiesExpansionParameterComponent;
import org.hl7.fhir.r5.model.Resource;
import org.hl7.fhir.r5.model.StringType;
import org.hl7.fhir.r5.model.TerminologyCapabilities;
import org.hl7.fhir.r5.model.ValueSet;
import org.hl7.fhir.r5.model.CapabilityStatement.CapabilityStatementRestComponent;
import org.hl7.fhir.r5.model.CapabilityStatement.CapabilityStatementRestResourceComponent;
import org.hl7.fhir.r5.model.CapabilityStatement.CapabilityStatementRestResourceOperationComponent;
import org.hl7.fhir.r5.model.CapabilityStatement.CapabilityStatementRestResourceSearchParamComponent;
import org.hl7.fhir.r5.model.CapabilityStatement.ResourceInteractionComponent;
import org.hl7.fhir.r5.model.CapabilityStatement.SystemInteractionComponent;
import org.hl7.fhir.r5.model.Enumerations.CommonLanguages;
import org.hl7.fhir.r5.model.CodeType;
import org.hl7.fhir.r5.model.CodeableConcept;
import org.hl7.fhir.r5.model.Coding;
import org.hl7.fhir.r5.model.Enumeration;
import org.hl7.fhir.r5.model.ValueSet.ConceptPropertyComponent;
import org.hl7.fhir.r5.model.ValueSet.ConceptReferenceDesignationComponent;
import org.hl7.fhir.r5.model.ValueSet.ValueSetExpansionContainsComponent;
@ -27,9 +43,11 @@ import org.hl7.fhir.r5.model.ValueSet.ValueSetExpansionParameterComponent;
import org.hl7.fhir.r5.model.ValueSet.ValueSetExpansionPropertyComponent;
import org.hl7.fhir.utilities.CommaSeparatedStringBuilder;
import org.hl7.fhir.utilities.json.JsonException;
import org.hl7.fhir.validation.special.TxTesterSorters.CodeTypeSorter;
public class TxTesterSorters {
public static void main(String[] args) throws JsonException, IOException {
Resource r = new JsonParser().parse(new FileInputStream(args[0]));
switch (r.fhirType()) {
@ -234,7 +252,205 @@ public class TxTesterSorters {
}
}
public static void sortCapStmt(CapabilityStatement cs) {
Collections.sort(cs.getFormat(), new CodeTypeSorter());
Collections.sort(cs.getInstantiates(), new CanonicalTypeSorter());
Collections.sort(cs.getImports(), new CanonicalTypeSorter());
Collections.sort(cs.getAcceptLanguage(), new CodeTypeSorter());
Collections.sort(cs.getRest(), new CSRestSorter());
for (CapabilityStatementRestComponent r : cs.getRest()) {
if (r.hasSecurity()) {
for (CodeableConcept cc : r.getSecurity().getService()) {
Collections.sort(cc.getCoding(), new CodingSorter());
}
Collections.sort(r.getSecurity().getService(), new CodeableConceptSorter());
}
Collections.sort(r.getResource(), new CSRestResourceSorter());
for (CapabilityStatementRestResourceComponent res : r.getResource()) {
Collections.sort(res.getSupportedProfile(), new CanonicalTypeSorter());
Collections.sort(res.getInteraction(), new CSRestResourceInteractionSorter());
Collections.sort(res.getSearchInclude(), new StringTypeSorter());
Collections.sort(res.getSearchRevInclude(), new StringTypeSorter());
Collections.sort(res.getSearchParam(), new SearchParamSorter());
Collections.sort(res.getOperation(), new CSRestResourceOperationSorter());
}
Collections.sort(r.getInteraction(), new CSRestInteractionSorter());
Collections.sort(r.getSearchParam(), new SearchParamSorter());
Collections.sort(r.getOperation(), new CSRestResourceOperationSorter());
Collections.sort(r.getCompartment(), new CanonicalTypeSorter());
}
}
public static class CodeTypeSorter implements Comparator<CodeType> {
@Override
public int compare(CodeType o1, CodeType o2) {
return o1.asStringValue().compareTo(o2.asStringValue());
}
}
public static class StringTypeSorter implements Comparator<StringType> {
@Override
public int compare(StringType o1, StringType o2) {
return o1.asStringValue().compareTo(o2.asStringValue());
}
}
public static class CanonicalTypeSorter implements Comparator<CanonicalType> {
@Override
public int compare(CanonicalType o1, CanonicalType o2) {
return o1.asStringValue().compareTo(o2.asStringValue());
}
}
public static class CodingSorter implements Comparator<Coding> {
@Override
public int compare(Coding c1, Coding c2) {
if (c1.getSystem().equals(c2.getSystem())) {
return c1.getCode().compareTo(c2.getCode());
} else {
return c1.getSystem().compareTo(c2.getSystem());
}
}
}
public static class CodeableConceptSorter implements Comparator<CodeableConcept> {
@Override
public int compare(CodeableConcept o1, CodeableConcept o2) {
if (o1.hasCoding() && o2.hasCoding()) {
Coding c1 = o1.getCodingFirstRep();
Coding c2 = o2.getCodingFirstRep();
if (c1.getSystem().equals(c2.getSystem())) {
return c1.getCode().compareTo(c2.getCode());
} else {
return c1.getSystem().compareTo(c2.getSystem());
}
} else {
return o1.getText().compareTo(o2.getText());
}
}
}
public static class CSRestSorter implements Comparator<CapabilityStatementRestComponent> {
@Override
public int compare(CapabilityStatementRestComponent o1, CapabilityStatementRestComponent o2) {
return o1.getMode().compareTo(o2.getMode());
}
}
public static class CSRestResourceSorter implements Comparator<CapabilityStatementRestResourceComponent> {
@Override
public int compare(CapabilityStatementRestResourceComponent o1, CapabilityStatementRestResourceComponent o2) {
return o1.getType().compareTo(o2.getType());
}
}
public static class CSRestResourceInteractionSorter implements Comparator<ResourceInteractionComponent> {
@Override
public int compare(ResourceInteractionComponent o1, ResourceInteractionComponent o2) {
return o1.getCode().toCode().compareTo(o2.getCode().toCode());
}
}
public static class CSRestInteractionSorter implements Comparator<SystemInteractionComponent> {
@Override
public int compare(SystemInteractionComponent o1, SystemInteractionComponent o2) {
return o1.getCode().compareTo(o2.getCode());
}
}
public static class SearchParamSorter implements Comparator<CapabilityStatementRestResourceSearchParamComponent> {
@Override
public int compare(CapabilityStatementRestResourceSearchParamComponent o1, CapabilityStatementRestResourceSearchParamComponent o2) {
return o1.getName().compareTo(o2.getName());
}
}
public static class CSRestResourceOperationSorter implements Comparator<CapabilityStatementRestResourceOperationComponent> {
@Override
public int compare(CapabilityStatementRestResourceOperationComponent o1, CapabilityStatementRestResourceOperationComponent o2) {
return o1.getName().compareTo(o2.getName());
}
}
public static void sortTermCaps(TerminologyCapabilities tc) {
Collections.sort(tc.getCodeSystem(), new TCCodeSystemSorter());
for (TerminologyCapabilitiesCodeSystemComponent t : tc.getCodeSystem()) {
Collections.sort(t.getVersion(), new TCCodeSystemVersionSorter());
for (TerminologyCapabilitiesCodeSystemVersionComponent v : t.getVersion()) {
Collections.sort(v.getLanguage(), new LanguageSorter());
Collections.sort(v.getProperty(), new CodeTypeSorter());
Collections.sort(v.getFilter(), new TCCodeSystemVersionFilterSorter());
}
}
Collections.sort(tc.getExpansion().getParameter(), new TCExpansionParameterSorter());
}
public static class LanguageSorter implements Comparator<Enumeration<CommonLanguages>> {
@Override
public int compare(Enumeration<CommonLanguages> o1, Enumeration<CommonLanguages> o2) {
return o1.asStringValue().compareTo(o2.asStringValue());
}
}
public static class TCCodeSystemSorter implements Comparator<TerminologyCapabilitiesCodeSystemComponent> {
@Override
public int compare(TerminologyCapabilitiesCodeSystemComponent o1, TerminologyCapabilitiesCodeSystemComponent o2) {
return o1.getUri().compareTo(o2.getUri());
}
}
public static class TCCodeSystemVersionSorter implements Comparator<TerminologyCapabilitiesCodeSystemVersionComponent> {
@Override
public int compare(TerminologyCapabilitiesCodeSystemVersionComponent o1, TerminologyCapabilitiesCodeSystemVersionComponent o2) {
return o1.getCode() == null || o2.getCode() == null ? 0 : o1.getCode().compareTo(o2.getCode());
}
}
public static class TCCodeSystemVersionFilterSorter implements Comparator<TerminologyCapabilitiesCodeSystemVersionFilterComponent> {
@Override
public int compare(TerminologyCapabilitiesCodeSystemVersionFilterComponent o1, TerminologyCapabilitiesCodeSystemVersionFilterComponent o2) {
return o1.getCode().compareTo(o2.getCode());
}
}
public static class TCExpansionParameterSorter implements Comparator<TerminologyCapabilitiesExpansionParameterComponent> {
@Override
public int compare(TerminologyCapabilitiesExpansionParameterComponent o1, TerminologyCapabilitiesExpansionParameterComponent o2) {
return o1.getName().compareTo(o2.getName());
}
}
}

View File

@ -245,7 +245,7 @@ public class ComparisonTests {
String en = Utilities.path("[tmp]", "comparison", Utilities.changeFileExt(name, ".expected.html"));
TextFile.stringToFile(expected, en);
String msg = CompareUtilities.checkXMLIsSame(id, en, an);
String msg = new CompareUtilities().checkXMLIsSame(id, en, an);
Assertions.assertTrue(msg == null, "Output does not match expected: "+msg);
}

View File

@ -20,7 +20,9 @@ import org.hl7.fhir.r5.model.Constants;
import org.hl7.fhir.r5.model.Resource;
import org.hl7.fhir.r5.test.utils.TestingUtilities;
import org.hl7.fhir.utilities.Utilities;
import org.hl7.fhir.utilities.VersionUtil;
import org.hl7.fhir.utilities.filesystem.ManagedFileAccess;
import org.hl7.fhir.utilities.json.JsonException;
import org.hl7.fhir.utilities.json.model.JsonObject;
import org.hl7.fhir.utilities.settings.FhirSettings;
import org.hl7.fhir.utilities.tests.TestConfig;
@ -81,6 +83,7 @@ public class LocalTerminologyServiceTests implements ITxTesterLoader {
for (String id : names) {
objects.add(new Object[]{id, examples.get(id)});
}
objects.add(new Object[]{"final", null});
return objects;
}
@ -90,6 +93,7 @@ public class LocalTerminologyServiceTests implements ITxTesterLoader {
private String version = "5.0.0";
private static TxTester tester;
private List<String> modes = new ArrayList<>();
private boolean error = false;
public LocalTerminologyServiceTests(String name, JsonObjectPair setup) {
this.setup = setup;
@ -107,17 +111,29 @@ public class LocalTerminologyServiceTests implements ITxTesterLoader {
logTestSkip("No local terminology server available.");
return;
}
if (SERVER != null) {
if (tester == null) {
tester = new TxTester(this, SERVER, true, externals);
if (setup == null) {
if (!error) {
System.out.println("tx.fhir.org passed all HL7 terminology service tests (mode 'tx.fhir.org', tests v"+loadVersion()+", runner v"+VersionUtil.getBaseVersion()+")");
}
String err = tester.executeTest(setup.suite, setup.test, modes);
Assertions.assertTrue(err == null, err);
Assertions.assertTrue(!error);
} else {
Assertions.assertTrue(true);
if (SERVER != null) {
if (tester == null) {
tester = new TxTester(this, SERVER, true, externals);
}
String err = tester.executeTest(setup.suite, setup.test, modes);
error = error || err != null;
Assertions.assertTrue(err == null, err);
} else {
Assertions.assertTrue(true);
}
}
}
private String loadVersion() throws JsonException, IOException {
return TxTester.processHistoryMarkdown(TestingUtilities.loadTestResourceBytes("tx", "history.md"));
}
private void logTestSkip(String reason) {
System.out.println("Skipping test: " + setup.suite.asString("name") + " " + setup.test.asString("name") + " reason: " + reason);
}

View File

@ -92,7 +92,8 @@ private static TxTestData testData;
if (setup.getSuite().asBoolean("disabled") || setup.getTest().asBoolean("disabled")) {
return;
}
Resource req = loadResource(setup.getTest().asString("request"));
String reqFile = setup.getTest().asString("request");
Resource req = reqFile == null ? null : loadResource(reqFile);
String fn = setup.getTest().has("response:tx.fhir.org") ? setup.getTest().asString("response:tx.fhir.org") : setup.getTest().asString("response");
String resp = TestingUtilities.loadTestResource("tx", fn);
String fp = Utilities.path("[tmp]", "tx", fn);
@ -114,7 +115,7 @@ private static TxTestData testData;
} else if (setup.getTest().asString("operation").equals("cs-validate-code")) {
String diff = TxServiceTestHelper.getDiffForValidation(setup.getTest().str("name"), engine.getContext(), setup.getTest().asString("name"), req, resp, setup.getTest().asString("Content-Language"), fp, ext, true);
assertNull(diff, diff);
} else if (Utilities.existsInList(setup.getTest().asString("operation"), "lookup", "translate")) {
} else if (Utilities.existsInList(setup.getTest().asString("operation"), "lookup", "translate", "metadata", "term-caps")) {
Assertions.assertTrue(true); // we don't test these for the internal server
} else {
Assertions.fail("Unknown Operation "+ setup.getTest().asString("operation"));
@ -140,7 +141,7 @@ private static TxTestData testData;
TxTesterSorters.sortValueSet(vse.getValueset());
TxTesterScrubbers.scrubVS(vse.getValueset(), false);
String vsj = new JsonParser().setOutputStyle(OutputStyle.PRETTY).composeString(vse.getValueset());
String diff = CompareUtilities.checkJsonSrcIsSame(id, resp, vsj, ext);
String diff = new CompareUtilities(ext).checkJsonSrcIsSame(id, resp, vsj);
if (diff != null) {
Utilities.createDirectory(Utilities.getDirectoryForFile(fp));
TextFile.stringToFile(vsj, fp);
@ -189,7 +190,7 @@ private static TxTestData testData;
TxTesterScrubbers.scrubOO(oo, false);
String ooj = new JsonParser().setOutputStyle(OutputStyle.PRETTY).composeString(oo);
String diff = CompareUtilities.checkJsonSrcIsSame(id, resp, ooj, ext);
String diff = new CompareUtilities(ext).checkJsonSrcIsSame(id, resp, ooj);
if (diff != null) {
Utilities.createDirectory(Utilities.getDirectoryForFile(fp));
TextFile.stringToFile(ooj, fp);

View File

@ -121,11 +121,11 @@ public class StructureMappingTests {
fail(e.getMessage());
}
if (output.endsWith("json")) {
msg = CompareUtilities.checkJsonSrcIsSame(name, s.toString(), outputJson, null);
msg = new CompareUtilities().checkJsonSrcIsSame(name, s.toString(), outputJson);
} else {
TextFile.bytesToFile(s.toByteArray(), fileOutputRes);
TextFile.bytesToFile(outputJson.getBytes(), fileOutputResOrig);
msg = CompareUtilities.checkXMLIsSame(name, ManagedFileAccess.inStream(fileOutputResOrig), ManagedFileAccess.inStream(fileOutputRes));
msg = new CompareUtilities().checkXMLIsSame(name, ManagedFileAccess.inStream(fileOutputResOrig), ManagedFileAccess.inStream(fileOutputRes));
}
if (!Utilities.noString(msg)) {
System.out.print(s.toString());