From 3684fde56a259920e2f9e0e3adeace83a5643150 Mon Sep 17 00:00:00 2001 From: JanHolger Date: Sat, 9 Mar 2024 16:29:10 +0100 Subject: [PATCH] Improved test coverage in AbstractArray, did a few minor fixes to prevent rare but unexpected NPE's, deprecated the typed query helpers in AbstractArray as they have barely any use-case and unnecessarily bloat the code --- .../abstractdata/AbstractArray.java | 75 +++++-- .../abstractdata/AbstractArrayTest.java | 189 ++++++++++++++++++ 2 files changed, 246 insertions(+), 18 deletions(-) diff --git a/src/main/java/org/javawebstack/abstractdata/AbstractArray.java b/src/main/java/org/javawebstack/abstractdata/AbstractArray.java index a94faaa..c92fa98 100644 --- a/src/main/java/org/javawebstack/abstractdata/AbstractArray.java +++ b/src/main/java/org/javawebstack/abstractdata/AbstractArray.java @@ -30,76 +30,109 @@ public AbstractObject object(boolean strict) throws AbstractCoercingException { return object; } + @Deprecated public AbstractObject object(String key) throws AbstractCoercingException { - return query(key).object(); + AbstractElement e = query(key); + return e != null ? e.object() : null; } + @Deprecated public AbstractArray array(String key) throws AbstractCoercingException { - return query(key).array(); + AbstractElement e = query(key); + return e != null ? e.array() : null; } + @Deprecated public AbstractPrimitive primitive(String key) throws AbstractCoercingException { - return query(key).primitive(); + AbstractElement e = query(key); + return e != null ? e.primitive() : null; } + @Deprecated public String string(String key) throws AbstractCoercingException { - return query(key).string(); + AbstractElement e = query(key); + return e != null ? e.string() : null; } + @Deprecated public Boolean bool(String key) throws AbstractCoercingException { - return query(key).bool(); + AbstractElement e = query(key); + return e != null ? e.bool() : null; } + @Deprecated public Number number(String key) throws AbstractCoercingException { - return query(key).number(); + AbstractElement e = query(key); + return e != null ? e.number() : null; } + @Deprecated public AbstractObject object(String key, AbstractObject orElse) throws AbstractCoercingException { - return query(key, orElse).object(); + AbstractElement e = query(key, orElse); + return e != null ? e.object() : null; } + @Deprecated public AbstractArray array(String key, AbstractArray orElse) throws AbstractCoercingException { - return query(key, orElse).array(); + AbstractElement e = query(key, orElse); + return e != null ? e.array() : null; } + @Deprecated public AbstractPrimitive primitive(String key, AbstractPrimitive orElse) throws AbstractCoercingException { - return query(key, orElse).primitive(); + AbstractElement e = query(key, orElse); + return e != null ? e.primitive() : null; } + @Deprecated public String string(String key, String orElse) throws AbstractCoercingException { - return query(key, new AbstractPrimitive(orElse)).string(); + AbstractPrimitive orElsePrimitive = orElse != null ? new AbstractPrimitive(orElse) : null; + AbstractElement e = primitive(key, orElsePrimitive); + return e != null ? e.string() : null; } + @Deprecated public Boolean bool(String key, Boolean orElse) throws AbstractCoercingException { - return query(key, new AbstractPrimitive(orElse)).bool(); + AbstractPrimitive orElsePrimitive = orElse != null ? new AbstractPrimitive(orElse) : null; + AbstractElement e = primitive(key, orElsePrimitive); + return e != null ? e.bool() : null; } + @Deprecated public Number number(String key, Number orElse) throws AbstractCoercingException { - return query(key, new AbstractPrimitive(orElse)).number(); + AbstractPrimitive orElsePrimitive = orElse != null ? new AbstractPrimitive(orElse) : null; + AbstractElement e = primitive(key, orElsePrimitive); + return e != null ? e.number() : null; } public AbstractObject object(int index) throws AbstractCoercingException { - return get(index).object(); + AbstractElement e = get(index); + return e != null ? e.object() : null; } public AbstractArray array(int index) throws AbstractCoercingException { - return get(index).array(); + AbstractElement e = get(index); + return e != null ? e.array() : null; } public AbstractPrimitive primitive(int index) throws AbstractCoercingException { - return get(index).primitive(); + AbstractElement e = get(index); + return e != null ? e.primitive() : null; } public String string(int index) throws AbstractCoercingException { - return get(index).string(); + AbstractElement e = get(index); + return e != null ? e.string() : null; } public Boolean bool(int index) throws AbstractCoercingException { - return get(index).bool(); + AbstractElement e = get(index); + return e != null ? e.bool() : null; } public Number number(int index) throws AbstractCoercingException { - return get(index).number(); + AbstractElement e = get(index); + return e != null ? e.number() : null; } public AbstractObject object(int index, AbstractObject orElse) throws AbstractCoercingException { @@ -214,6 +247,8 @@ public AbstractElement[] toArray() { } public AbstractElement get(int i) { + if(i >= elements.size()) + return null; return elements.get(i); } @@ -223,6 +258,8 @@ public AbstractElement get(int index, AbstractElement orElse) { } public AbstractElement query(String query) { + if(query == null) + throw new IllegalArgumentException("query can not be null"); String[] q = query.split("\\.", 2); try { int index = Integer.parseInt(q[0]); @@ -370,6 +407,8 @@ public boolean equals(Object obj) { } public AbstractArray addAll(AbstractArray array) { + if(array == null) + throw new IllegalArgumentException("array may not be null"); elements.addAll(array.elements); return this; } diff --git a/src/test/java/org/javawebstack/abstractdata/AbstractArrayTest.java b/src/test/java/org/javawebstack/abstractdata/AbstractArrayTest.java index d02306f..0c503f9 100644 --- a/src/test/java/org/javawebstack/abstractdata/AbstractArrayTest.java +++ b/src/test/java/org/javawebstack/abstractdata/AbstractArrayTest.java @@ -1,11 +1,200 @@ package org.javawebstack.abstractdata; +import org.javawebstack.abstractdata.exception.AbstractCoercingException; import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.*; class AbstractArrayTest { + @Test + void testIsArrayReturnsTrue() { + assertTrue(new AbstractArray().isArray()); + } + + @Test + void testObjectThrowsInStrictMode() { + assertThrows(AbstractCoercingException.class, () -> new AbstractArray().object(true)); + } + + @Test + void testObjectCoercingWhenNotInStrictMode() { + AbstractArray a = new AbstractArray(); + a.add(0); + a.add("1"); + AbstractObject o = assertDoesNotThrow(() -> a.object(false)); + assertTrue(o.hasNumber("0")); + assertTrue(o.hasString("1")); + } + + @Test + void testObjectQueryReturnsNullWhenKeyIsNotFound() { + assertNull(new AbstractArray().add(new AbstractObject()).object("1")); + } + + @Test + void testObjectQueryReturnsValueWhenKeyIsFound() { + assertNotNull(new AbstractArray().add(new AbstractObject()).object("0")); + } + + @Test + void testArrayQueryReturnsNullWhenKeyIsNotFound() { + assertNull(new AbstractArray().add(new AbstractArray()).array("1")); + } + + @Test + void testArrayQueryReturnsValueWhenKeyIsFound() { + assertNotNull(new AbstractArray().add(new AbstractArray()).array("0")); + } + + @Test + void testPrimitiveQueryReturnsNullWhenKeyIsNotFound() { + assertNull(new AbstractArray().add(0).primitive("1")); + } + + @Test + void testPrimitiveQueryReturnsValueWhenKeyIsFound() { + assertNotNull(new AbstractArray().add(0).primitive("0")); + } + + @Test + void testStringQueryReturnsNullWhenKeyIsNotFound() { + assertNull(new AbstractArray().add("abc").string("1")); + } + + @Test + void testStringQueryReturnsValueWhenKeyIsFound() { + assertEquals("abc", new AbstractArray().add("abc").string("0")); + } + + @Test + void testNumberQueryReturnsNullWhenKeyIsNotFound() { + assertNull(new AbstractArray().add(123).number("1")); + } + + @Test + void testNumberQueryReturnsValueWhenKeyIsFound() { + assertEquals(123, new AbstractArray().add(123).number("0")); + } + + @Test + void testBoolQueryReturnsNullWhenKeyIsNotFound() { + assertNull(new AbstractArray().add(true).bool("1")); + } + + @Test + void testBoolQueryReturnsValueWhenKeyIsFound() { + assertEquals(true, new AbstractArray().add(true).bool("0")); + } + + @Test + void testQueryOrElseReturnsValueIfFoundAndNonNull() { + AbstractElement expected = new AbstractPrimitive(123); + AbstractElement orElse = new AbstractPrimitive("456"); + AbstractArray array = new AbstractArray().add(expected); + assertEquals(expected, array.query("0", orElse)); + } + + @Test + void testQueryOrElseReturnsOrElseIfFoundAndNull() { + AbstractElement orElse = new AbstractPrimitive("456"); + AbstractArray array = new AbstractArray().addNull(); + assertEquals(orElse, array.query("0", orElse)); + } + + @Test + void testQueryOrElseReturnsOrElseIfNotFound() { + AbstractElement unexpected = new AbstractPrimitive(123); + AbstractElement orElse = new AbstractPrimitive("456"); + AbstractArray array = new AbstractArray().add(unexpected); + assertEquals(orElse, array.query("1", orElse)); + } + + @Test + void testObjectQueryOrElseReturnsOrElseIfNotFound() { + AbstractObject orElse = new AbstractObject().set("a", 1); + assertSame(orElse, new AbstractArray().object("0", orElse)); + } + + @Test + void testArrayQueryOrElseReturnsOrElseIfNotFound() { + AbstractArray orElse = new AbstractArray().add(123); + assertSame(orElse, new AbstractArray().array("0", orElse)); + } + + @Test + void testPrimitiveQueryOrElseReturnsOrElseIfNotFound() { + AbstractPrimitive orElse = new AbstractPrimitive(123); + assertSame(orElse, new AbstractArray().primitive("0", orElse)); + } + + @Test + void testStringQueryOrElseReturnsOrElseIfNotFound() { + String orElse = "abc"; + assertEquals(orElse, new AbstractArray().string("0", orElse)); + } + + @Test + void testNumberQueryOrElseReturnsOrElseIfNotFound() { + Number orElse = 123; + assertEquals(orElse, new AbstractArray().number("0", orElse)); + } + + @Test + void testBoolQueryOrElseReturnsOrElseIfNotFound() { + Boolean orElse = true; + assertEquals(orElse, new AbstractArray().bool("0", orElse)); + } + + @Test + void testQueryThrowsOnNull() { + assertThrows(IllegalArgumentException.class, () -> new AbstractArray().query(null)); + } + + @Test + void testQueryWithNonIntPathReturnsNull() { + assertNull(new AbstractArray().add(1).query("abc")); + } + + @Test + void testQueryWithNonExistingIndexReturnsNull() { + assertNull(new AbstractArray().add(0).query("1")); + } + + @Test + void testQueryWithOnlyOneSegmentReturnsValue() { + assertNotNull(new AbstractArray().add(1).query("0")); + } + + @Test + void testClearClearsTheArrayAndReturnsThis() { + AbstractArray array = new AbstractArray().add(1).add(2).add(3); + assertEquals(3, array.size()); + assertSame(array, array.clear()); + assertEquals(0, array.size()); + } + + @Test + void testQueryWithObjectValueQueriesObject() { + AbstractArray array = new AbstractArray(); + array.add(new AbstractObject().set("a", 1)); + assertEquals(1, array.query("0.a").number().intValue()); + } + + @Test + void testQueryWithArrayValueQueriesArray() { + AbstractArray array = new AbstractArray(); + array.add(new AbstractArray().add(1)); + assertEquals(1, array.query("0.0").number().intValue()); + } + + @Test + void testQueryWithPrimitiveValueReturnsNull() { + AbstractArray array = new AbstractArray(); + array.add("abc"); + assertNull(array.query("0.abc")); + } + @Test void testEqualsNormal() { AbstractArray first = new AbstractArray();