From 9a93c4889caee3d7420948db92d89d5fd6ad4693 Mon Sep 17 00:00:00 2001 From: Nico Piel Date: Thu, 30 Jul 2026 18:45:02 +0200 Subject: [PATCH 01/10] Add SonarQube Signed-off-by: Nico Piel --- build.gradle | 1 + 1 file changed, 1 insertion(+) diff --git a/build.gradle b/build.gradle index d9de29d36..7a93eb367 100644 --- a/build.gradle +++ b/build.gradle @@ -45,6 +45,7 @@ plugins { // vulnerability scanning: ./gradlew dependencyCheckAggregate // (replaces the old standalone dependency-check.xml Ant entry point) id 'org.owasp.dependencycheck' version '12.2.2' + id "org.sonarqube" version "7.3.1.8318" } dependencyCheck { From 12298ea8423bc9169b9f57da74a34a1be4d8eec6 Mon Sep 17 00:00:00 2001 From: Nico Piel Date: Thu, 30 Jul 2026 19:11:44 +0200 Subject: [PATCH 02/10] test: run the orphaned HL7v2 loose serializer suite HL7SerializerTests never matched Gradle's '**/*Test.class' filter, so 15 loose-parser round-trip tests have never run in CI. Rename it, and compare ER7-to-XML output with line endings normalized: the fixtures are CRLF while prettyPrintXml emits the platform separator, so these five assertions could only ever have passed on Windows. Signed-off-by: Nico Piel --- .../connect/model/converters/TestUtil.java | 8 +++ ...lizerTests.java => HL7SerializerTest.java} | 51 +++---------------- 2 files changed, 15 insertions(+), 44 deletions(-) rename server/src/test/java/com/mirth/connect/plugins/datatypes/hl7v2/{HL7SerializerTests.java => HL7SerializerTest.java} (74%) diff --git a/server/src/test/java/com/mirth/connect/model/converters/TestUtil.java b/server/src/test/java/com/mirth/connect/model/converters/TestUtil.java index 405550a60..49ce52684 100644 --- a/server/src/test/java/com/mirth/connect/model/converters/TestUtil.java +++ b/server/src/test/java/com/mirth/connect/model/converters/TestUtil.java @@ -52,4 +52,12 @@ public static String prettyPrintXml(String input) throws Exception { public static String convertCRToCRLF(String input) { return input.replaceAll("\r", "\r\n"); } + + /** + * Collapses CRLF/CR/LF to LF and trims surrounding whitespace, so that expected values stored + * in CRLF fixture files compare equal to output whose line separator is platform-dependent. + */ + public static String normalizeLineEndings(String input) { + return input.replaceAll("\r\n|\r|\n", "\n").trim(); + } } diff --git a/server/src/test/java/com/mirth/connect/plugins/datatypes/hl7v2/HL7SerializerTests.java b/server/src/test/java/com/mirth/connect/plugins/datatypes/hl7v2/HL7SerializerTest.java similarity index 74% rename from server/src/test/java/com/mirth/connect/plugins/datatypes/hl7v2/HL7SerializerTests.java rename to server/src/test/java/com/mirth/connect/plugins/datatypes/hl7v2/HL7SerializerTest.java index aae28422b..c2ebc7749 100644 --- a/server/src/test/java/com/mirth/connect/plugins/datatypes/hl7v2/HL7SerializerTests.java +++ b/server/src/test/java/com/mirth/connect/plugins/datatypes/hl7v2/HL7SerializerTest.java @@ -11,27 +11,19 @@ import java.io.File; -import junit.framework.Assert; - import org.apache.commons.io.FileUtils; +import org.junit.Assert; import org.junit.Before; import org.junit.Test; import com.mirth.connect.model.converters.TestUtil; -public class HL7SerializerTests { +public class HL7SerializerTest { private HL7v2DataTypeProperties defaultProperties; @Before public void setUp() throws Exception { defaultProperties = new HL7v2DataTypeProperties(); - -// defaultProperties = new Properties(); -// defaultProperties.put("useStrictParser", "false"); -// defaultProperties.put("handleRepetitions", "false"); -// defaultProperties.put("handleSubcomponents", "false"); -// defaultProperties.put("inputSegmentDelimiter", "\\r\\n|\\r|\\n"); -// defaultProperties.put("outputSegmentDelimiter", "\\r"); } @Test @@ -39,7 +31,7 @@ public void testToXmlDefault() throws Exception { String input = FileUtils.readFileToString(new File("tests/test-hl7-input.txt")); String output = FileUtils.readFileToString(new File("tests/test-hl7-output.xml")); ER7Serializer serializer = new ER7Serializer(defaultProperties.getSerializerProperties()); - Assert.assertEquals(output, TestUtil.prettyPrintXml(serializer.toXML(input))); + Assert.assertEquals(TestUtil.normalizeLineEndings(output), TestUtil.normalizeLineEndings(TestUtil.prettyPrintXml(serializer.toXML(input)))); } @Test @@ -55,7 +47,7 @@ public void testToXmlWhitepsace() throws Exception { String input = FileUtils.readFileToString(new File("tests/test-hl7-whitespace-input.txt")); String output = FileUtils.readFileToString(new File("tests/test-hl7-whitespace-output.xml")); ER7Serializer serializer = new ER7Serializer(defaultProperties.getSerializerProperties()); - Assert.assertEquals(output, TestUtil.prettyPrintXml(serializer.toXML(input))); + Assert.assertEquals(TestUtil.normalizeLineEndings(output), TestUtil.normalizeLineEndings(TestUtil.prettyPrintXml(serializer.toXML(input)))); } @Test @@ -98,11 +90,6 @@ public void testFromXmlMissingSubcomponents() throws Exception { @Test public void testFromXmlSingleSegment() throws Exception { HL7v2DataTypeProperties properties = new HL7v2DataTypeProperties(); -// properties.put("useStrictParser", "false"); -// properties.put("handleRepetitions", "false"); -// properties.put("handleSubcomponents", "true"); -// properties.put("inputSegmentDelimiter", "\\r\\n|\\r|\\n"); -// properties.put("outputSegmentDelimiter", "\\r"); String input = FileUtils.readFileToString(new File("tests/test-hl7-single-segment-input.xml")); String output = FileUtils.readFileToString(new File("tests/test-hl7-single-segment-output.txt")); @@ -121,28 +108,16 @@ public void testFromXmlSingleField() throws Exception { @Test public void testToXmlWithSubcomponents() throws Exception { HL7v2DataTypeProperties properties = new HL7v2DataTypeProperties(); -// Properties properties = new Properties(); -// properties.put("useStrictParser", "false"); -// properties.put("handleRepetitions", "false"); -// properties.put("handleSubcomponents", "true"); -// properties.put("inputSegmentDelimiter", "\\r\\n|\\r|\\n"); -// properties.put("outputSegmentDelimiter", "\\r"); String input = FileUtils.readFileToString(new File("tests/test-hl7-subcomponents-input.txt")); String output = FileUtils.readFileToString(new File("tests/test-hl7-subcomponents-output.xml")); ER7Serializer serializer = new ER7Serializer(properties.getSerializerProperties()); - Assert.assertEquals(output, TestUtil.prettyPrintXml(serializer.toXML(input))); + Assert.assertEquals(TestUtil.normalizeLineEndings(output), TestUtil.normalizeLineEndings(TestUtil.prettyPrintXml(serializer.toXML(input)))); } @Test public void testFromXmlWithSubcomponents() throws Exception { HL7v2DataTypeProperties properties = new HL7v2DataTypeProperties(); -// Properties properties = new Properties(); -// properties.put("useStrictParser", "false"); -// properties.put("handleRepetitions", "false"); -// properties.put("handleSubcomponents", "true"); -// properties.put("inputSegmentDelimiter", "\\r\\n|\\r|\\n"); -// properties.put("outputSegmentDelimiter", "\\r"); String input = FileUtils.readFileToString(new File("tests/test-hl7-subcomponents-output.xml")); String output = FileUtils.readFileToString(new File("tests/test-hl7-subcomponents-input.txt")); @@ -153,28 +128,16 @@ public void testFromXmlWithSubcomponents() throws Exception { @Test public void testToXmlWithRepetitions() throws Exception { HL7v2DataTypeProperties properties = new HL7v2DataTypeProperties(); -// Properties properties = new Properties(); -// properties.put("useStrictParser", "false"); -// properties.put("handleRepetitions", "true"); -// properties.put("handleSubcomponents", "false"); -// properties.put("inputSegmentDelimiter", "\\r\\n|\\r|\\n"); -// properties.put("outputSegmentDelimiter", "\\r"); String input = FileUtils.readFileToString(new File("tests/test-hl7-repetitions-input.txt")); String output = FileUtils.readFileToString(new File("tests/test-hl7-repetitions-output.xml")); ER7Serializer serializer = new ER7Serializer(properties.getSerializerProperties()); - Assert.assertEquals(output, TestUtil.prettyPrintXml(serializer.toXML(input))); + Assert.assertEquals(TestUtil.normalizeLineEndings(output), TestUtil.normalizeLineEndings(TestUtil.prettyPrintXml(serializer.toXML(input)))); } @Test public void testFromXmlWithRepetitions() throws Exception { HL7v2DataTypeProperties properties = new HL7v2DataTypeProperties(); -// Properties properties = new Properties(); -// properties.put("useStrictParser", "false"); -// properties.put("handleRepetitions", "true"); -// properties.put("handleSubcomponents", "false"); -// properties.put("inputSegmentDelimiter", "\\r\\n|\\r|\\n"); -// properties.put("outputSegmentDelimiter", "\\r"); String input = FileUtils.readFileToString(new File("tests/test-hl7-repetitions-output.xml")); String output = FileUtils.readFileToString(new File("tests/test-hl7-repetitions-input.txt")); @@ -187,7 +150,7 @@ public void testToXmlWithBatch() throws Exception { String input = FileUtils.readFileToString(new File("tests/test-hl7-batch-input.txt")); String output = FileUtils.readFileToString(new File("tests/test-hl7-batch-output.xml")); ER7Serializer serializer = new ER7Serializer(defaultProperties.getSerializerProperties()); - Assert.assertEquals(output, TestUtil.prettyPrintXml(serializer.toXML(input))); + Assert.assertEquals(TestUtil.normalizeLineEndings(output), TestUtil.normalizeLineEndings(TestUtil.prettyPrintXml(serializer.toXML(input)))); } @Test From 8ef628f5cdcf2d48f4b6a25c62edcbd0bd0723af Mon Sep 17 00:00:00 2001 From: Nico Piel Date: Thu, 30 Jul 2026 19:17:18 +0200 Subject: [PATCH 03/10] test: refresh HL7v2 fixtures for handleSubcomponents default These fixtures were generated when handleSubcomponents defaulted to false. It now defaults to true, so the unescaped '&' in OBR.4.3 splits into subcomponents. Splitting is the spec-correct reading; the fixtures were stale. Signed-off-by: Nico Piel --- server/tests/test-hl7-batch-output.xml | 5 ++++- server/tests/test-hl7-output.xml | 5 ++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/server/tests/test-hl7-batch-output.xml b/server/tests/test-hl7-batch-output.xml index f42adc856..bd1535a03 100644 --- a/server/tests/test-hl7-batch-output.xml +++ b/server/tests/test-hl7-batch-output.xml @@ -236,7 +236,10 @@ MRS Shephard - Jane MRI W/&W/O CONTRAST + + Jane MRI W/ + W/O CONTRAST + 70553 diff --git a/server/tests/test-hl7-output.xml b/server/tests/test-hl7-output.xml index 4628e91f7..f8e5fc4dd 100644 --- a/server/tests/test-hl7-output.xml +++ b/server/tests/test-hl7-output.xml @@ -218,7 +218,10 @@ MRS Shephard - Jane MRI W/&W/O CONTRAST + + Jane MRI W/ + W/O CONTRAST + 70553 From e9e7443d4a078bb37762d3fb759d5b359df4d375 Mon Sep 17 00:00:00 2001 From: Nico Piel Date: Thu, 30 Jul 2026 19:20:57 +0200 Subject: [PATCH 04/10] test: cover HL7v2 loose parser encoding-character handling Covers custom MSH-2 separators, a header-only message with no trailing field separator, the MIRTH-1544 fixup firing on a non-header first segment, and the too-short-message guard. Signed-off-by: Nico Piel --- .../datatypes/hl7v2/ER7SerializerTest.java | 52 ++++++++++++++++++- 1 file changed, 51 insertions(+), 1 deletion(-) diff --git a/server/src/test/java/com/mirth/connect/plugins/datatypes/hl7v2/ER7SerializerTest.java b/server/src/test/java/com/mirth/connect/plugins/datatypes/hl7v2/ER7SerializerTest.java index a7319dca5..1fda09be1 100644 --- a/server/src/test/java/com/mirth/connect/plugins/datatypes/hl7v2/ER7SerializerTest.java +++ b/server/src/test/java/com/mirth/connect/plugins/datatypes/hl7v2/ER7SerializerTest.java @@ -1,21 +1,26 @@ package com.mirth.connect.plugins.datatypes.hl7v2; +import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; import java.io.File; import org.apache.commons.io.FileUtils; import org.junit.BeforeClass; import org.junit.Test; +import org.xml.sax.SAXException; import org.xml.sax.SAXParseException; import com.mirth.connect.donkey.model.message.MessageSerializerException; import com.mirth.connect.model.datatype.SerializerProperties; public class ER7SerializerTest { + private static final String XML_DECL = ""; + private static ER7Serializer serializer; - + @BeforeClass public static void setupClass() throws Exception { SerializerProperties serializerProperties = new SerializerProperties(new HL7v2SerializationProperties(), new HL7v2DeserializationProperties(), null); @@ -53,4 +58,49 @@ public void testValidFromXMLWithExternalDTD() throws Exception { assertFalse(exceptionThrown); } + + @Test + public void testToXMLWithCustomEncodingCharacters() throws Exception { + String er7 = "MSH#@%\\$#App1#Fac1\rPID#1#Smith@John"; + + assertEquals(XML_DECL + "#@%\\$" + + "App1" + + "Fac1" + + "1" + + "SmithJohn", + serializer.toXML(er7)); + } + + @Test + public void testToXMLWithHeaderOnlyAndNoTrailingFieldSeparator() throws Exception { + // Covers ER7Reader's nextDelimiter == -1 branch: MSH-2 runs to end of message. + assertEquals(XML_DECL + "|^~\\&", + serializer.toXML("MSH|^~\\&")); + } + + @Test + public void testToXMLAppliesMirth1544FixupToNonHeaderFirstSegment() throws Exception { + /* + * Characterization of ER7Reader's MIRTH-1544 fixup. The "^~&|" check is a positional + * substring test that does not require a header segment, so it also fires on a Z-segment, + * installing '&' as the subcomponent separator. Recorded as current behavior, not endorsed. + */ + assertEquals(XML_DECL + "" + + "" + + "" + + "ab" + + "", + serializer.toXML("ZZZ|^~&|a&b")); + } + + @Test + public void testToXMLRejectsMessageShorterThanSixCharacters() throws Exception { + try { + serializer.toXML("MSH"); + fail("expected MessageSerializerException"); + } catch (MessageSerializerException e) { + assertTrue(e.getCause() instanceof SAXException); + assertEquals("Unable to parse message. It is NULL or too short. MSH", e.getCause().getMessage()); + } + } } From efcc525bb21687c0742befc5a3cc74cb2b239089 Mon Sep 17 00:00:00 2001 From: Nico Piel Date: Thu, 30 Jul 2026 19:24:23 +0200 Subject: [PATCH 05/10] test: cover HL7v2 loose parser degenerate separators Consecutive and trailing repetition separators, trailing empty fields, and empty segments. Signed-off-by: Nico Piel --- .../datatypes/hl7v2/ER7SerializerTest.java | 39 +++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/server/src/test/java/com/mirth/connect/plugins/datatypes/hl7v2/ER7SerializerTest.java b/server/src/test/java/com/mirth/connect/plugins/datatypes/hl7v2/ER7SerializerTest.java index 1fda09be1..6cbcfb76d 100644 --- a/server/src/test/java/com/mirth/connect/plugins/datatypes/hl7v2/ER7SerializerTest.java +++ b/server/src/test/java/com/mirth/connect/plugins/datatypes/hl7v2/ER7SerializerTest.java @@ -18,6 +18,8 @@ public class ER7SerializerTest { private static final String XML_DECL = ""; + private static final String MSH_ER7 = "MSH|^~\\&|A\r"; + private static final String MSH_XML = "|^~\\&A"; private static ER7Serializer serializer; @@ -103,4 +105,41 @@ public void testToXMLRejectsMessageShorterThanSixCharacters() throws Exception { assertEquals("Unable to parse message. It is NULL or too short. MSH", e.getCause().getMessage()); } } + + @Test + public void testToXMLWithConsecutiveRepetitionSeparators() throws Exception { + assertEquals(XML_DECL + "" + MSH_XML + "" + + "a" + + "" + + "b" + + "", + serializer.toXML(MSH_ER7 + "PID|a~~b")); + } + + @Test + public void testToXMLWithTrailingRepetitionSeparator() throws Exception { + assertEquals(XML_DECL + "" + MSH_XML + "" + + "a" + + "" + + "", + serializer.toXML(MSH_ER7 + "PID|a~")); + } + + @Test + public void testToXMLWithTrailingEmptyFields() throws Exception { + assertEquals(XML_DECL + "" + MSH_XML + "" + + "a" + + "" + + "" + + "", + serializer.toXML(MSH_ER7 + "PID|a||")); + } + + @Test + public void testToXMLSkipsEmptySegments() throws Exception { + // StringUtils.split drops empty tokens, so a blank line between segments simply vanishes. + assertEquals(XML_DECL + "" + MSH_XML + + "1", + serializer.toXML("MSH|^~\\&|A\r\rPID|1")); + } } From 13a064180eac3ddda9e03ce45d4f81f26ec6b1c8 Mon Sep 17 00:00:00 2001 From: Nico Piel Date: Thu, 30 Jul 2026 19:28:00 +0200 Subject: [PATCH 06/10] test: cover ER7Serializer.transformWithoutSerializing Delimiter conversion, mixed line-break normalization, the pass-through case when delimiters already match, and the null "nothing to do" result. Signed-off-by: Nico Piel --- .../datatypes/hl7v2/ER7SerializerTest.java | 45 +++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/server/src/test/java/com/mirth/connect/plugins/datatypes/hl7v2/ER7SerializerTest.java b/server/src/test/java/com/mirth/connect/plugins/datatypes/hl7v2/ER7SerializerTest.java index 6cbcfb76d..c18b2ef24 100644 --- a/server/src/test/java/com/mirth/connect/plugins/datatypes/hl7v2/ER7SerializerTest.java +++ b/server/src/test/java/com/mirth/connect/plugins/datatypes/hl7v2/ER7SerializerTest.java @@ -2,6 +2,7 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; @@ -29,6 +30,50 @@ public static void setupClass() throws Exception { serializer = new ER7Serializer(serializerProperties); } + private static ER7Serializer serializerWith(boolean convertLineBreaks, String deserializationSegmentDelimiter) { + HL7v2SerializationProperties serializationProperties = new HL7v2SerializationProperties(); + serializationProperties.setConvertLineBreaks(convertLineBreaks); + + HL7v2DeserializationProperties deserializationProperties = new HL7v2DeserializationProperties(); + deserializationProperties.setSegmentDelimiter(deserializationSegmentDelimiter); + + return new ER7Serializer(new SerializerProperties(serializationProperties, deserializationProperties, null)); + } + + @Test + public void testTransformWithoutSerializingConvertsToOutboundDelimiter() throws Exception { + ER7Serializer inbound = serializerWith(true, "\\r"); + ER7Serializer outbound = serializerWith(true, "\\n"); + + assertEquals("MSH|^~\\&|A\nPID|1", inbound.transformWithoutSerializing("MSH|^~\\&|A\rPID|1", outbound)); + } + + @Test + public void testTransformWithoutSerializingNormalizesMixedLineBreaks() throws Exception { + ER7Serializer serializer = serializerWith(true, "\\r"); + + assertEquals("MSH|^~\\&|A\rPID|1", serializer.transformWithoutSerializing("MSH|^~\\&|A\r\nPID|1", serializer)); + } + + @Test + public void testTransformWithoutSerializingStillConvertsWhenDelimitersMatch() throws Exception { + /* + * convertLineBreaks is on, so the message goes through conversion and is returned even + * though it is unchanged. Only the convertLineBreaks-off case short-circuits to null. + */ + ER7Serializer serializer = serializerWith(true, "\\r"); + + assertEquals("MSH|^~\\&|A\rPID|1", serializer.transformWithoutSerializing("MSH|^~\\&|A\rPID|1", serializer)); + } + + @Test + public void testTransformWithoutSerializingReturnsNullWhenNothingToDo() throws Exception { + ER7Serializer inbound = serializerWith(false, "\\r"); + ER7Serializer outbound = serializerWith(true, "\\r"); + + assertNull(inbound.transformWithoutSerializing("MSH|^~\\&|A\rPID|1", outbound)); + } + @Test public void testFromXMLWithExternalDTD() throws Exception { String xml = FileUtils.readFileToString(new File("tests/test-xxe-hl7-example.xml"), "UTF-8"); From be3e5a24cd5b60d4e3072b10b1f84d6831e62a6a Mon Sep 17 00:00:00 2001 From: Nico Piel Date: Thu, 30 Jul 2026 19:34:16 +0200 Subject: [PATCH 07/10] test: cover ER7Serializer's delimiter-replace branch The four existing transformWithoutSerializing tests all set convertLineBreaks true (or leave the default serialization delimiter equal to the deserialization one), so every one of them short-circuits before reaching the StringUtils.replace branch. Add an overload of serializerWith that also controls the serialization delimiter, and a test with convertLineBreaks off and differing delimiters to actually exercise that branch. Signed-off-by: Nico Piel --- .../datatypes/hl7v2/ER7SerializerTest.java | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/server/src/test/java/com/mirth/connect/plugins/datatypes/hl7v2/ER7SerializerTest.java b/server/src/test/java/com/mirth/connect/plugins/datatypes/hl7v2/ER7SerializerTest.java index c18b2ef24..25160d4f9 100644 --- a/server/src/test/java/com/mirth/connect/plugins/datatypes/hl7v2/ER7SerializerTest.java +++ b/server/src/test/java/com/mirth/connect/plugins/datatypes/hl7v2/ER7SerializerTest.java @@ -31,8 +31,13 @@ public static void setupClass() throws Exception { } private static ER7Serializer serializerWith(boolean convertLineBreaks, String deserializationSegmentDelimiter) { + return serializerWith(convertLineBreaks, "\\r", deserializationSegmentDelimiter); + } + + private static ER7Serializer serializerWith(boolean convertLineBreaks, String serializationSegmentDelimiter, String deserializationSegmentDelimiter) { HL7v2SerializationProperties serializationProperties = new HL7v2SerializationProperties(); serializationProperties.setConvertLineBreaks(convertLineBreaks); + serializationProperties.setSegmentDelimiter(serializationSegmentDelimiter); HL7v2DeserializationProperties deserializationProperties = new HL7v2DeserializationProperties(); deserializationProperties.setSegmentDelimiter(deserializationSegmentDelimiter); @@ -66,6 +71,22 @@ public void testTransformWithoutSerializingStillConvertsWhenDelimitersMatch() th assertEquals("MSH|^~\\&|A\rPID|1", serializer.transformWithoutSerializing("MSH|^~\\&|A\rPID|1", serializer)); } + @Test + public void testTransformWithoutSerializingReplacesDelimiterWhenLineBreakConversionIsOff() throws Exception { + /* + * The only test that reaches the StringUtils.replace branch at ER7Serializer.java:170. + * Every convertLineBreaks=true configuration short-circuits earlier: either the + * skipIntermediateDelimiter fast path at line 162, or (for the delimiters-match case) + * the convertLineBreaks(...) call at line 165 with transformed already true. Only + * convertLineBreaks=false skips that whole block and falls through to the delimiter + * comparison at line 169. + */ + ER7Serializer inbound = serializerWith(false, "\\r", "\\r"); + ER7Serializer outbound = serializerWith(true, "\\n"); + + assertEquals("MSH|^~\\&|A\nPID|1", inbound.transformWithoutSerializing("MSH|^~\\&|A\rPID|1", outbound)); + } + @Test public void testTransformWithoutSerializingReturnsNullWhenNothingToDo() throws Exception { ER7Serializer inbound = serializerWith(false, "\\r"); From 70a3bbe4fa795500054c1182ce38e98c986204a4 Mon Sep 17 00:00:00 2001 From: Nico Piel Date: Thu, 30 Jul 2026 19:39:11 +0200 Subject: [PATCH 08/10] test: assert HL7v2 loose parser ER7 round-trip invariant fromXML(toXML(er7)) must reproduce the input for every ER7 fixture. Signed-off-by: Nico Piel --- .../plugins/datatypes/hl7v2/HL7SerializerTest.java | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/server/src/test/java/com/mirth/connect/plugins/datatypes/hl7v2/HL7SerializerTest.java b/server/src/test/java/com/mirth/connect/plugins/datatypes/hl7v2/HL7SerializerTest.java index c2ebc7749..2cae3f24a 100644 --- a/server/src/test/java/com/mirth/connect/plugins/datatypes/hl7v2/HL7SerializerTest.java +++ b/server/src/test/java/com/mirth/connect/plugins/datatypes/hl7v2/HL7SerializerTest.java @@ -160,4 +160,18 @@ public void testFromXmlWithBatch() throws Exception { ER7Serializer serializer = new ER7Serializer(defaultProperties.getSerializerProperties()); Assert.assertEquals(output, TestUtil.convertCRToCRLF(serializer.fromXML(input))); } + + @Test + public void testRoundTripAllEr7Fixtures() throws Exception { + String[] fixtures = { "tests/test-hl7-input.txt", "tests/test-hl7-whitespace-input.txt", + "tests/test-hl7-subcomponents-input.txt", "tests/test-hl7-repetitions-input.txt", + "tests/test-hl7-batch-input.txt" }; + + for (String fixture : fixtures) { + String er7 = FileUtils.readFileToString(new File(fixture)); + ER7Serializer serializer = new ER7Serializer(defaultProperties.getSerializerProperties()); + + Assert.assertEquals(fixture, TestUtil.normalizeLineEndings(er7), TestUtil.normalizeLineEndings(serializer.fromXML(serializer.toXML(er7)))); + } + } } From da8c39bd2fd063e6a1f09f981bec30e650f9f31f Mon Sep 17 00:00:00 2001 From: Nico Piel Date: Thu, 30 Jul 2026 19:50:34 +0200 Subject: [PATCH 09/10] Clean up ER7SerializerTest and HL7SerializerTest per review Remove a dead 3-argument serializerWith overload that duplicated the 2-argument form's behavior (the extra parameter always received the already-default segment delimiter), rename shadowed local `serializer` variables to `sameEnds` in the transformWithoutSerializing tests, and hoist the configuration-invariant ER7Serializer construction out of the fixture loop in testRoundTripAllEr7Fixtures. Signed-off-by: Nico Piel --- .../datatypes/hl7v2/ER7SerializerTest.java | 15 +++++---------- .../datatypes/hl7v2/HL7SerializerTest.java | 3 ++- 2 files changed, 7 insertions(+), 11 deletions(-) diff --git a/server/src/test/java/com/mirth/connect/plugins/datatypes/hl7v2/ER7SerializerTest.java b/server/src/test/java/com/mirth/connect/plugins/datatypes/hl7v2/ER7SerializerTest.java index 25160d4f9..45072bdc8 100644 --- a/server/src/test/java/com/mirth/connect/plugins/datatypes/hl7v2/ER7SerializerTest.java +++ b/server/src/test/java/com/mirth/connect/plugins/datatypes/hl7v2/ER7SerializerTest.java @@ -31,13 +31,8 @@ public static void setupClass() throws Exception { } private static ER7Serializer serializerWith(boolean convertLineBreaks, String deserializationSegmentDelimiter) { - return serializerWith(convertLineBreaks, "\\r", deserializationSegmentDelimiter); - } - - private static ER7Serializer serializerWith(boolean convertLineBreaks, String serializationSegmentDelimiter, String deserializationSegmentDelimiter) { HL7v2SerializationProperties serializationProperties = new HL7v2SerializationProperties(); serializationProperties.setConvertLineBreaks(convertLineBreaks); - serializationProperties.setSegmentDelimiter(serializationSegmentDelimiter); HL7v2DeserializationProperties deserializationProperties = new HL7v2DeserializationProperties(); deserializationProperties.setSegmentDelimiter(deserializationSegmentDelimiter); @@ -55,9 +50,9 @@ public void testTransformWithoutSerializingConvertsToOutboundDelimiter() throws @Test public void testTransformWithoutSerializingNormalizesMixedLineBreaks() throws Exception { - ER7Serializer serializer = serializerWith(true, "\\r"); + ER7Serializer sameEnds = serializerWith(true, "\\r"); - assertEquals("MSH|^~\\&|A\rPID|1", serializer.transformWithoutSerializing("MSH|^~\\&|A\r\nPID|1", serializer)); + assertEquals("MSH|^~\\&|A\rPID|1", sameEnds.transformWithoutSerializing("MSH|^~\\&|A\r\nPID|1", sameEnds)); } @Test @@ -66,9 +61,9 @@ public void testTransformWithoutSerializingStillConvertsWhenDelimitersMatch() th * convertLineBreaks is on, so the message goes through conversion and is returned even * though it is unchanged. Only the convertLineBreaks-off case short-circuits to null. */ - ER7Serializer serializer = serializerWith(true, "\\r"); + ER7Serializer sameEnds = serializerWith(true, "\\r"); - assertEquals("MSH|^~\\&|A\rPID|1", serializer.transformWithoutSerializing("MSH|^~\\&|A\rPID|1", serializer)); + assertEquals("MSH|^~\\&|A\rPID|1", sameEnds.transformWithoutSerializing("MSH|^~\\&|A\rPID|1", sameEnds)); } @Test @@ -81,7 +76,7 @@ public void testTransformWithoutSerializingReplacesDelimiterWhenLineBreakConvers * convertLineBreaks=false skips that whole block and falls through to the delimiter * comparison at line 169. */ - ER7Serializer inbound = serializerWith(false, "\\r", "\\r"); + ER7Serializer inbound = serializerWith(false, "\\r"); ER7Serializer outbound = serializerWith(true, "\\n"); assertEquals("MSH|^~\\&|A\nPID|1", inbound.transformWithoutSerializing("MSH|^~\\&|A\rPID|1", outbound)); diff --git a/server/src/test/java/com/mirth/connect/plugins/datatypes/hl7v2/HL7SerializerTest.java b/server/src/test/java/com/mirth/connect/plugins/datatypes/hl7v2/HL7SerializerTest.java index 2cae3f24a..2d3340472 100644 --- a/server/src/test/java/com/mirth/connect/plugins/datatypes/hl7v2/HL7SerializerTest.java +++ b/server/src/test/java/com/mirth/connect/plugins/datatypes/hl7v2/HL7SerializerTest.java @@ -167,9 +167,10 @@ public void testRoundTripAllEr7Fixtures() throws Exception { "tests/test-hl7-subcomponents-input.txt", "tests/test-hl7-repetitions-input.txt", "tests/test-hl7-batch-input.txt" }; + ER7Serializer serializer = new ER7Serializer(defaultProperties.getSerializerProperties()); + for (String fixture : fixtures) { String er7 = FileUtils.readFileToString(new File(fixture)); - ER7Serializer serializer = new ER7Serializer(defaultProperties.getSerializerProperties()); Assert.assertEquals(fixture, TestUtil.normalizeLineEndings(er7), TestUtil.normalizeLineEndings(serializer.fromXML(serializer.toXML(er7)))); } From e353553ac800d8acd6cc88dbde7690827f323129 Mon Sep 17 00:00:00 2001 From: Nico Piel Date: Thu, 30 Jul 2026 20:11:24 +0200 Subject: [PATCH 10/10] Remove SonarQube plugin from build.gradle Signed-off-by: Nico Piel --- build.gradle | 1 - 1 file changed, 1 deletion(-) diff --git a/build.gradle b/build.gradle index 7a93eb367..d9de29d36 100644 --- a/build.gradle +++ b/build.gradle @@ -45,7 +45,6 @@ plugins { // vulnerability scanning: ./gradlew dependencyCheckAggregate // (replaces the old standalone dependency-check.xml Ant entry point) id 'org.owasp.dependencycheck' version '12.2.2' - id "org.sonarqube" version "7.3.1.8318" } dependencyCheck {