diff --git a/test/jdk/TEST.groups b/test/jdk/TEST.groups index 4ab277dd0f7..0e3d9f4e6d5 100644 --- a/test/jdk/TEST.groups +++ b/test/jdk/TEST.groups @@ -173,9 +173,14 @@ jdk_util = \ :jdk_stream valhalla_adopted = \ - java/util/Collections/AddAll.java \ java/util/Arrays \ - java/util/Collections + java/util/Collections \ + java/util/HashMap \ + java/util/HashSet \ + java/util/Hashtable \ + java/util/LinkedHashMap \ + java/util/LinkedHashSet \ + java/util/LinkedList # All util components not part of some other util category jdk_util_other = \ diff --git a/test/jdk/java/util/HashMap/KeySetRemove.java b/test/jdk/java/util/HashMap/KeySetRemove.java index 81f635bc979..c71f8aa96d6 100644 --- a/test/jdk/java/util/HashMap/KeySetRemove.java +++ b/test/jdk/java/util/HashMap/KeySetRemove.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,19 +26,28 @@ * @bug 4286765 * @summary HashMap and TreeMap entrySet().remove(k) spuriously returned * false if the Map previously mapped k to null. + * @library /test/lib */ +import jdk.test.lib.valueclass.VClass; import java.util.HashMap; import java.util.Map; import java.util.TreeMap; public class KeySetRemove { public static void main(String[] args) throws Exception { - Map[] m = {new HashMap(), new TreeMap()}; - for (int i=0; i(), new TreeMap<>() }; + for (int i = 0; i < valueMaps.length; i++) { + valueMaps[i].put(new VClass(1, new int[] { 1 }), null); + if (!valueMaps[i].keySet().remove(new VClass(1, new int[] { 1 }))) + throw new Exception("Value banana was not removed: " + i); } } } diff --git a/test/jdk/java/util/HashMap/NullKeyAtResize.java b/test/jdk/java/util/HashMap/NullKeyAtResize.java index 6166fa8ecd4..86a29182114 100644 --- a/test/jdk/java/util/HashMap/NullKeyAtResize.java +++ b/test/jdk/java/util/HashMap/NullKeyAtResize.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,19 +27,27 @@ * @summary If the key to be inserted into a HashMap is null and the table * needs to be resized as part of the insertion then addEntry will try to * recalculate the hash of a null key. This will fail with an NPE. + * @library /test/lib */ +import jdk.test.lib.valueclass.VClass; import java.util.*; +import java.util.function.IntFunction; public class NullKeyAtResize { public static void main(String[] args) throws Exception { + test(Integer::valueOf); + test(i -> new VClass(i, new int[] { i })); + } + + private static void test(IntFunction keyFactory) throws Exception { List old_order = new ArrayList<>(); Map m = new HashMap<>(16); int number = 0; while(number < 100000) { m.put(null,null); // try to put in null. This may cause resize. m.remove(null); // remove it. - Integer adding = (number += 100); + Object adding = keyFactory.apply(number += 100); m.put(adding, null); // try to put in a number. This wont cause resize. List new_order = new ArrayList<>(); new_order.addAll(m.keySet()); diff --git a/test/jdk/java/util/HashMap/PutNullKey.java b/test/jdk/java/util/HashMap/PutNullKey.java index 72aade00186..8a0a07d2c78 100644 --- a/test/jdk/java/util/HashMap/PutNullKey.java +++ b/test/jdk/java/util/HashMap/PutNullKey.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,8 +26,10 @@ * @bug 8046085 * @summary Ensure that when trees are being used for collisions that null key * insertion still works. + * @library /test/lib */ +import jdk.test.lib.valueclass.AsValueClass; import java.util.*; import java.util.stream.IntStream; @@ -78,7 +80,46 @@ public int compareTo(CollidingHash o) { } } + @AsValueClass + public static class CollidingHashValue implements Comparable { + + private final int value; + + public CollidingHashValue(int value) { + this.value = value; + } + + @Override + public int hashCode() { + // intentionally bad hashcode. Force into first bin. + return 0; + } + + @Override + public boolean equals(Object o) { + if (null == o) { + return false; + } + + if (o.getClass() != CollidingHashValue.class) { + return false; + } + + return value == ((CollidingHashValue) o).value; + } + + @Override + public int compareTo(CollidingHashValue o) { + return value - o.value; + } + } + public static void main(String[] args) throws Exception { + testCollidingHash(); + testCollidingHashValue(); + } + + private static void testCollidingHash() { Map m = new HashMap<>(INITIAL_CAPACITY, LOAD_FACTOR); IntStream.range(0, SIZE) .mapToObj(CollidingHash::new) @@ -87,4 +128,14 @@ public static void main(String[] args) throws Exception { // kaboom? m.put(null, null); } + + private static void testCollidingHashValue() { + Map m = new HashMap<>(INITIAL_CAPACITY, LOAD_FACTOR); + IntStream.range(0, SIZE) + .mapToObj(CollidingHashValue::new) + .forEach(e -> { m.put(e, e); }); + + // kaboom? + m.put(null, null); + } } diff --git a/test/jdk/java/util/HashMap/ReplaceExisting.java b/test/jdk/java/util/HashMap/ReplaceExisting.java index 81795b30b1f..4bc1f80b1d1 100644 --- a/test/jdk/java/util/HashMap/ReplaceExisting.java +++ b/test/jdk/java/util/HashMap/ReplaceExisting.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,9 +27,11 @@ * @summary Verify that replacing the value for an existing key does not * corrupt active iterators, in particular due to a resize() occurring and * not updating modCount. + * @library /test/lib * @run main ReplaceExisting */ +import jdk.test.lib.valueclass.VClass; import java.util.ConcurrentModificationException; import java.util.HashMap; import java.util.HashSet; @@ -43,6 +45,8 @@ public static void main(String[] args) { for (int i = 0; i <= ENTRIES; i++) { HashMap hm = prepHashMap(); testItr(hm, i); + HashMap tupleHm = prepTupleHashMap(); + testTupleItr(tupleHm, i); } } @@ -56,6 +60,15 @@ private static HashMap prepHashMap() { return hm; } + private static HashMap prepTupleHashMap() { + HashMap hm = new HashMap<>(16, 0.75f); + // Add items to one more than the resize threshold + for (int i = 0; i < ENTRIES; i++) { + hm.put(new VClass(i * 10, new int[] { i * 10 }), i * 10); + } + return hm; + } + /* Iterate hm for elemBeforePut elements, then call put() to replace value * for existing key. With bug 8025173, this will also cause a resize, but * not increase the modCount. @@ -98,4 +111,42 @@ private static void testItr(HashMap hm, int elemBeforePut) { throw new RuntimeException("Collected keys do not match original set of keys"); } } + + private static void testTupleItr(HashMap hm, int elemBeforePut) { + if (elemBeforePut > hm.size()) { + throw new IllegalArgumentException("Error in test: elemBeforePut must be <= HashMap size"); + } + // Create a copy of the keys + HashSet keys = new HashSet<>(hm.size()); + keys.addAll(hm.keySet()); + + HashSet collected = new HashSet<>(hm.size()); + + // Run itr for elemBeforePut items, collecting returned elems + Iterator itr = hm.keySet().iterator(); + for (int i = 0; i < elemBeforePut; i++) { + VClass retVal = itr.next(); + if (!collected.add(retVal)) { + throw new RuntimeException("Corrupt iterator: key " + retVal + " already encountered"); + } + } + + // Do put() to replace entry (and resize table when bug present) + if (null == hm.put(new VClass(0, new int[] { 0 }), 100)) { + throw new RuntimeException("Error in test: expected key (0, 0) to be in the HashMap"); + } + + // Finish itr + collecting returned elems + while(itr.hasNext()) { + VClass retVal = itr.next(); + if (!collected.add(retVal)) { + throw new RuntimeException("Corrupt iterator: key " + retVal + " already encountered"); + } + } + + // Compare returned elems to original copy of keys + if (!keys.equals(collected)) { + throw new RuntimeException("Collected keys do not match original set of keys"); + } + } } diff --git a/test/jdk/java/util/HashMap/SetValue.java b/test/jdk/java/util/HashMap/SetValue.java index 2f9daf4889c..8271ed2a0a0 100644 --- a/test/jdk/java/util/HashMap/SetValue.java +++ b/test/jdk/java/util/HashMap/SetValue.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,8 +26,10 @@ * @bug 4627516 * @summary HashMap.Entry.setValue() returns new value (as opposed to old) * @author jbloch + * @library /test/lib */ +import jdk.test.lib.valueclass.VClass; import java.util.HashMap; import java.util.Map; @@ -37,6 +39,11 @@ public class SetValue { static final String newValue = "new"; public static void main(String[] args) throws Exception { + testStringValue(); + testVClass(); + } + + private static void testStringValue() { Map m = new HashMap(); m.put(key, oldValue); Map.Entry e = (Map.Entry) m.entrySet().iterator().next(); @@ -44,4 +51,15 @@ public static void main(String[] args) throws Exception { if (!returnVal.equals(oldValue)) throw new RuntimeException("Return value: " + returnVal); } + + private static void testVClass() { + Map m = new HashMap<>(); + VClass oldValue = new VClass(1, new int[] { 1 }); + VClass newValue = new VClass(2, new int[] { 2 }); + m.put(key, oldValue); + Map.Entry e = m.entrySet().iterator().next(); + Object returnVal = e.setValue(newValue); + if (!returnVal.equals(oldValue)) + throw new RuntimeException("Return value: " + returnVal); + } } diff --git a/test/jdk/java/util/HashMap/ToArray.java b/test/jdk/java/util/HashMap/ToArray.java index b9336dfc4cb..e2c4471de9b 100644 --- a/test/jdk/java/util/HashMap/ToArray.java +++ b/test/jdk/java/util/HashMap/ToArray.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -31,27 +31,26 @@ import java.util.List; import java.util.Map; import java.util.stream.LongStream; +import jdk.test.lib.valueclass.VClass; /* * @test * @bug 8336669 * @summary HashMap.toArray() behavior tests * @author tvaleev + * @library /test/lib */ public class ToArray { - // An interned identity class holding an int (like non-Preview Integer) - record Int(int intValue) implements Comparable { - @Override - public int compareTo(Int o) { - return Integer.compare(intValue, o.intValue); - } - } public static void main(String[] args) { checkMap(false); checkMap(true); checkSet(false); checkSet(true); + checkVClassMap(false); + checkVClassMap(true); + checkVClassSet(false); + checkVClassSet(true); } private static > void checkToArray(String message, T[] expected, Collection collection, @@ -161,4 +160,46 @@ private static void checkSet(boolean ordered) { checkToArray("Collisions", LongStream.range(0, 100).mapToObj(x -> x | (x << 32)) .toArray(Long[]::new), longSet, !ordered); } + + private static void checkVClassMap(boolean ordered) { + Map map = ordered ? new LinkedHashMap<>() : new HashMap<>(); + checkToArray("Empty-tuple-keys", new VClass[0], map.keySet(), !ordered); + checkToArray("Empty-tuple-values", new VClass[0], map.values(), !ordered); + + List keys = new ArrayList<>(); + List values = new ArrayList<>(); + for (int i = 0; i < 100; i++) { + keys.add(new VClass(i, new int[] { i })); + values.add(new VClass(i * 2, new int[] { i * 2 })); + map.put(new VClass(i, new int[] { i }), new VClass(i * 2, new int[] { i * 2 })); + checkToArray(i + "-tuple-keys", keys.toArray(new VClass[0]), map.keySet(), !ordered); + checkToArray(i + "-tuple-values", values.toArray(new VClass[0]), map.values(), !ordered); + } + map.clear(); + checkToArray("Empty-tuple-keys", new VClass[0], map.keySet(), !ordered); + checkToArray("Empty-tuple-values", new VClass[0], map.values(), !ordered); + } + + private static void checkVClassSet(boolean ordered) { + Collection set = ordered ? new LinkedHashSet<>() : new HashSet<>(); + checkToArray("Empty-tuple", new VClass[0], set, !ordered); + set.add(new VClass(1, new int[] { 1 })); + checkToArray("One-tuple", new VClass[]{new VClass(1, new int[] { 1 })}, set, !ordered); + set.add(new VClass(2, new int[] { 2 })); + checkToArray("Two-tuple", new VClass[]{new VClass(1, new int[] { 1 }), new VClass(2, new int[] { 2 })}, set, !ordered); + + Collection tupleSet = ordered ? new LinkedHashSet<>() : new HashSet<>(); + for (int x = 0; x < 100; x++) { + tupleSet.add(new VClass(x, new int[] { x })); + } + checkToArray("100-tuple", LongStream.range(0, 100).mapToObj(x -> new VClass((int) x, new int[] { (int) x })) + .toArray(VClass[]::new), tupleSet, !ordered); + tupleSet.clear(); + checkToArray("After-clear-tuple", new VClass[0], tupleSet, !ordered); + for (int x = 0; x < 100; x++) { + tupleSet.add(new VClass(x, new int[] { -31 * x })); + } + checkToArray("Collisions-tuple", LongStream.range(0, 100).mapToObj(x -> new VClass((int) x, new int[] { -31 * (int) x })) + .toArray(VClass[]::new), tupleSet, !ordered); + } } diff --git a/test/jdk/java/util/HashMap/TreeBinAssert.java b/test/jdk/java/util/HashMap/TreeBinAssert.java index bde93b5ce7c..b310f41c89a 100644 --- a/test/jdk/java/util/HashMap/TreeBinAssert.java +++ b/test/jdk/java/util/HashMap/TreeBinAssert.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,9 +25,11 @@ * @test * @bug 8205399 * @summary Check for AssertionError from HashMap TreeBin after Iterator.remove + * @library /test/lib * @run testng/othervm -esa TreeBinAssert */ +import jdk.test.lib.valueclass.AsValueClass; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; import org.testng.annotations.BeforeTest; @@ -172,4 +174,62 @@ public Key(int desiredHash) { return Integer.compare(this.hash, k.hash); } } + + @AsValueClass + static class KeyVClass implements Comparable { + final int hash; + + public KeyVClass(int desiredHash) { + // Account for processing done by HashMap + this.hash = desiredHash ^ (desiredHash >>> 16); + } + + @Override public int hashCode() { return this.hash; } + + @Override public boolean equals(Object o) { + return o.hashCode() == this.hashCode(); + } + + @Override public int compareTo(KeyVClass k) { + return Integer.compare(this.hash, k.hash); + } + } + + @Test(dataProvider = "SizeAndHashes") + public void testMapVClass(int size, int[] hashes) { + Map map = new HashMap<>(size); + + doTestVClass(map, hashes, + (c,k) -> { ((Map)c).put(k,0); }, + (c) -> { return ((Map)c).keySet().iterator(); } + ); + } + + @Test(dataProvider = "SizeAndHashes") + public void testSetVClass(int size, int[] hashes) { + Set set = new LinkedHashSet<>(size); + + doTestVClass(set, hashes, + (c,k) -> { ((Set)c).add(k); }, + (c) -> { return ((Set)c).iterator(); } + ); + } + + private void doTestVClass(Object collection, int[] hashes, + BiConsumer addKey, + Function> mkItr) { + Iterator itr = null; + for (int h : hashes) { + if (h == ITR_RM) { + if (itr == null) { + itr = mkItr.apply(collection); + } + itr.next(); + itr.remove(); + } else { + itr = null; + addKey.accept(collection, new KeyVClass(h)); + } + } + } } diff --git a/test/jdk/java/util/Hashtable/EqualsCast.java b/test/jdk/java/util/Hashtable/EqualsCast.java index 7451d88473c..5a02268d6c8 100644 --- a/test/jdk/java/util/Hashtable/EqualsCast.java +++ b/test/jdk/java/util/Hashtable/EqualsCast.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,8 +27,11 @@ * @summary Hashtable was less robust to extension that it could have been * because the equals and Hashcode methods used internals * unnecessarily. (java.security.Provider tickled this sensitivity.) + * @library /test/lib */ +import jdk.test.lib.valueclass.VClass; + import java.security.Provider; import java.util.Map; @@ -36,7 +39,9 @@ public class EqualsCast { public static void main(String[] args) throws Exception { Map m1 = new MyProvider("foo", 69, "baz"); Map m2 = new MyProvider("foo", 69, "baz"); - m1.equals(m2); + if (!m1.equals(m2)) { + throw new RuntimeException("Provider maps are not equal"); + } } } @@ -48,6 +53,7 @@ public MyProvider(String name, double version, String info) { super(name, version, info); this.name = name; put("Signature.sigalg", "sigimpl"); + put(new VClass(1, new int[] { 1 }), new VClass(2, new int[] { 2 })); } public String getName() { diff --git a/test/jdk/java/util/Hashtable/SimpleSerialization.java b/test/jdk/java/util/Hashtable/SimpleSerialization.java index deb322cb7fc..5fa0e0beac5 100644 --- a/test/jdk/java/util/Hashtable/SimpleSerialization.java +++ b/test/jdk/java/util/Hashtable/SimpleSerialization.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -43,11 +43,15 @@ public class SimpleSerialization { public static void main(final String[] args) throws Exception { - Hashtable h1 = new Hashtable<>(); - System.err.println("*** BEGIN TEST ***"); - h1.put("key", "value"); + test(new Hashtable(), "key", "value"); + test(new Hashtable(), 1, 2); + } + + private static void test(Hashtable h1, K key, V value) + throws Exception { + h1.put(key, value); final ByteArrayOutputStream baos = new ByteArrayOutputStream(); try (ObjectOutputStream oos = new ObjectOutputStream(baos)) { @@ -66,11 +70,14 @@ public static void main(final String[] args) throws Exception { } if (false == h1.equals(deserializedObject)) { - Hashtable d1 = (Hashtable) h1; - for(Map.Entry entry: h1.entrySet()) { - System.err.println("h1.key::" + entry.getKey() + " d1.containsKey()::" + d1.containsKey((String) entry.getKey())); - System.err.println("h1.value::" + entry.getValue() + " d1.contains()::" + d1.contains(entry.getValue())); - System.err.println("h1.value == d1.value " + entry.getValue().equals(d1.get((String) entry.getKey()))); + Hashtable copy = (Hashtable) deserializedObject; + for (Map.Entry entry : h1.entrySet()) { + System.err.println("h1.key::" + entry.getKey() + + " copy.containsKey()::" + copy.containsKey(entry.getKey())); + System.err.println("h1.value::" + entry.getValue() + + " copy.contains()::" + copy.contains(entry.getValue())); + System.err.println("h1.value equals copy.value " + + entry.getValue().equals(copy.get(entry.getKey()))); } throw new RuntimeException(getFailureText(h1, deserializedObject)); diff --git a/test/jdk/java/util/LinkedHashMap/ComputeIfAbsentAccessOrder.java b/test/jdk/java/util/LinkedHashMap/ComputeIfAbsentAccessOrder.java index 532f2f78512..511e6db60dd 100644 --- a/test/jdk/java/util/LinkedHashMap/ComputeIfAbsentAccessOrder.java +++ b/test/jdk/java/util/LinkedHashMap/ComputeIfAbsentAccessOrder.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -31,6 +31,11 @@ public class ComputeIfAbsentAccessOrder { public static void main(String args[]) throws Throwable { + testStringKeys(); + testIntegerKeys(); + } + + private static void testStringKeys() { LinkedHashMap map = new LinkedHashMap<>(2, 0.75f, true); map.put("first", null); map.put("second", null); @@ -44,4 +49,21 @@ public static void main(String args[]) throws Throwable { throw new RuntimeException("not expected value " + "first" + "!=" + key); } } + + private static void testIntegerKeys() { + LinkedHashMap map = new LinkedHashMap<>(2, 0.75f, true); + Integer first = Integer.valueOf(1996); + Integer second = Integer.valueOf(2026); + map.put(first, null); + map.put(second, null); + + map.computeIfAbsent(first, l -> null); // should do nothing + + Integer key = map.keySet().stream() + .findFirst() + .orElseThrow(() -> new RuntimeException("no value")); + if (!first.equals(key)) { + throw new RuntimeException("not expected value " + first + "!=" + key); + } + } } diff --git a/test/jdk/java/util/LinkedHashMap/EmptyMapIterator.java b/test/jdk/java/util/LinkedHashMap/EmptyMapIterator.java index 8b552f26ff4..a5531a55418 100644 --- a/test/jdk/java/util/LinkedHashMap/EmptyMapIterator.java +++ b/test/jdk/java/util/LinkedHashMap/EmptyMapIterator.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -30,13 +30,29 @@ import java.util.ConcurrentModificationException; import java.util.HashMap; import java.util.Iterator; +import java.util.Map; public class EmptyMapIterator { public static void main(String[] args) throws Exception { + testStringKeys(); + testIntegerKeys(); + } + + private static void testStringKeys() throws Exception { HashMap map = new HashMap(); Iterator iter = map.entrySet().iterator(); map.put("key", "value"); + expectConcurrentModification(iter); + } + + private static void testIntegerKeys() throws Exception { + HashMap map = new HashMap<>(); + Iterator> iter = map.entrySet().iterator(); + map.put(Integer.valueOf(1), Integer.valueOf(2)); + expectConcurrentModification(iter); + } + private static void expectConcurrentModification(Iterator iter) throws Exception { try { iter.next(); throw new Exception("No exception thrown"); diff --git a/test/jdk/java/util/LinkedList/AddAll.java b/test/jdk/java/util/LinkedList/AddAll.java index a7554988178..8d260d30a94 100644 --- a/test/jdk/java/util/LinkedList/AddAll.java +++ b/test/jdk/java/util/LinkedList/AddAll.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 1999, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,8 +25,11 @@ * @test * @bug 4163207 * @summary AddAll was prepending instead of appending! + * @library /test/lib */ +import jdk.test.lib.valueclass.VClass; + import java.util.ArrayList; import java.util.Collections; import java.util.LinkedList; @@ -34,8 +37,13 @@ public class AddAll { public static void main(String[] args) throws Exception { - List head = Collections.nCopies(7, "deadly sin"); - List tail = Collections.nCopies(4, "basic food group"); + testAddAll(Collections.nCopies(7, "deadly sin"), + Collections.nCopies(4, "basic food group")); + testAddAll(Collections.nCopies(7, new VClass(7, new int[] { 1 })), + Collections.nCopies(4, new VClass(4, new int[] { 2 }))); + } + + private static void testAddAll(List head, List tail) { List l1 = new ArrayList(head); List l2 = new LinkedList(head); l1.addAll(tail); diff --git a/test/jdk/java/util/LinkedList/Clone.java b/test/jdk/java/util/LinkedList/Clone.java index 7b8908efbf3..9c376c6b3f8 100644 --- a/test/jdk/java/util/LinkedList/Clone.java +++ b/test/jdk/java/util/LinkedList/Clone.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,53 +27,84 @@ * @summary Cloning a subclass of LinkedList results in an object that isn't * an instance of the subclass. The same applies to TreeSet and * TreeMap. + * @library /test/lib */ +import jdk.test.lib.valueclass.VClass; + import java.util.LinkedList; import java.util.TreeMap; import java.util.TreeSet; public class Clone { public static void main(String[] args) { + testStrings(); + testVClass(); + } + + private static void testStrings() { LinkedList2 l = new LinkedList2(); - LinkedList2 lClone = (LinkedList2) l.clone(); - if (!(l.equals(lClone) && lClone.equals(l))) - throw new RuntimeException("LinkedList.clone() is broken 1."); + checkLinkedListClone(l, "LinkedList.clone() is broken 1."); l.add("a"); - lClone = (LinkedList2) l.clone(); - if (!(l.equals(lClone) && lClone.equals(l))) - throw new RuntimeException("LinkedList.clone() is broken 2."); + checkLinkedListClone(l, "LinkedList.clone() is broken 2."); l.add("b"); - lClone = (LinkedList2) l.clone(); - if (!(l.equals(lClone) && lClone.equals(l))) - throw new RuntimeException("LinkedList.clone() is broken 2."); + checkLinkedListClone(l, "LinkedList.clone() is broken 3."); TreeSet2 s = new TreeSet2(); - TreeSet2 sClone = (TreeSet2) s.clone(); - if (!(s.equals(sClone) && sClone.equals(s))) - throw new RuntimeException("TreeSet.clone() is broken."); + checkTreeSetClone(s, "TreeSet.clone() is broken."); s.add("a"); - sClone = (TreeSet2) s.clone(); - if (!(s.equals(sClone) && sClone.equals(s))) - throw new RuntimeException("TreeSet.clone() is broken."); + checkTreeSetClone(s, "TreeSet.clone() is broken."); s.add("b"); - sClone = (TreeSet2) s.clone(); - if (!(s.equals(sClone) && sClone.equals(s))) - throw new RuntimeException("TreeSet.clone() is broken."); + checkTreeSetClone(s, "TreeSet.clone() is broken."); TreeMap2 m = new TreeMap2(); - TreeMap2 mClone = (TreeMap2) m.clone(); - if (!(m.equals(mClone) && mClone.equals(m))) - throw new RuntimeException("TreeMap.clone() is broken."); + checkTreeMapClone(m, "TreeMap.clone() is broken."); m.put("a", "b"); - mClone = (TreeMap2) m.clone(); - if (!(m.equals(mClone) && mClone.equals(m))) - throw new RuntimeException("TreeMap.clone() is broken."); + checkTreeMapClone(m, "TreeMap.clone() is broken."); m.put("c", "d"); - mClone = (TreeMap2) m.clone(); + checkTreeMapClone(m, "TreeMap.clone() is broken."); + } + + private static void testVClass() { + LinkedList2 l = new LinkedList2(); + checkLinkedListClone(l, "LinkedList.clone() is broken for VClass 1."); + l.add(new VClass(1, new int[] { 0 })); + checkLinkedListClone(l, "LinkedList.clone() is broken for VClass 2."); + l.add(new VClass(2, new int[] { 0 })); + checkLinkedListClone(l, "LinkedList.clone() is broken for VClass 3."); + + TreeSet2 s = new TreeSet2(); + checkTreeSetClone(s, "TreeSet.clone() is broken for VClass 1."); + s.add(new VClass(1, new int[] { 0 })); + checkTreeSetClone(s, "TreeSet.clone() is broken for VClass 2."); + s.add(new VClass(2, new int[] { 0 })); + checkTreeSetClone(s, "TreeSet.clone() is broken for VClass 3."); + + TreeMap2 m = new TreeMap2(); + checkTreeMapClone(m, "TreeMap.clone() is broken for VClass 1."); + m.put(new VClass(1, new int[] { 0 }), new VClass(1, new int[] { 1 })); + checkTreeMapClone(m, "TreeMap.clone() is broken for VClass 2."); + m.put(new VClass(2, new int[] { 0 }), new VClass(2, new int[] { 1 })); + checkTreeMapClone(m, "TreeMap.clone() is broken for VClass 3."); + } + + private static void checkLinkedListClone(LinkedList2 l, String message) { + LinkedList2 lClone = (LinkedList2) l.clone(); + if (!(l.equals(lClone) && lClone.equals(l))) + throw new RuntimeException(message); + } + + private static void checkTreeSetClone(TreeSet2 s, String message) { + TreeSet2 sClone = (TreeSet2) s.clone(); + if (!(s.equals(sClone) && sClone.equals(s))) + throw new RuntimeException(message); + } + + private static void checkTreeMapClone(TreeMap2 m, String message) { + TreeMap2 mClone = (TreeMap2) m.clone(); if (!(m.equals(mClone) && mClone.equals(m))) - throw new RuntimeException("TreeMap.clone() is broken."); + throw new RuntimeException(message); } private static class LinkedList2 extends LinkedList {}