This is an automated email from the ASF dual-hosted git repository. garydgregory pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/commons-collections.git
commit 6eb1ecc870a001946954751ffcb872f804640399 Author: Gary Gregory <[email protected]> AuthorDate: Mon Jul 13 12:11:13 2026 -0400 Sort members. --- .../commons/collections4/list/SetUniqueList.java | 30 ++++---- .../commons/collections4/set/ListOrderedSet.java | 30 ++++---- .../commons/collections4/ClosureUtilsTest.java | 54 +++++++------- .../commons/collections4/bag/AbstractBagTest.java | 40 +++++----- .../commons/collections4/bag/HashBagTest.java | 26 +++---- .../bloomfilter/SetOperationsTest.java | 52 ++++++------- .../collections4/list/SetUniqueListTest.java | 24 +++--- .../collections4/map/CaseInsensitiveMapTest.java | 24 +++--- .../commons/collections4/map/CompositeMapTest.java | 32 ++++---- .../map/ConcurrentHashMapSanityTest.java | 22 +++--- .../commons/collections4/map/HashedMapTest.java | 34 ++++----- .../commons/collections4/map/LRUMapTest.java | 24 +++--- .../commons/collections4/map/LinkedMapTest.java | 20 ++--- .../collections4/map/ListOrderedMapTest.java | 20 ++--- .../collections4/map/ReferenceIdentityMapTest.java | 24 +++--- .../multimap/AbstractMultiValuedMapTest.java | 36 ++++----- .../multiset/AbstractMultiSetTest.java | 86 +++++++++++----------- .../collections4/multiset/HashMultiSetTest.java | 36 ++++----- .../collections4/multiset/TreeMultiSetTest.java | 20 ++--- .../properties/OrderedPropertiesTest.java | 28 +++---- .../collections4/queue/CircularFifoQueueTest.java | 80 ++++++++++---------- .../commons/collections4/set/CompositeSetTest.java | 46 ++++++------ .../collections4/set/ListOrderedSetTest.java | 18 ++--- 23 files changed, 403 insertions(+), 403 deletions(-) diff --git a/src/main/java/org/apache/commons/collections4/list/SetUniqueList.java b/src/main/java/org/apache/commons/collections4/list/SetUniqueList.java index 22c1038b7..a63e18714 100644 --- a/src/main/java/org/apache/commons/collections4/list/SetUniqueList.java +++ b/src/main/java/org/apache/commons/collections4/list/SetUniqueList.java @@ -337,6 +337,21 @@ public class SetUniqueList<E> extends AbstractSerializableListDecorator<E> { return new SetListListIterator<>(super.listIterator(index), set); } + /** + * Deserializes the list and re-checks the no-duplicate invariant the + * constructors guarantee. + * + * @param in The input stream + * @throws IOException if an error occurs while reading from the stream + * @throws ClassNotFoundException if a class read from the stream cannot be loaded + */ + private void readObject(final ObjectInputStream in) throws IOException, ClassNotFoundException { + in.defaultReadObject(); + if (set.size() != size() || !new HashSet<>(decorated()).equals(set)) { + throw new InvalidObjectException("Inconsistent SetUniqueList deserialized: backing list does not match the uniqueness set"); + } + } + @Override public E remove(final int index) { final E result = super.remove(index); @@ -437,19 +452,4 @@ public class SetUniqueList<E> extends AbstractSerializableListDecorator<E> { return ListUtils.unmodifiableList(new SetUniqueList<>(superSubList, subSet)); } - /** - * Deserializes the list and re-checks the no-duplicate invariant the - * constructors guarantee. - * - * @param in The input stream - * @throws IOException if an error occurs while reading from the stream - * @throws ClassNotFoundException if a class read from the stream cannot be loaded - */ - private void readObject(final ObjectInputStream in) throws IOException, ClassNotFoundException { - in.defaultReadObject(); - if (set.size() != size() || !new HashSet<>(decorated()).equals(set)) { - throw new InvalidObjectException("Inconsistent SetUniqueList deserialized: backing list does not match the uniqueness set"); - } - } - } diff --git a/src/main/java/org/apache/commons/collections4/set/ListOrderedSet.java b/src/main/java/org/apache/commons/collections4/set/ListOrderedSet.java index 470e7ffcb..eb96dc9fe 100644 --- a/src/main/java/org/apache/commons/collections4/set/ListOrderedSet.java +++ b/src/main/java/org/apache/commons/collections4/set/ListOrderedSet.java @@ -322,6 +322,21 @@ public class ListOrderedSet<E> return new OrderedSetIterator<>(setOrder.listIterator(), decorated()); } + /** + * Deserializes the set and re-checks that the iteration order matches the + * decorated set, as the constructors guarantee. + * + * @param in The input stream + * @throws IOException if an error occurs while reading from the stream + * @throws ClassNotFoundException if a class read from the stream cannot be loaded + */ + private void readObject(final ObjectInputStream in) throws IOException, ClassNotFoundException { + in.defaultReadObject(); + if (setOrder.size() != size() || !new HashSet<>(setOrder).equals(decorated())) { + throw new InvalidObjectException("Inconsistent ListOrderedSet deserialized: iteration order does not match the set"); + } + } + /** * Removes the element at the specified position from the ordered set. * Shifts any subsequent elements to the left. @@ -416,19 +431,4 @@ public class ListOrderedSet<E> return setOrder.toString(); } - /** - * Deserializes the set and re-checks that the iteration order matches the - * decorated set, as the constructors guarantee. - * - * @param in The input stream - * @throws IOException if an error occurs while reading from the stream - * @throws ClassNotFoundException if a class read from the stream cannot be loaded - */ - private void readObject(final ObjectInputStream in) throws IOException, ClassNotFoundException { - in.defaultReadObject(); - if (setOrder.size() != size() || !new HashSet<>(setOrder).equals(decorated())) { - throw new InvalidObjectException("Inconsistent ListOrderedSet deserialized: iteration order does not match the set"); - } - } - } diff --git a/src/test/java/org/apache/commons/collections4/ClosureUtilsTest.java b/src/test/java/org/apache/commons/collections4/ClosureUtilsTest.java index 4a7ea5f19..3faa7eb5c 100644 --- a/src/test/java/org/apache/commons/collections4/ClosureUtilsTest.java +++ b/src/test/java/org/apache/commons/collections4/ClosureUtilsTest.java @@ -273,6 +273,33 @@ class ClosureUtilsTest { () -> ClosureUtils.<String>switchClosure(new Predicate[] { TruePredicate.<String>truePredicate() }, new Closure[] { a, b })); } + @Test + void testSwitchClosureDoesNotMutateInputMap() { + final MockClosure<String> def = new MockClosure<>(); + final MockClosure<String> match = new MockClosure<>(); + final Map<Predicate<String>, Closure<String>> predicateMap = new HashMap<>(); + predicateMap.put(null, def); + predicateMap.put(EqualPredicate.equalPredicate("HELLO"), match); + final Closure<String> closure = ClosureUtils.switchClosure(predicateMap); + assertTrue(predicateMap.containsKey(null)); + closure.execute("HELLO"); + closure.execute("WORLD"); + assertEquals(1, match.count); + assertEquals(1, def.count); + + final MockClosure<String> mapDef = new MockClosure<>(); + final MockClosure<String> mapMatch = new MockClosure<>(); + final Map<String, Closure<String>> objectMap = new HashMap<>(); + objectMap.put(null, mapDef); + objectMap.put("HELLO", mapMatch); + final Closure<String> mapClosure = ClosureUtils.switchMapClosure(objectMap); + assertTrue(objectMap.containsKey(null)); + mapClosure.execute("HELLO"); + mapClosure.execute("WORLD"); + assertEquals(1, mapMatch.count); + assertEquals(1, mapDef.count); + } + @Test void testSwitchMapClosure() { final MockClosure<String> a = new MockClosure<>(); @@ -310,33 +337,6 @@ class ClosureUtilsTest { assertThrows(NullPointerException.class, () -> ClosureUtils.switchMapClosure(null)); } - @Test - void testSwitchClosureDoesNotMutateInputMap() { - final MockClosure<String> def = new MockClosure<>(); - final MockClosure<String> match = new MockClosure<>(); - final Map<Predicate<String>, Closure<String>> predicateMap = new HashMap<>(); - predicateMap.put(null, def); - predicateMap.put(EqualPredicate.equalPredicate("HELLO"), match); - final Closure<String> closure = ClosureUtils.switchClosure(predicateMap); - assertTrue(predicateMap.containsKey(null)); - closure.execute("HELLO"); - closure.execute("WORLD"); - assertEquals(1, match.count); - assertEquals(1, def.count); - - final MockClosure<String> mapDef = new MockClosure<>(); - final MockClosure<String> mapMatch = new MockClosure<>(); - final Map<String, Closure<String>> objectMap = new HashMap<>(); - objectMap.put(null, mapDef); - objectMap.put("HELLO", mapMatch); - final Closure<String> mapClosure = ClosureUtils.switchMapClosure(objectMap); - assertTrue(objectMap.containsKey(null)); - mapClosure.execute("HELLO"); - mapClosure.execute("WORLD"); - assertEquals(1, mapMatch.count); - assertEquals(1, mapDef.count); - } - @Test void testTransformerClosure() { final MockTransformer<Object> mock = new MockTransformer<>(); diff --git a/src/test/java/org/apache/commons/collections4/bag/AbstractBagTest.java b/src/test/java/org/apache/commons/collections4/bag/AbstractBagTest.java index ca4a4ae21..e2e6a0322 100644 --- a/src/test/java/org/apache/commons/collections4/bag/AbstractBagTest.java +++ b/src/test/java/org/apache/commons/collections4/bag/AbstractBagTest.java @@ -603,6 +603,25 @@ public abstract class AbstractBagTest<T> extends AbstractCollectionTest<T> { assertEquals(2, bag.size(), "Should have 2 total items"); } + @Test + @SuppressWarnings("unchecked") + void testBagRetainAllOtherHasMoreCopies() { + if (!isAddSupported()) { + return; + } + final Bag<T> bag = makeObject(); + bag.add((T) "A", 2); + bag.add((T) "B", 3); + final Bag<T> other = makeObject(); + other.add((T) "A", 5); + other.add((T) "B", 10); + bag.retainAll(other); + // When other has MORE copies, we should keep ALL of ours (the intersection keeps min) + assertEquals(2, bag.getCount("A"), "Should keep 2 copies of A when other has 5"); + assertEquals(3, bag.getCount("B"), "Should keep 3 copies of B when other has 10"); + assertEquals(5, bag.size(), "Should have 5 total items"); + } + @Test @SuppressWarnings("unchecked") void testBagSize() { @@ -698,6 +717,7 @@ public abstract class AbstractBagTest<T> extends AbstractCollectionTest<T> { } } + /** * Compare the current serialized form of the Bag * against the canonical version in SCM. @@ -712,24 +732,4 @@ public abstract class AbstractBagTest<T> extends AbstractCollectionTest<T> { assertEquals(bag, bag2); } } - - - @Test - @SuppressWarnings("unchecked") - void testBagRetainAllOtherHasMoreCopies() { - if (!isAddSupported()) { - return; - } - final Bag<T> bag = makeObject(); - bag.add((T) "A", 2); - bag.add((T) "B", 3); - final Bag<T> other = makeObject(); - other.add((T) "A", 5); - other.add((T) "B", 10); - bag.retainAll(other); - // When other has MORE copies, we should keep ALL of ours (the intersection keeps min) - assertEquals(2, bag.getCount("A"), "Should keep 2 copies of A when other has 5"); - assertEquals(3, bag.getCount("B"), "Should keep 3 copies of B when other has 10"); - assertEquals(5, bag.size(), "Should have 5 total items"); - } } diff --git a/src/test/java/org/apache/commons/collections4/bag/HashBagTest.java b/src/test/java/org/apache/commons/collections4/bag/HashBagTest.java index b8671e98a..9b2f357a4 100644 --- a/src/test/java/org/apache/commons/collections4/bag/HashBagTest.java +++ b/src/test/java/org/apache/commons/collections4/bag/HashBagTest.java @@ -45,19 +45,6 @@ public class HashBagTest<T> extends AbstractBagTest<T> { return new HashBag<>(); } - @Test - void testDeserializeRejectsNonPositiveCount() throws Exception { - final int marker = 0x11223344; - final HashBag<String> bag = new HashBag<>(); - bag.add("X", marker); - final byte[] byteArray = serialize(bag); - for (final int count : new int[] { 0, -7 }) { - final byte[] bytes = byteArray.clone(); - replaceInt(bytes, marker, count); - assertThrows(InvalidObjectException.class, () -> deserialize(bytes)); - } - } - @Test void testAddClampsCountAndSizeToIntegerMaxValue() { final HashBag<String> bag = new HashBag<>(); @@ -77,6 +64,19 @@ public class HashBagTest<T> extends AbstractBagTest<T> { assertEquals(Integer.MAX_VALUE - 10, bag.size()); } + @Test + void testDeserializeRejectsNonPositiveCount() throws Exception { + final int marker = 0x11223344; + final HashBag<String> bag = new HashBag<>(); + bag.add("X", marker); + final byte[] byteArray = serialize(bag); + for (final int count : new int[] { 0, -7 }) { + final byte[] bytes = byteArray.clone(); + replaceInt(bytes, marker, count); + assertThrows(InvalidObjectException.class, () -> deserialize(bytes)); + } + } + // void testCreate() throws Exception { // Bag<T> bag = makeObject(); // writeExternalFormToDisk((java.io.Serializable) bag, "src/test/resources/data/test/HashBag.emptyCollection.version4.obj"); diff --git a/src/test/java/org/apache/commons/collections4/bloomfilter/SetOperationsTest.java b/src/test/java/org/apache/commons/collections4/bloomfilter/SetOperationsTest.java index 60da89457..319596d58 100644 --- a/src/test/java/org/apache/commons/collections4/bloomfilter/SetOperationsTest.java +++ b/src/test/java/org/apache/commons/collections4/bloomfilter/SetOperationsTest.java @@ -180,6 +180,32 @@ class SetOperationsTest { assertSymmetricOperation(0.0, SetOperations::cosineSimilarity, filter1, filter3); } + @Test + final void testCosineSimilarityLargeCardinalityNoOverflow() { + // Create two identical BitMapExtractors with cardinality > 46341 each. + // Each long has 64 bits. We want cardinality = 50000. + // 781 * 64 = 49984, plus 16 more bits = 50000. + final long[] bitMaps = new long[782]; + for (int i = 0; i < 781; i++) { + bitMaps[i] = -1L; // all 64 bits set + } + // Last word: 16 bits set = 0xFFFF + bitMaps[781] = 0xFFFFL; + + final BitMapExtractor extractor = BitMapExtractor.fromBitMapArray(bitMaps); + // Verify cardinality is 50000 + assertEquals(50000, SetOperations.cardinality(extractor)); + + // Cosine similarity of two identical non-empty extractors should be 1.0. + // With integer overflow: 50000 * 50000 = 2,500,000,000 > Integer.MAX_VALUE, overflows to negative, + // Math.sqrt(negative) = NaN, so the result would be NaN instead of 1.0. + final double similarity = SetOperations.cosineSimilarity(extractor, extractor); + assertEquals(1.0, similarity, 1e-9, "cosineSimilarity of identical large-cardinality extractors should be 1.0, not NaN"); + + final double distance = SetOperations.cosineDistance(extractor, extractor); + assertEquals(0.0, distance, 1e-9, "cosineDistance of identical large-cardinality extractors should be 0.0, not NaN"); + } + /** * Tests that the Hamming distance is correctly calculated. */ @@ -324,30 +350,4 @@ class SetOperationsTest { filter2 = createFilter(shape2, IndexExtractor.fromIndexArray(5, 64, 169)); assertSymmetricOperation(3, SetOperations::xorCardinality, filter1, filter2); } - - @Test - final void testCosineSimilarityLargeCardinalityNoOverflow() { - // Create two identical BitMapExtractors with cardinality > 46341 each. - // Each long has 64 bits. We want cardinality = 50000. - // 781 * 64 = 49984, plus 16 more bits = 50000. - final long[] bitMaps = new long[782]; - for (int i = 0; i < 781; i++) { - bitMaps[i] = -1L; // all 64 bits set - } - // Last word: 16 bits set = 0xFFFF - bitMaps[781] = 0xFFFFL; - - final BitMapExtractor extractor = BitMapExtractor.fromBitMapArray(bitMaps); - // Verify cardinality is 50000 - assertEquals(50000, SetOperations.cardinality(extractor)); - - // Cosine similarity of two identical non-empty extractors should be 1.0. - // With integer overflow: 50000 * 50000 = 2,500,000,000 > Integer.MAX_VALUE, overflows to negative, - // Math.sqrt(negative) = NaN, so the result would be NaN instead of 1.0. - final double similarity = SetOperations.cosineSimilarity(extractor, extractor); - assertEquals(1.0, similarity, 1e-9, "cosineSimilarity of identical large-cardinality extractors should be 1.0, not NaN"); - - final double distance = SetOperations.cosineDistance(extractor, extractor); - assertEquals(0.0, distance, 1e-9, "cosineDistance of identical large-cardinality extractors should be 0.0, not NaN"); - } } diff --git a/src/test/java/org/apache/commons/collections4/list/SetUniqueListTest.java b/src/test/java/org/apache/commons/collections4/list/SetUniqueListTest.java index 8232646bd..b966fb401 100644 --- a/src/test/java/org/apache/commons/collections4/list/SetUniqueListTest.java +++ b/src/test/java/org/apache/commons/collections4/list/SetUniqueListTest.java @@ -102,17 +102,6 @@ public class SetUniqueListTest<E> extends AbstractListTest<E> { return new SetUniqueList<>(new ArrayList<>(), new HashSet<>()); } - @Test - void testDeserializeRejectsDuplicateInBackingList() throws Exception { - final SetUniqueList<String> list = SetUniqueList.setUniqueList(new ArrayList<>()); - list.add("alpha"); - list.add("beta"); - // push a duplicate straight onto the decorated list, bypassing the uniqueness set - list.decorated().add("alpha"); - assertThrows(InvalidObjectException.class, () -> serializeDeserialize(list)); - - } - @Test @SuppressWarnings("unchecked") void testAdd() { @@ -180,6 +169,7 @@ public class SetUniqueListTest<E> extends AbstractListTest<E> { extraVerify = true; } } + @Test void testCollections304() { final List<String> list = new LinkedList<>(); @@ -203,7 +193,6 @@ public class SetUniqueListTest<E> extends AbstractListTest<E> { decoratedList.add(1, s2); assertEquals(4, decoratedList.size()); } - @Test @SuppressWarnings("unchecked") void testCollections307() { @@ -300,6 +289,17 @@ public class SetUniqueListTest<E> extends AbstractListTest<E> { assertThrows(NullPointerException.class, () -> setUniqueList.createSetBasedOnList(new HashSet<>(), null)); } + @Test + void testDeserializeRejectsDuplicateInBackingList() throws Exception { + final SetUniqueList<String> list = SetUniqueList.setUniqueList(new ArrayList<>()); + list.add("alpha"); + list.add("beta"); + // push a duplicate straight onto the decorated list, bypassing the uniqueness set + list.decorated().add("alpha"); + assertThrows(InvalidObjectException.class, () -> serializeDeserialize(list)); + + } + @Test void testFactory() { final Integer[] array = { Integer.valueOf(1), Integer.valueOf(2), Integer.valueOf(1) }; diff --git a/src/test/java/org/apache/commons/collections4/map/CaseInsensitiveMapTest.java b/src/test/java/org/apache/commons/collections4/map/CaseInsensitiveMapTest.java index f7a902523..6339938ab 100644 --- a/src/test/java/org/apache/commons/collections4/map/CaseInsensitiveMapTest.java +++ b/src/test/java/org/apache/commons/collections4/map/CaseInsensitiveMapTest.java @@ -50,18 +50,6 @@ public class CaseInsensitiveMapTest<K, V> extends AbstractIterableMapTest<K, V> return new CaseInsensitiveMap<>(); } - /** - * A crafted stream can carry a load factor the constructor rejects. AbstractHashedMap.doReadObject - * must reapply that contract on read. - */ - @ParameterizedTest - @ValueSource(floats = {0.0f, -1.0f, Float.NaN}) - void testDeserializeRejectsInvalidLoadFactor(final float badLoadFactor) { - final CaseInsensitiveMap<K, V> map = new CaseInsensitiveMap<>(); - map.loadFactor = badLoadFactor; - assertThrows(InvalidObjectException.class, () -> serializeDeserialize(map)); - } - @Test @SuppressWarnings("unchecked") void testCaseInsensitive() { @@ -84,6 +72,18 @@ public class CaseInsensitiveMapTest<K, V> extends AbstractIterableMapTest<K, V> assertSame(map.get("1"), cloned.get("1")); } + /** + * A crafted stream can carry a load factor the constructor rejects. AbstractHashedMap.doReadObject + * must reapply that contract on read. + */ + @ParameterizedTest + @ValueSource(floats = {0.0f, -1.0f, Float.NaN}) + void testDeserializeRejectsInvalidLoadFactor(final float badLoadFactor) { + final CaseInsensitiveMap<K, V> map = new CaseInsensitiveMap<>(); + map.loadFactor = badLoadFactor; + assertThrows(InvalidObjectException.class, () -> serializeDeserialize(map)); + } + /** * Test for <a href="https://issues.apache.org/jira/browse/COLLECTIONS-323">COLLECTIONS-323</a>. */ diff --git a/src/test/java/org/apache/commons/collections4/map/CompositeMapTest.java b/src/test/java/org/apache/commons/collections4/map/CompositeMapTest.java index e315788c0..2e33f1447 100644 --- a/src/test/java/org/apache/commons/collections4/map/CompositeMapTest.java +++ b/src/test/java/org/apache/commons/collections4/map/CompositeMapTest.java @@ -51,6 +51,22 @@ public class CompositeMapTest<K, V> extends AbstractIterableMapTest<K, V> { } } + /** An empty-iterating map that reports {@code Integer.MAX_VALUE} mappings. */ + private static Map<String, String> maxSizeMap() { + return new AbstractMap<String, String>() { + + @Override + public Set<Map.Entry<String, String>> entrySet() { + return Collections.emptySet(); + } + + @Override + public int size() { + return Integer.MAX_VALUE; + } + }; + } + /** Used as a flag in MapMutator tests */ private boolean pass; @@ -244,22 +260,6 @@ public class CompositeMapTest<K, V> extends AbstractIterableMapTest<K, V> { assertEquals(Integer.MAX_VALUE, map.size()); } - /** An empty-iterating map that reports {@code Integer.MAX_VALUE} mappings. */ - private static Map<String, String> maxSizeMap() { - return new AbstractMap<String, String>() { - - @Override - public Set<Map.Entry<String, String>> entrySet() { - return Collections.emptySet(); - } - - @Override - public int size() { - return Integer.MAX_VALUE; - } - }; - } - // void testCreate() throws Exception { // resetEmpty(); // writeExternalFormToDisk((java.io.Serializable) map, "src/test/resources/data/test/CompositeMap.emptyCollection.version4.obj"); diff --git a/src/test/java/org/apache/commons/collections4/map/ConcurrentHashMapSanityTest.java b/src/test/java/org/apache/commons/collections4/map/ConcurrentHashMapSanityTest.java index 78ec38d9e..501ac3260 100644 --- a/src/test/java/org/apache/commons/collections4/map/ConcurrentHashMapSanityTest.java +++ b/src/test/java/org/apache/commons/collections4/map/ConcurrentHashMapSanityTest.java @@ -30,6 +30,17 @@ import org.junit.jupiter.api.Test; */ public class ConcurrentHashMapSanityTest<K, V> extends AbstractMapTest<ConcurrentHashMap<K, V>, K, V> { + @Nested + public class MapEntrySetTest extends AbstractMapTest.MapEntrySetTest { + @Test + @Override + public void testUnsupportedAdd() { + resetEmpty(); + // ConcurrentHashMap.entrySet() supports add. + getCollection().add(getFullNonNullElements()[0]); + } + } + @Override public boolean isAllowNullKey() { return false; @@ -53,17 +64,6 @@ public class ConcurrentHashMapSanityTest<K, V> extends AbstractMapTest<Concurren return false; } - @Nested - public class MapEntrySetTest extends AbstractMapTest.MapEntrySetTest { - @Test - @Override - public void testUnsupportedAdd() { - resetEmpty(); - // ConcurrentHashMap.entrySet() supports add. - getCollection().add(getFullNonNullElements()[0]); - } - } - @Override public ConcurrentHashMap<K, V> makeObject() { return new ConcurrentHashMap<>(); diff --git a/src/test/java/org/apache/commons/collections4/map/HashedMapTest.java b/src/test/java/org/apache/commons/collections4/map/HashedMapTest.java index 9d9a451a4..340150fb1 100644 --- a/src/test/java/org/apache/commons/collections4/map/HashedMapTest.java +++ b/src/test/java/org/apache/commons/collections4/map/HashedMapTest.java @@ -55,12 +55,15 @@ public class HashedMapTest<K, V> extends AbstractIterableMapTest<K, V> { } /** - * Test for <a href="https://issues.apache.org/jira/browse/COLLECTIONS-323">COLLECTIONS-323</a>. + * A crafted stream can carry a load factor the constructor rejects. AbstractHashedMap.doReadObject + * must reapply that contract on read. */ - @Test - void testInitialCapacityZero() { - final HashedMap<String, String> map = new HashedMap<>(0); - assertEquals(1, map.data.length); + @ParameterizedTest + @ValueSource(floats = {0.0f, -1.0f, Float.NaN}) + void testDeserializeRejectsInvalidLoadFactor(final float badLoadFactor) { + final HashedMap<K, V> map = new HashedMap<>(); + map.loadFactor = badLoadFactor; + assertThrows(InvalidObjectException.class, () -> serializeDeserialize(map)); } // void testCreate() throws Exception { @@ -70,6 +73,15 @@ public class HashedMapTest<K, V> extends AbstractIterableMapTest<K, V> { // writeExternalFormToDisk((java.io.Serializable) map, "src/test/resources/data/test/HashedMap.fullCollection.version4.obj"); // } + /** + * Test for <a href="https://issues.apache.org/jira/browse/COLLECTIONS-323">COLLECTIONS-323</a>. + */ + @Test + void testInitialCapacityZero() { + final HashedMap<String, String> map = new HashedMap<>(0); + assertEquals(1, map.data.length); + } + @Test void testInternalState() { final HashedMap<Integer, Integer> map = new HashedMap<>(42, 0.75f); @@ -90,16 +102,4 @@ public class HashedMapTest<K, V> extends AbstractIterableMapTest<K, V> { // the threshold has changed due to calling ensureCapacity assertEquals(96, map.threshold); } - - /** - * A crafted stream can carry a load factor the constructor rejects. AbstractHashedMap.doReadObject - * must reapply that contract on read. - */ - @ParameterizedTest - @ValueSource(floats = {0.0f, -1.0f, Float.NaN}) - void testDeserializeRejectsInvalidLoadFactor(final float badLoadFactor) { - final HashedMap<K, V> map = new HashedMap<>(); - map.loadFactor = badLoadFactor; - assertThrows(InvalidObjectException.class, () -> serializeDeserialize(map)); - } } diff --git a/src/test/java/org/apache/commons/collections4/map/LRUMapTest.java b/src/test/java/org/apache/commons/collections4/map/LRUMapTest.java index 20520ac94..5e528bf0c 100644 --- a/src/test/java/org/apache/commons/collections4/map/LRUMapTest.java +++ b/src/test/java/org/apache/commons/collections4/map/LRUMapTest.java @@ -169,18 +169,6 @@ public class LRUMapTest<K, V> extends AbstractOrderedMapTest<K, V> { return new LRUMap<>(); } - /** - * A crafted stream can carry a load factor the constructor rejects. AbstractHashedMap.doReadObject - * must reapply that contract on read. - */ - @ParameterizedTest - @ValueSource(floats = {0.0f, -1.0f, Float.NaN}) - void testDeserializeRejectsInvalidLoadFactor(final float badLoadFactor) { - final LRUMap<K, V> map = new LRUMap<>(); - map.loadFactor = badLoadFactor; - assertThrows(InvalidObjectException.class, () -> serializeDeserialize(map)); - } - @Test void testAccessOrder() { if (!isPutAddSupported() || !isPutChangeSupported()) { @@ -326,6 +314,18 @@ public class LRUMapTest<K, V> extends AbstractOrderedMapTest<K, V> { assertThrows(IllegalArgumentException.class, () -> new LRUMap<K, V>(10, 12, 0.75f, false), "initialSize must not be larger than maxSize"); } + /** + * A crafted stream can carry a load factor the constructor rejects. AbstractHashedMap.doReadObject + * must reapply that contract on read. + */ + @ParameterizedTest + @ValueSource(floats = {0.0f, -1.0f, Float.NaN}) + void testDeserializeRejectsInvalidLoadFactor(final float badLoadFactor) { + final LRUMap<K, V> map = new LRUMap<>(); + map.loadFactor = badLoadFactor; + assertThrows(InvalidObjectException.class, () -> serializeDeserialize(map)); + } + @Test void testDeserializeRejectsNonPositiveMaxSize() throws Exception { final LRUMap<String, String> map = new LRUMap<>(3); diff --git a/src/test/java/org/apache/commons/collections4/map/LinkedMapTest.java b/src/test/java/org/apache/commons/collections4/map/LinkedMapTest.java index 35d8f4181..13be9ae76 100644 --- a/src/test/java/org/apache/commons/collections4/map/LinkedMapTest.java +++ b/src/test/java/org/apache/commons/collections4/map/LinkedMapTest.java @@ -119,6 +119,16 @@ public class LinkedMapTest<K, V> extends AbstractOrderedMapTest<K, V> { return new LinkedMap<>(); } + @Test + @SuppressWarnings("unchecked") + void testClone() { + final LinkedMap<K, V> map = new LinkedMap<>(10); + map.put((K) "1", (V) "1"); + final Map<K, V> cloned = map.clone(); + assertEquals(map.size(), cloned.size()); + assertSame(map.get("1"), cloned.get("1")); + } + /** * A crafted stream can carry a load factor the constructor rejects. AbstractHashedMap.doReadObject * must reapply that contract on read. @@ -131,16 +141,6 @@ public class LinkedMapTest<K, V> extends AbstractOrderedMapTest<K, V> { assertThrows(InvalidObjectException.class, () -> serializeDeserialize(map)); } - @Test - @SuppressWarnings("unchecked") - void testClone() { - final LinkedMap<K, V> map = new LinkedMap<>(10); - map.put((K) "1", (V) "1"); - final Map<K, V> cloned = map.clone(); - assertEquals(map.size(), cloned.size()); - assertSame(map.get("1"), cloned.get("1")); - } - @Test void testGetByIndex() { resetEmpty(); diff --git a/src/test/java/org/apache/commons/collections4/map/ListOrderedMapTest.java b/src/test/java/org/apache/commons/collections4/map/ListOrderedMapTest.java index 13b05ef5a..4f2c21dd3 100644 --- a/src/test/java/org/apache/commons/collections4/map/ListOrderedMapTest.java +++ b/src/test/java/org/apache/commons/collections4/map/ListOrderedMapTest.java @@ -167,16 +167,6 @@ public class ListOrderedMapTest<K, V> extends AbstractOrderedMapTest<K, V> { return ListOrderedMap.listOrderedMap(new HashMap<>()); } - @Test - void testDeserializeRejectsKeyOrderMismatch() throws Exception { - final ListOrderedMap<String, String> map = new ListOrderedMap<>(); - map.put("one", "1"); - map.put("two", "2"); - // drop a key straight from the backing map; the insert-order list still names it - map.decorated().remove("one"); - assertThrows(InvalidObjectException.class, () -> serializeDeserialize(map)); - } - @Test void testCOLLECTIONS_474_nonNullValues() { final Object key1 = new Object(); @@ -207,6 +197,16 @@ public class ListOrderedMapTest<K, V> extends AbstractOrderedMapTest<K, V> { listMap.putAll(2, hmap); } + @Test + void testDeserializeRejectsKeyOrderMismatch() throws Exception { + final ListOrderedMap<String, String> map = new ListOrderedMap<>(); + map.put("one", "1"); + map.put("two", "2"); + // drop a key straight from the backing map; the insert-order list still names it + map.decorated().remove("one"); + assertThrows(InvalidObjectException.class, () -> serializeDeserialize(map)); + } + @Test void testGetByIndex() { resetEmpty(); diff --git a/src/test/java/org/apache/commons/collections4/map/ReferenceIdentityMapTest.java b/src/test/java/org/apache/commons/collections4/map/ReferenceIdentityMapTest.java index 41b7789e9..1bbce8ab9 100644 --- a/src/test/java/org/apache/commons/collections4/map/ReferenceIdentityMapTest.java +++ b/src/test/java/org/apache/commons/collections4/map/ReferenceIdentityMapTest.java @@ -238,18 +238,6 @@ public class ReferenceIdentityMapTest<K, V> extends AbstractIterableMapTest<K, V return new ReferenceIdentityMap<>(ReferenceStrength.WEAK, ReferenceStrength.WEAK); } - /** - * A crafted stream can carry a load factor the constructor rejects. AbstractReferenceMap.doReadObject - * (its own override) must reapply that contract on read. - */ - @ParameterizedTest - @ValueSource(floats = {0.0f, -1.0f, Float.NaN}) - void testDeserializeRejectsInvalidLoadFactor(final float badLoadFactor) { - final ReferenceIdentityMap<K, V> map = new ReferenceIdentityMap<>(); - map.loadFactor = badLoadFactor; - assertThrows(InvalidObjectException.class, () -> serializeDeserialize(map)); - } - @Test @SuppressWarnings("unchecked") void testBasics() { @@ -284,6 +272,18 @@ public class ReferenceIdentityMapTest<K, V> extends AbstractIterableMapTest<K, V assertTrue(map.containsValue(I2B)); } + /** + * A crafted stream can carry a load factor the constructor rejects. AbstractReferenceMap.doReadObject + * (its own override) must reapply that contract on read. + */ + @ParameterizedTest + @ValueSource(floats = {0.0f, -1.0f, Float.NaN}) + void testDeserializeRejectsInvalidLoadFactor(final float badLoadFactor) { + final ReferenceIdentityMap<K, V> map = new ReferenceIdentityMap<>(); + map.loadFactor = badLoadFactor; + assertThrows(InvalidObjectException.class, () -> serializeDeserialize(map)); + } + @Test @SuppressWarnings("unchecked") void testHashEntry() { diff --git a/src/test/java/org/apache/commons/collections4/multimap/AbstractMultiValuedMapTest.java b/src/test/java/org/apache/commons/collections4/multimap/AbstractMultiValuedMapTest.java index 78396b26d..aaade2bcf 100644 --- a/src/test/java/org/apache/commons/collections4/multimap/AbstractMultiValuedMapTest.java +++ b/src/test/java/org/apache/commons/collections4/multimap/AbstractMultiValuedMapTest.java @@ -1279,24 +1279,6 @@ public abstract class AbstractMultiValuedMapTest<K, V> extends AbstractObjectTes assertEquals(getSampleTotalValueCount(), makeFullMap().size()); } - @Test - void testSizeClampsToIntegerMaxValue() { - // bag-valued map: value collection sizes are counts, so the total is cheap to grow past Integer.MAX_VALUE - final AbstractMultiValuedMap<String, String> map = new AbstractMultiValuedMap<String, String>(new HashMap<>()) { - - @Override - protected Collection<String> createCollection() { - return new HashBag<>(); - } - }; - map.put("k1", "v1"); - map.put("k2", "v2"); - ((HashBag<String>) map.getMap().get("k1")).add("v1", Integer.MAX_VALUE - 1); - ((HashBag<String>) map.getMap().get("k2")).add("v2", Integer.MAX_VALUE - 1); - ((HashBag<String>) map.getMap().get("k1")).add("v1", Integer.MAX_VALUE - 1); - assertEquals(Integer.MAX_VALUE, map.size()); - } - @Test @SuppressWarnings("unchecked") void testSize_Key() { @@ -1331,6 +1313,24 @@ public abstract class AbstractMultiValuedMapTest<K, V> extends AbstractObjectTes assertEquals(2, map.get((K) "B").size()); } + @Test + void testSizeClampsToIntegerMaxValue() { + // bag-valued map: value collection sizes are counts, so the total is cheap to grow past Integer.MAX_VALUE + final AbstractMultiValuedMap<String, String> map = new AbstractMultiValuedMap<String, String>(new HashMap<>()) { + + @Override + protected Collection<String> createCollection() { + return new HashBag<>(); + } + }; + map.put("k1", "v1"); + map.put("k2", "v2"); + ((HashBag<String>) map.getMap().get("k1")).add("v1", Integer.MAX_VALUE - 1); + ((HashBag<String>) map.getMap().get("k2")).add("v2", Integer.MAX_VALUE - 1); + ((HashBag<String>) map.getMap().get("k1")).add("v1", Integer.MAX_VALUE - 1); + assertEquals(Integer.MAX_VALUE, map.size()); + } + @Test @SuppressWarnings("unchecked") void testSizeWithPutRemove() { diff --git a/src/test/java/org/apache/commons/collections4/multiset/AbstractMultiSetTest.java b/src/test/java/org/apache/commons/collections4/multiset/AbstractMultiSetTest.java index 9b671a825..39b65b181 100644 --- a/src/test/java/org/apache/commons/collections4/multiset/AbstractMultiSetTest.java +++ b/src/test/java/org/apache/commons/collections4/multiset/AbstractMultiSetTest.java @@ -131,6 +131,21 @@ public abstract class AbstractMultiSetTest<T> extends AbstractCollectionTest<T> } } + private static MultiSet.Entry<String> maxCountEntry(final String element) { + return new AbstractMultiSet.AbstractEntry<String>() { + + @Override + public int getCount() { + return Integer.MAX_VALUE; + } + + @Override + public String getElement() { + return element; + } + }; + } + /** * Bulk test {@link MultiSet#uniqueSet()}. This method runs through all of * the tests in {@link AbstractSetTest}. @@ -568,34 +583,6 @@ public abstract class AbstractMultiSetTest<T> extends AbstractCollectionTest<T> assertFalse(it2.hasNext()); } - @Test - @SuppressWarnings("unchecked") - void testMultiSetViewIteratorRemoveKeepsSizeConsistent() { - if (!isRemoveSupported()) { - return; - } - // removing through uniqueSet()/entrySet() drops the whole entry, so - // size() must fall by that entry's count and the views stay consistent - final MultiSet<T> multiset = makeObject(); - multiset.add((T) "A", 3); - multiset.add((T) "B", 2); - final Iterator<T> unique = multiset.uniqueSet().iterator(); - final T removed = unique.next(); - final int removedCount = multiset.getCount(removed); - unique.remove(); - assertThrows(IllegalStateException.class, unique::remove); - assertEquals(5 - removedCount, multiset.size()); - assertFalse(multiset.contains(removed)); - assertEquals(multiset.size(), multiset.toArray().length); - final Iterator<MultiSet.Entry<T>> entries = multiset.entrySet().iterator(); - entries.next(); - entries.remove(); - assertThrows(IllegalStateException.class, unique::remove); - assertEquals(0, multiset.size()); - assertTrue(multiset.isEmpty()); - assertEquals(0, multiset.toArray().length); - } - @Test @SuppressWarnings("unchecked") void testMultiSetRemove() { @@ -709,21 +696,6 @@ public abstract class AbstractMultiSetTest<T> extends AbstractCollectionTest<T> assertEquals(Integer.MAX_VALUE, multiset.size()); } - private static MultiSet.Entry<String> maxCountEntry(final String element) { - return new AbstractMultiSet.AbstractEntry<String>() { - - @Override - public int getCount() { - return Integer.MAX_VALUE; - } - - @Override - public String getElement() { - return element; - } - }; - } - @Test @SuppressWarnings("unchecked") void testMultiSetToArray() { @@ -778,4 +750,32 @@ public abstract class AbstractMultiSetTest<T> extends AbstractCollectionTest<T> assertEquals(1, c); } + @Test + @SuppressWarnings("unchecked") + void testMultiSetViewIteratorRemoveKeepsSizeConsistent() { + if (!isRemoveSupported()) { + return; + } + // removing through uniqueSet()/entrySet() drops the whole entry, so + // size() must fall by that entry's count and the views stay consistent + final MultiSet<T> multiset = makeObject(); + multiset.add((T) "A", 3); + multiset.add((T) "B", 2); + final Iterator<T> unique = multiset.uniqueSet().iterator(); + final T removed = unique.next(); + final int removedCount = multiset.getCount(removed); + unique.remove(); + assertThrows(IllegalStateException.class, unique::remove); + assertEquals(5 - removedCount, multiset.size()); + assertFalse(multiset.contains(removed)); + assertEquals(multiset.size(), multiset.toArray().length); + final Iterator<MultiSet.Entry<T>> entries = multiset.entrySet().iterator(); + entries.next(); + entries.remove(); + assertThrows(IllegalStateException.class, unique::remove); + assertEquals(0, multiset.size()); + assertTrue(multiset.isEmpty()); + assertEquals(0, multiset.toArray().length); + } + } diff --git a/src/test/java/org/apache/commons/collections4/multiset/HashMultiSetTest.java b/src/test/java/org/apache/commons/collections4/multiset/HashMultiSetTest.java index da57c20f8..399d147b6 100644 --- a/src/test/java/org/apache/commons/collections4/multiset/HashMultiSetTest.java +++ b/src/test/java/org/apache/commons/collections4/multiset/HashMultiSetTest.java @@ -46,6 +46,24 @@ public class HashMultiSetTest<T> extends AbstractMultiSetTest<T> { return new HashMultiSet<>(); } + @Test + void testAddClampsCountAndSizeToIntegerMaxValue() { + final HashMultiSet<String> set = new HashMultiSet<>(); + set.add("X", Integer.MAX_VALUE); + set.add("X", 1); + assertEquals(Integer.MAX_VALUE, set.getCount("X")); + assertEquals(Integer.MAX_VALUE, set.size()); + set.add("Y", Integer.MAX_VALUE); + assertEquals(Integer.MAX_VALUE, set.size()); + // true size is 2 * Integer.MAX_VALUE - 2 after this, so size() must stay saturated + set.remove("X", 2); + assertEquals(Integer.MAX_VALUE - 2, set.getCount("X")); + assertEquals(Integer.MAX_VALUE, set.size()); + // size() only drops below Integer.MAX_VALUE once the true size does + set.remove("Y", Integer.MAX_VALUE); + assertEquals(Integer.MAX_VALUE - 2, set.size()); + } + @Test void testConstructorFromIterable() { final Iterable<String> iterable = () -> Arrays.asList("a", "b", "a").iterator(); @@ -68,24 +86,6 @@ public class HashMultiSetTest<T> extends AbstractMultiSetTest<T> { } } - @Test - void testAddClampsCountAndSizeToIntegerMaxValue() { - final HashMultiSet<String> set = new HashMultiSet<>(); - set.add("X", Integer.MAX_VALUE); - set.add("X", 1); - assertEquals(Integer.MAX_VALUE, set.getCount("X")); - assertEquals(Integer.MAX_VALUE, set.size()); - set.add("Y", Integer.MAX_VALUE); - assertEquals(Integer.MAX_VALUE, set.size()); - // true size is 2 * Integer.MAX_VALUE - 2 after this, so size() must stay saturated - set.remove("X", 2); - assertEquals(Integer.MAX_VALUE - 2, set.getCount("X")); - assertEquals(Integer.MAX_VALUE, set.size()); - // size() only drops below Integer.MAX_VALUE once the true size does - set.remove("Y", Integer.MAX_VALUE); - assertEquals(Integer.MAX_VALUE - 2, set.size()); - } - // void testCreate() throws Exception { // MultiSet<T> multiset = makeObject(); // writeExternalFormToDisk((java.io.Serializable) multiset, "src/test/resources/data/test/HashMultiSet.emptyCollection.version4.1.obj"); diff --git a/src/test/java/org/apache/commons/collections4/multiset/TreeMultiSetTest.java b/src/test/java/org/apache/commons/collections4/multiset/TreeMultiSetTest.java index 79fcaf834..e33ff6c4b 100644 --- a/src/test/java/org/apache/commons/collections4/multiset/TreeMultiSetTest.java +++ b/src/test/java/org/apache/commons/collections4/multiset/TreeMultiSetTest.java @@ -52,16 +52,6 @@ public class TreeMultiSetTest<T> extends AbstractSortedMultiSetTest<T> { return multiset; } - @Test - void testConstructorFromIterable() { - final Iterable<String> iterable = () -> Arrays.asList("b", "a", "b").iterator(); - final SortedMultiSet<String> multiset = new TreeMultiSet<>(iterable); - assertEquals(3, multiset.size()); - assertEquals(2, multiset.getCount("b")); - assertEquals("a", multiset.first()); - assertEquals("b", multiset.last()); - } - @Test void testAddNonComparable() { final MultiSet<Object> multiset = new TreeMultiSet<>(); @@ -92,6 +82,16 @@ public class TreeMultiSetTest<T> extends AbstractSortedMultiSetTest<T> { assertEquals(String.CASE_INSENSITIVE_ORDER, multiset2.comparator()); } + @Test + void testConstructorFromIterable() { + final Iterable<String> iterable = () -> Arrays.asList("b", "a", "b").iterator(); + final SortedMultiSet<String> multiset = new TreeMultiSet<>(iterable); + assertEquals(3, multiset.size()); + assertEquals(2, multiset.getCount("b")); + assertEquals("a", multiset.first()); + assertEquals("b", multiset.last()); + } + @Test void testOrdering() { final SortedMultiSet<T> multiset = setupMultiSet(); diff --git a/src/test/java/org/apache/commons/collections4/properties/OrderedPropertiesTest.java b/src/test/java/org/apache/commons/collections4/properties/OrderedPropertiesTest.java index 816387625..20b936a02 100644 --- a/src/test/java/org/apache/commons/collections4/properties/OrderedPropertiesTest.java +++ b/src/test/java/org/apache/commons/collections4/properties/OrderedPropertiesTest.java @@ -119,20 +119,6 @@ class OrderedPropertiesTest { assertDescendingOrder(orderedProperties); } - @Test - void testComputeToNullRemovesKey() { - final OrderedProperties orderedProperties = new OrderedProperties(); - orderedProperties.put("a", "1"); - orderedProperties.put("b", "2"); - // A remapping to null removes the mapping; the ordered key view must follow. - orderedProperties.compute("a", (k, v) -> null); - assertFalse(orderedProperties.containsKey("a")); - assertFalse(orderedProperties.keySet().contains("a")); - assertEquals(1, orderedProperties.size()); - assertEquals("[b]", orderedProperties.keySet().toString()); - assertEquals("{b=2}", orderedProperties.toString()); - } - @Test void testComputeIfAbsent() { final OrderedProperties orderedProperties = new OrderedProperties(); @@ -153,6 +139,20 @@ class OrderedPropertiesTest { assertDescendingOrder(orderedProperties); } + @Test + void testComputeToNullRemovesKey() { + final OrderedProperties orderedProperties = new OrderedProperties(); + orderedProperties.put("a", "1"); + orderedProperties.put("b", "2"); + // A remapping to null removes the mapping; the ordered key view must follow. + orderedProperties.compute("a", (k, v) -> null); + assertFalse(orderedProperties.containsKey("a")); + assertFalse(orderedProperties.keySet().contains("a")); + assertEquals(1, orderedProperties.size()); + assertEquals("[b]", orderedProperties.keySet().toString()); + assertEquals("{b=2}", orderedProperties.toString()); + } + @Test void testEntrySet() { final OrderedProperties orderedProperties = new OrderedProperties(); diff --git a/src/test/java/org/apache/commons/collections4/queue/CircularFifoQueueTest.java b/src/test/java/org/apache/commons/collections4/queue/CircularFifoQueueTest.java index d71850ea8..70e77a5e8 100644 --- a/src/test/java/org/apache/commons/collections4/queue/CircularFifoQueueTest.java +++ b/src/test/java/org/apache/commons/collections4/queue/CircularFifoQueueTest.java @@ -37,6 +37,24 @@ import org.junit.jupiter.api.Test; */ public class CircularFifoQueueTest<E> extends AbstractQueueTest<E> { + private static int indexOfInt(final byte[] data, final int value) { + final byte[] needle = {(byte) (value >>> 24), (byte) (value >>> 16), (byte) (value >>> 8), (byte) value}; + for (int i = 0; i <= data.length - 4; i++) { + if (data[i] == needle[0] && data[i + 1] == needle[1] + && data[i + 2] == needle[2] && data[i + 3] == needle[3]) { + return i; + } + } + throw new IllegalStateException("value not found in stream"); + } + + private static void patchInt(final byte[] data, final int pos, final int value) { + data[pos] = (byte) (value >>> 24); + data[pos + 1] = (byte) (value >>> 16); + data[pos + 2] = (byte) (value >>> 8); + data[pos + 3] = (byte) value; + } + /** * {@inheritDoc} */ @@ -203,6 +221,28 @@ public class CircularFifoQueueTest<E> extends AbstractQueueTest<E> { assertThrows(NoSuchElementException.class, () -> fifo.get(-2)); } + @Test + @SuppressWarnings("unchecked") + void testDeserializeRejectsCorruptSize() throws Exception { + // a stored size larger than maxElements would write past the backing array + final CircularFifoQueue<E> full = new CircularFifoQueue<>(7); + for (int i = 0; i < 7; i++) { + full.add((E) ("x" + i)); + } + final byte[] tooLarge = serialize(full); + // first 0x00000007 is maxElements; shrink it so size (7) now exceeds it + patchInt(tooLarge, indexOfInt(tooLarge, 7), 2); + assertThrows(InvalidObjectException.class, () -> deserialize(tooLarge)); + + // a negative stored size leaves the queue in an inconsistent state + final CircularFifoQueue<E> partial = new CircularFifoQueue<>(7); + partial.add((E) "a"); + partial.add((E) "b"); + final byte[] negative = serialize(partial); + patchInt(negative, indexOfInt(negative, 2), -1); + assertThrows(InvalidObjectException.class, () -> deserialize(negative)); + } + @Test void testGetIndex() { resetFull(); @@ -429,46 +469,6 @@ public class CircularFifoQueueTest<E> extends AbstractQueueTest<E> { assertTrue(b3.contains("c")); } - @Test - @SuppressWarnings("unchecked") - void testDeserializeRejectsCorruptSize() throws Exception { - // a stored size larger than maxElements would write past the backing array - final CircularFifoQueue<E> full = new CircularFifoQueue<>(7); - for (int i = 0; i < 7; i++) { - full.add((E) ("x" + i)); - } - final byte[] tooLarge = serialize(full); - // first 0x00000007 is maxElements; shrink it so size (7) now exceeds it - patchInt(tooLarge, indexOfInt(tooLarge, 7), 2); - assertThrows(InvalidObjectException.class, () -> deserialize(tooLarge)); - - // a negative stored size leaves the queue in an inconsistent state - final CircularFifoQueue<E> partial = new CircularFifoQueue<>(7); - partial.add((E) "a"); - partial.add((E) "b"); - final byte[] negative = serialize(partial); - patchInt(negative, indexOfInt(negative, 2), -1); - assertThrows(InvalidObjectException.class, () -> deserialize(negative)); - } - - private static int indexOfInt(final byte[] data, final int value) { - final byte[] needle = {(byte) (value >>> 24), (byte) (value >>> 16), (byte) (value >>> 8), (byte) value}; - for (int i = 0; i <= data.length - 4; i++) { - if (data[i] == needle[0] && data[i + 1] == needle[1] - && data[i + 2] == needle[2] && data[i + 3] == needle[3]) { - return i; - } - } - throw new IllegalStateException("value not found in stream"); - } - - private static void patchInt(final byte[] data, final int pos, final int value) { - data[pos] = (byte) (value >>> 24); - data[pos + 1] = (byte) (value >>> 16); - data[pos + 2] = (byte) (value >>> 8); - data[pos + 3] = (byte) value; - } - // void testCreate() throws Exception { // resetEmpty(); // writeExternalFormToDisk((java.io.Serializable) getCollection(), "src/test/resources/data/test/CircularFifoQueue.emptyCollection.version4.obj"); diff --git a/src/test/java/org/apache/commons/collections4/set/CompositeSetTest.java b/src/test/java/org/apache/commons/collections4/set/CompositeSetTest.java index 0a497bb2d..5616d56ca 100644 --- a/src/test/java/org/apache/commons/collections4/set/CompositeSetTest.java +++ b/src/test/java/org/apache/commons/collections4/set/CompositeSetTest.java @@ -38,6 +38,22 @@ import org.junit.jupiter.api.Test; */ public class CompositeSetTest<E> extends AbstractSetTest<E> { + /** An empty-iterating set that reports {@code Integer.MAX_VALUE} elements. */ + private static Set<String> maxSizeSet() { + return new AbstractSet<String>() { + + @Override + public Iterator<String> iterator() { + return Collections.emptyIterator(); + } + + @Override + public int size() { + return Integer.MAX_VALUE; + } + }; + } + @SuppressWarnings("unchecked") public Set<E> buildOne() { final HashSet<E> set = new HashSet<>(); @@ -183,29 +199,6 @@ public class CompositeSetTest<E> extends AbstractSetTest<E> { assertFalse(one.contains("3")); } - @Test - void testSizeClampsToIntegerMaxValue() { - final CompositeSet<String> set = new CompositeSet<>(maxSizeSet()); - set.addComposited(maxSizeSet()); - assertEquals(Integer.MAX_VALUE, set.size()); - } - - /** An empty-iterating set that reports {@code Integer.MAX_VALUE} elements. */ - private static Set<String> maxSizeSet() { - return new AbstractSet<String>() { - - @Override - public Iterator<String> iterator() { - return Collections.emptyIterator(); - } - - @Override - public int size() { - return Integer.MAX_VALUE; - } - }; - } - @Test @SuppressWarnings("unchecked") void testRemoveUnderlying() { @@ -219,6 +212,13 @@ public class CompositeSetTest<E> extends AbstractSetTest<E> { assertFalse(set.contains("3")); } + @Test + void testSizeClampsToIntegerMaxValue() { + final CompositeSet<String> set = new CompositeSet<>(maxSizeSet()); + set.addComposited(maxSizeSet()); + assertEquals(Integer.MAX_VALUE, set.size()); + } + // void testCreate() throws Exception { // resetEmpty(); // writeExternalFormToDisk((java.io.Serializable) getCollection(), "src/test/resources/data/test/CompositeSet.emptyCollection.version4.obj"); diff --git a/src/test/java/org/apache/commons/collections4/set/ListOrderedSetTest.java b/src/test/java/org/apache/commons/collections4/set/ListOrderedSetTest.java index 7794af1bd..95553f8ac 100644 --- a/src/test/java/org/apache/commons/collections4/set/ListOrderedSetTest.java +++ b/src/test/java/org/apache/commons/collections4/set/ListOrderedSetTest.java @@ -93,6 +93,15 @@ public class ListOrderedSetTest<E> return set; } + @Test + void testDecorator() { + assertThrows(NullPointerException.class, () -> ListOrderedSet.listOrderedSet((List<E>) null)); + assertThrows(NullPointerException.class, () -> ListOrderedSet.listOrderedSet((Set<E>) null)); + assertThrows(NullPointerException.class, () -> ListOrderedSet.listOrderedSet(null, null)); + assertThrows(NullPointerException.class, () -> ListOrderedSet.listOrderedSet(new HashSet<>(), null)); + assertThrows(NullPointerException.class, () -> ListOrderedSet.listOrderedSet(null, new ArrayList<>())); + } + @Test void testDeserializeRejectsOrderMismatch() throws Exception { final ListOrderedSet<String> set = ListOrderedSet.listOrderedSet(new HashSet<>()); @@ -103,15 +112,6 @@ public class ListOrderedSetTest<E> assertThrows(InvalidObjectException.class, () -> serializeDeserialize(set)); } - @Test - void testDecorator() { - assertThrows(NullPointerException.class, () -> ListOrderedSet.listOrderedSet((List<E>) null)); - assertThrows(NullPointerException.class, () -> ListOrderedSet.listOrderedSet((Set<E>) null)); - assertThrows(NullPointerException.class, () -> ListOrderedSet.listOrderedSet(null, null)); - assertThrows(NullPointerException.class, () -> ListOrderedSet.listOrderedSet(new HashSet<>(), null)); - assertThrows(NullPointerException.class, () -> ListOrderedSet.listOrderedSet(null, new ArrayList<>())); - } - @Test @SuppressWarnings("unchecked") void testDuplicates() {
