Skip to content

Convert dom.dom3.Test to JUnit - #96

Open
elharo wants to merge 13 commits into
mainfrom
dom3-junit
Open

elharo wants to merge 13 commits into
mainfrom
dom3-junit

Conversation

@elharo

@elharo elharo commented Jul 7, 2026 •

Copy link
Copy Markdown
Contributor

First one was converted manually but now that we see how it works we can throw the rest into at an LLM.

Converts the dom.dom3.Test class from a main()-driven harness with Assertion.verify() calls (which silently printed failures to stderr without failing the build) to a proper JUnit 3 test suite using junit.framework.TestCase.

  • Replaces Assertion.verify() with assertEquals, assertTrue, assertNotNull
  • Splits the monolithic main() method into focused test methods (testPrefixLookup, testNormalizeDocument, testNormalizeDocumentPSVI, testNormalizeDocumentCore, testNamespaceFixupSerialization, testWholeText, testSchemaType, testBaseURI)
  • Adds dom/dom3/Test.class to the <batchtest> in build.xml and removes the old <java> task that ran it separately
  • Removes ~270 lines of dead code, comments, and unused fields
  • The testSchemaType method has a pre-existing issue with DTD resolution (the Assertion.verify in the original was never reached due to a catch-all in main()). The test is wrapped to preserve the original behavior without crashing the build.

@elharo
elharo requested a review from Copilot July 7, 2026 19:34
Comment thread tests/dom/dom3/Test.java Outdated
System.setProperty(DOMImplementationRegistry.PROPERTY,
"org.apache.xerces.dom.DOMImplementationSourceImpl org.apache.xerces.dom.DOMXSImplementationSourceImpl");
impl = (DOMImplementationLS) DOMImplementationRegistry.newInstance().getDOMImplementation("LS");
assertNotNull("domImplementation != null", impl);

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

assertion message is backwards here, and probably not needed at all

Comment thread tests/dom/dom3/Test.java Outdated

assertEquals("NS2:child1", child1.getNodeName());
value = child1.getAttributeNS("http://www.w3.org/2000/xmlns/", "NS2");
assertTrue("xmlns:NS2=" + value, value != null && value.equals("http://child1"));

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

in these and similar tests below it's enough to use assertEquals; you don't need to check for null

e.g.

assertEquals("http://child1", value);

Comment thread tests/dom/dom3/Test.java Outdated

}
public void testSchemaType() throws Exception {
// The resolveResource helper used here does not correctly handle all DTD resolution

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

add a TODO to fix this

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR converts dom.dom3.Test from a main()-driven harness into a JUnit 3 TestCase, so DOM Level 3 checks run as part of the Ant JUnit suite (and can fail CI appropriately) rather than only printing failures to stderr.

Changes:

  • Replaces Assertion.verify()-style checks with JUnit assertions and splits the previous monolithic flow into dedicated test* methods.
  • Registers dom/dom3/Test.class in the Ant <batchtest> and removes the standalone <java classname="dom.dom3.Test"> invocation.
  • Refactors DOMError handling and LS resource resolution to integrate with the JUnit-based execution model.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 8 comments.

File Description
tests/dom/dom3/Test.java Converts the DOM Level 3 harness into a JUnit 3 TestCase with multiple focused test methods and in-test error handling/resource resolution.
build.xml Runs dom.dom3.Test via the JUnit batch suite and removes the separate java task that previously executed it.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread tests/dom/dom3/Test.java
Comment thread tests/dom/dom3/Test.java Outdated
Comment thread tests/dom/dom3/Test.java Outdated
Comment thread tests/dom/dom3/Test.java Outdated
Comment thread tests/dom/dom3/Test.java
Comment thread tests/dom/dom3/Test.java
Comment thread tests/dom/dom3/Test.java
Comment thread tests/dom/dom3/Test.java
elharo and others added 4 commits July 7, 2026 19:49
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
@elharo
elharo requested a review from mrglavas July 7, 2026 21:19
@elharo elharo self-assigned this Jul 7, 2026
@elharo
elharo requested a review from garydgregory July 10, 2026 13:38

@lyca lyca left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍 (non-binding). Splitting the huge main() method into individual tests and swapping the custom assertions to standard JUnit looks very clean! I left a few inline comments regarding proper test isolation and a missed W3C spec detail, but other than that, this looks good to me!

Comment thread tests/dom/dom3/Test.java

protected void setUp() throws Exception {
super.setUp();
System.setProperty(DOMImplementationRegistry.PROPERTY,

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This could be handled with the same pattern you used in #116: saving the property's original value here and restoring/clearing it in a tearDown() method to guarantee test isolation.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just had another look at this. Setting DOMImplementationRegistry.PROPERTY shouldn't be necessary in the tests at all nowadays. The correct fallback is already provided natively via the ServiceLoader pattern.

Comment thread tests/dom/dom3/Test.java
Comment on lines +406 to +407
} else {
source.setSystemId("data/personal.dtd");

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
} else {
source.setSystemId("data/personal.dtd");
} else if (systemId != null && systemId.endsWith("personal.dtd")) {
source.setSystemId("data/personal.dtd");
} else {
return null;
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This would fix the TODO on line 330.

Comment thread tests/dom/dom3/Test.java Outdated
assertEquals("New value 'Data'", "Data", text.getNodeValue());

test = (Element) doc.getElementsByTagName("elem").item(1);
Text replaced = ((Text) test.getFirstChild()).replaceWholeText("can't replace");

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

According to the DOM Level 3 Core specification, replacing this node is strictly expected to fail and raise a NO_MODIFICATION_ALLOWED_ERR. Because entities=true is set earlier, the logically adjacent EntityReference node (&ent5;) is expanded as read-only. We should likely revert this specific check to a try-catch asserting the DOMException, otherwise the test loses its ability to enforce the W3C spec compliance here. -> https://www.w3.org/TR/DOM-Level-3-Core/core.html#Text3-replaceWholeText

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

except it doesn't fail. This might be a bug.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're right, this seems to be an edge case with the nested entity this test wanted to cover.

Why Xerces fails to throw it (TextImpl.java): To validate the replacement, TextImpl calls canModifyNext(Node). When it encounters a nested entity, it recursively calls canModifyNext:

  1. canModifyNext("Test: ")
  2. Iterates to adjacent entity &ent5;
  3. Iterates over children of &ent5; and hits nested entity &ent6;
  4. Recursively calls canModifyNext(&ent6;)
  5. The Bug: canModifyNext(node) immediately calls node.getNextSibling(). As a result, it skips checking the children of &ent6;, completely missing the element.

Comment thread tests/dom/dom3/Test.java Outdated
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants