This is an automated email from the ASF dual-hosted git repository.

jamesbognar pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/juneau.git


The following commit(s) were added to refs/heads/master by this push:
     new 3b3009d2d9 Add coverage tests for MarshalledNode, JsonPointer, and 
PathTraversal.
3b3009d2d9 is described below

commit 3b3009d2d9beadc340398e1ecbb5ba01a36bb142
Author: James Bognar <[email protected]>
AuthorDate: Tue Jun 16 10:56:55 2026 -0400

    Add coverage tests for MarshalledNode, JsonPointer, and PathTraversal.
    
    Fill line/branch coverage gaps on the TODO-175b classes (typed-tree façade,
    RFC 6901 JSON-Pointer, relocated traversal engine, PathTraversalException).
    
    Co-authored-by: Cursor <[email protected]>
---
 .../marshall/collections/JsonPointer_Test.java     | 81 ++++++++++++++++++++++
 .../marshall/collections/MarshalledNode_Test.java  |  9 +++
 .../marshall/objecttools/PathTraversal_Test.java   | 69 ++++++++++++++++++
 3 files changed, 159 insertions(+)

diff --git 
a/juneau-core/juneau-marshall/src/test/java/org/apache/juneau/marshall/collections/JsonPointer_Test.java
 
b/juneau-core/juneau-marshall/src/test/java/org/apache/juneau/marshall/collections/JsonPointer_Test.java
index c6bb2bfe3a..0deccfcce9 100644
--- 
a/juneau-core/juneau-marshall/src/test/java/org/apache/juneau/marshall/collections/JsonPointer_Test.java
+++ 
b/juneau-core/juneau-marshall/src/test/java/org/apache/juneau/marshall/collections/JsonPointer_Test.java
@@ -204,6 +204,39 @@ class JsonPointer_Test extends TestBase {
                assertEquals("v", JsonPointer.of("").set(JsonMap.of("a", 1), 
"v"));
        }
 
+       @Test void e06_setIndexOutOfRangeThrows() {
+               // Setting at an index beyond the end of an existing list (not 
the append slot) is an error.
+               var root = JsonMap.of("a", JsonList.of(1, 2));
+               assertThrows(IllegalArgumentException.class, () -> 
JsonPointer.of("/a/5").set(root, 9));
+       }
+
+       @Test void e07_setReplaceAtExistingIndex() {
+               var root = JsonMap.of("a", JsonList.of(1, 2, 3));
+               JsonPointer.of("/a/1").set(root, 9);
+               assertEquals("{\"a\":[1,9,3]}", Json.of(root));
+       }
+
+       @Test void e08_vivifyListViaDashToken() {
+               // A '-' next token makes the auto-vivified intermediate 
container a list, and appends to it.
+               var root = new JsonMap();
+               JsonPointer.of("/a/-").set(root, "x");
+               assertEquals("{\"a\":[\"x\"]}", Json.of(root));
+               assertInstanceOf(JsonList.class, root.get("a"));
+       }
+
+       @Test void e09_descendThroughExistingObject() {
+               // navigateToParent descends through an already-present 
intermediate map without re-vivifying it.
+               var root = JsonMap.of("a", new JsonMap());
+               JsonPointer.of("/a/b").set(root, 1);
+               assertEquals("{\"a\":{\"b\":1}}", Json.of(root));
+       }
+
+       @Test void e10_setNonNumericListTokenThrows() {
+               // A non-numeric, non-'-' token on a list is an invalid array 
index on write.
+               var root = JsonMap.of("a", JsonList.of(1, 2));
+               assertThrows(IllegalArgumentException.class, () -> 
JsonPointer.of("/a/foo").set(root, 9));
+       }
+
        // 
-----------------------------------------------------------------------------------------------------------------
        // f - Remove
        // 
-----------------------------------------------------------------------------------------------------------------
@@ -224,4 +257,52 @@ class JsonPointer_Test extends TestBase {
                assertNull(JsonPointer.of("/missing").remove(JsonMap.of("a", 
1)));
                assertNull(JsonPointer.of("/a/5").remove(JsonMap.of("a", 
JsonList.of("x"))));
        }
+
+       @Test void f04_removeRootReturnsNull() {
+               // The root pointer addresses the whole document, which cannot 
be removed in place.
+               assertNull(JsonPointer.of("").remove(JsonMap.of("a", 1)));
+       }
+
+       @Test void f05_removeMissingIntermediateReturnsNull() {
+               assertNull(JsonPointer.of("/a/b/c").remove(new JsonMap()));
+       }
+
+       @Test void f06_removeNonNumericListTokenReturnsNull() {
+               var root = JsonMap.of("a", JsonList.of("x", "y"));
+               assertNull(JsonPointer.of("/a/-").remove(root));
+               assertNull(JsonPointer.of("/a/foo").remove(root));
+               // The list is left unchanged.
+               assertEquals("{\"a\":[\"x\",\"y\"]}", Json.of(root));
+       }
+
+       @Test void f07_removeThroughScalarReturnsNull() {
+               assertNull(JsonPointer.of("/a/b").remove(JsonMap.of("a", 
"scalar")));
+       }
+
+       // 
-----------------------------------------------------------------------------------------------------------------
+       // g - Array index token parsing
+       // 
-----------------------------------------------------------------------------------------------------------------
+
+       @Test void g01_emptyTokenOnArrayMisses() {
+               // An empty reference token is not a valid array index, so it 
resolves to a miss.
+               assertNull(JsonPointer.of("/").eval(JsonList.of("x")));
+       }
+
+       @Test void g02_leadingZeroIndexRejected() {
+               // RFC 6901 forbids leading zeros in array indices, so they 
resolve to a miss.
+               assertNull(JsonPointer.of("/01").eval(JsonList.of("a", "b")));
+               assertNull(JsonPointer.of("/00").eval(JsonList.of("a", "b")));
+       }
+
+       @Test void g03_multiDigitIndex() {
+               var l = new JsonList();
+               for (var i = 0; i < 12; i++)
+                       l.add(i);
+               assertEquals(10, JsonPointer.of("/10").eval(l));
+       }
+
+       @Test void g04_overflowingIndexMisses() {
+               // An all-digit token too large to fit in an int is treated as 
a non-index (miss), not an error.
+               
assertNull(JsonPointer.of("/99999999999999999999").eval(JsonList.of("x")));
+       }
 }
diff --git 
a/juneau-core/juneau-marshall/src/test/java/org/apache/juneau/marshall/collections/MarshalledNode_Test.java
 
b/juneau-core/juneau-marshall/src/test/java/org/apache/juneau/marshall/collections/MarshalledNode_Test.java
index 7b82ab49ca..d924bbf7af 100644
--- 
a/juneau-core/juneau-marshall/src/test/java/org/apache/juneau/marshall/collections/MarshalledNode_Test.java
+++ 
b/juneau-core/juneau-marshall/src/test/java/org/apache/juneau/marshall/collections/MarshalledNode_Test.java
@@ -142,6 +142,15 @@ class MarshalledNode_Test extends TestBase {
                assertNull(MarshalledNode.of(null).value());
        }
 
+       @Test void b09_asNullAndConversionFailureReturnNull() {
+               // as(Class) on a null node short-circuits to null (no 
conversion attempted).
+               assertNull(MarshalledNode.of(null).as(B06_Bean.class));
+               // as(Class) swallows InvalidDataConversionException and 
returns null for a non-convertible scalar...
+               assertNull(MarshalledNode.of("notanumber").as(Integer.class));
+               // ...and for a container that cannot convert to the requested 
scalar type.
+               assertNull(MarshalledNode.of(JsonList.of(1, 
2)).as(Integer.class));
+       }
+
        // 
-----------------------------------------------------------------------------------------------------------------
        // c - Navigation
        // 
-----------------------------------------------------------------------------------------------------------------
diff --git 
a/juneau-core/juneau-marshall/src/test/java/org/apache/juneau/marshall/objecttools/PathTraversal_Test.java
 
b/juneau-core/juneau-marshall/src/test/java/org/apache/juneau/marshall/objecttools/PathTraversal_Test.java
index 7507893dbe..1ed01c2bd6 100644
--- 
a/juneau-core/juneau-marshall/src/test/java/org/apache/juneau/marshall/objecttools/PathTraversal_Test.java
+++ 
b/juneau-core/juneau-marshall/src/test/java/org/apache/juneau/marshall/objecttools/PathTraversal_Test.java
@@ -896,6 +896,14 @@ class PathTraversal_Test extends TestBase {
                assertEquals("C2", p.addresses[0].city);
        }
 
+       @Test void h12_put_intoArray_parentNotMapOrBean_throws() {
+               // Array nested directly inside a List: the array's parent is a 
Collection (not Map/Bean) -> PUT error.
+               var root = new Json5List();
+               root.add(new String[]{"a","b"});
+               var model = PathTraversal.create(root);
+               assertThrowsWithMessage(PathTraversalException.class, "Cannot 
perform PUT on '0/1' with parent node type", ()->model.put("0/1", "B"));
+       }
+
        
//====================================================================================================
        // i - POST operations
        
//====================================================================================================
@@ -976,6 +984,22 @@ class PathTraversal_Test extends TestBase {
                assertThrowsWithMessage(PathTraversalException.class, "Cannot 
perform POST on", ()->model.post("name", "v"));
        }
 
+       @Test void i09_post_toArray_parentNotMapOrBean_throws() {
+               // Array nested directly inside a List: the array's parent is a 
Collection (not Map/Bean) -> POST error.
+               var root = new Json5List();
+               root.add(new String[]{"a","b"});
+               var model = PathTraversal.create(root);
+               assertThrowsWithMessage(PathTraversalException.class, "Cannot 
perform POST on '0' with parent node type", ()->model.post("0", "c"));
+       }
+
+       @Test void i10_post_nodeNotFound_404() {
+               // POST where the target URL resolves through a null 
intermediate -> getNode returns null -> 404.
+               var m = new HashMap<String,Object>();
+               m.put("a", null);
+               var model = PathTraversal.create(m);
+               assertThrowsWithMessage(PathTraversalException.class, "Node at 
URL 'a/b' not found.", ()->model.post("a/b", "v"));
+       }
+
        
//====================================================================================================
        // j - DELETE operations
        
//====================================================================================================
@@ -1055,6 +1079,28 @@ class PathTraversal_Test extends TestBase {
                assertThrowsWithMessage(PathTraversalException.class, "Cannot 
perform PUT on", ()->model.delete("name/x"));
        }
 
+       @Test void j10_delete_fromArray_parentNotMapOrBean_throws() {
+               // Array nested directly inside a List: the array's parent is a 
Collection (not Map/Bean) -> DELETE error.
+               var root = new Json5List();
+               root.add(new String[]{"a","b"});
+               var model = PathTraversal.create(root);
+               assertThrowsWithMessage(PathTraversalException.class, "Cannot 
perform POST on '0/1' with parent node type", ()->model.delete("0/1"));
+       }
+
+       @Test void j11_delete_parentMissing_404() {
+               // DELETE where the parent URL resolves to a missing key 
(o==null, Object meta) -> 404.
+               var model = PathTraversal.create(new Json5Map());
+               assertThrowsWithMessage(PathTraversalException.class, "Node at 
URL 'missing' not found.", ()->model.delete("missing/x"));
+       }
+
+       @Test void j12_delete_parentNotFound_404() {
+               // DELETE where the parent URL resolves through a null 
intermediate -> getNode returns null -> 404.
+               var m = new HashMap<String,Object>();
+               m.put("a", null);
+               var model = PathTraversal.create(m);
+               assertThrowsWithMessage(PathTraversalException.class, "Node at 
URL 'a/b' not found.", ()->model.delete("a/b/c"));
+       }
+
        
//====================================================================================================
        // k - getNode navigation: null o, list/array bounds, bean unknown 
property
        
//====================================================================================================
@@ -1180,4 +1226,27 @@ class PathTraversal_Test extends TestBase {
                assertEquals("editor", roles.get(0));
                assertEquals("viewer", roles.get(1));
        }
+
+       
//====================================================================================================
+       // p - PathTraversalException
+       
//====================================================================================================
+       @Test void p01_getStatus() {
+               assertEquals(404, new PathTraversalException(404, 
"msg").getStatus());
+       }
+
+       @Test void p02_causeConstructor() {
+               var cause = new RuntimeException("boom");
+               var x = new PathTraversalException(cause, 500, "Failed {0}", 
"x");
+               assertSame(cause, x.getCause());
+               assertEquals(500, x.getStatus());
+               assertEquals("Failed x", x.getMessage());
+       }
+
+       @Test void p03_covariantSetMessage() {
+               var x = new PathTraversalException(400, "orig");
+               // setMessage is covariantly typed to return 
PathTraversalException and returns the same instance.
+               PathTraversalException y = x.setMessage("new {0}", "msg");
+               assertSame(x, y);
+               assertEquals("new msg", x.getMessage());
+       }
 }

Reply via email to