From d29e3eb3dc6ce8cb974555ac2df352395447df0d Mon Sep 17 00:00:00 2001 From: "David M. Lloyd" Date: Thu, 16 May 2024 17:51:34 +0200 Subject: [PATCH] Fix NPE when deserializing `TestIdentifier` (#3820) An NPE was thrown when (de)serializing `TestIdentifiers` without a parent. Fixes #3819. Co-authored-by: Marc Philipp (cherry picked from commit bc55d0e13508fb5f2e8575ea9c236e3e93f5a603) --- .../release-notes/release-notes-5.10.3.adoc | 3 +++ .../junit/platform/launcher/TestIdentifier.java | 6 ++++-- .../platform/launcher/TestIdentifierTests.java | 15 +++++++++++++++ 3 files changed, 22 insertions(+), 2 deletions(-) diff --git a/documentation/src/docs/asciidoc/release-notes/release-notes-5.10.3.adoc b/documentation/src/docs/asciidoc/release-notes/release-notes-5.10.3.adoc index 315cba1adda3..10d5e3ec3617 100644 --- a/documentation/src/docs/asciidoc/release-notes/release-notes-5.10.3.adoc +++ b/documentation/src/docs/asciidoc/release-notes/release-notes-5.10.3.adoc @@ -19,6 +19,9 @@ on GitHub. `@ConfigurationParameter` when selecting tests by `UniqueId`. * In order to support using `@EnabledInNativeImage` on test classes, `UniqueIdTrackingListener` now tracks descendants of skipped test containers. +* Attempting to deserialize a `TestIdentifier` no longer causes a `NullPointerException` + when there is no parent identifier. See + link:https://github.com/junit-team/junit5/issues/3819[issue 3819]. ==== Deprecations and Breaking Changes diff --git a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/TestIdentifier.java b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/TestIdentifier.java index 20eaf35624d1..747b245b65e5 100644 --- a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/TestIdentifier.java +++ b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/TestIdentifier.java @@ -284,7 +284,8 @@ private void readObject(ObjectInputStream s) throws ClassNotFoundException, IOEx source = serializedForm.source; tags = serializedForm.tags; type = serializedForm.type; - parentId = UniqueId.parse(serializedForm.parentId); + String parentId = serializedForm.parentId; + this.parentId = parentId == null ? null : UniqueId.parse(parentId); legacyReportingName = serializedForm.legacyReportingName; } @@ -307,7 +308,8 @@ private static class SerializedForm implements Serializable { SerializedForm(TestIdentifier testIdentifier) { this.uniqueId = testIdentifier.uniqueId.toString(); - this.parentId = testIdentifier.parentId.toString(); + UniqueId parentId = testIdentifier.parentId; + this.parentId = parentId == null ? null : parentId.toString(); this.displayName = testIdentifier.displayName; this.legacyReportingName = testIdentifier.legacyReportingName; this.source = testIdentifier.source; diff --git a/platform-tests/src/test/java/org/junit/platform/launcher/TestIdentifierTests.java b/platform-tests/src/test/java/org/junit/platform/launcher/TestIdentifierTests.java index 8d007f4528ed..0b6236bbde53 100644 --- a/platform-tests/src/test/java/org/junit/platform/launcher/TestIdentifierTests.java +++ b/platform-tests/src/test/java/org/junit/platform/launcher/TestIdentifierTests.java @@ -72,6 +72,21 @@ void initialVersionCanBeDeserialized() throws Exception { } } + @Test + void identifierWithNoParentCanBeSerializedAndDeserialized() throws Exception { + TestIdentifier originalIdentifier = TestIdentifier.from( + new AbstractTestDescriptor(UniqueId.root("example", "id"), "Example") { + @Override + public Type getType() { + return Type.CONTAINER; + } + }); + + var deserializedIdentifier = (TestIdentifier) deserialize(serialize(originalIdentifier)); + + assertDeepEquals(originalIdentifier, deserializedIdentifier); + } + private static void assertDeepEquals(TestIdentifier first, TestIdentifier second) { assertEquals(first, second); assertEquals(first.getUniqueId(), second.getUniqueId());