diff --git a/test/jdk/jdk/internal/util/ReferencedKeyTest.java b/test/jdk/jdk/internal/util/ReferencedKeyTest.java index 75690fa6e25..c68908a8d5a 100644 --- a/test/jdk/jdk/internal/util/ReferencedKeyTest.java +++ b/test/jdk/jdk/internal/util/ReferencedKeyTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 2024, 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 @@ -23,7 +23,7 @@ /* * @test - * @bug 8285932 8310913 + * @bug 8285932 8310913 8336390 8338060 * @summary Test features provided by the ReferencedKeyMap/ReferencedKeySet classes. * @modules java.base/jdk.internal.util * @compile --patch-module java.base=${test.src} ReferencedKeyTest.java @@ -36,14 +36,27 @@ import java.lang.ref.PhantomReference; import java.lang.ref.Reference; import java.lang.ref.ReferenceQueue; import java.util.HashMap; +import java.util.List; import java.util.Map; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import java.util.function.BooleanSupplier; +import java.util.function.Function; import java.util.function.Supplier; +import java.util.stream.IntStream; public class ReferencedKeyTest { - static long BASE_KEY = 10_000_000L; + private static String BASE_KEY = "BASEKEY-"; + + // Return a String (identity object) that can be a key in WeakHashMap. + private static String genKey(int i) { + return BASE_KEY + i; + } + + // Return a String of the letter 'a' plus the integer (0..0xffff) + private static String genValue(int i) { + return String.valueOf((char) ('a' + i)); + } public static void main(String[] args) { mapTest(false, HashMap::new); @@ -63,73 +76,77 @@ public class ReferencedKeyTest { } } - static void mapTest(boolean isSoft, Supplier, String>> supplier) { - Map map = ReferencedKeyMap.create(isSoft, supplier); - populate(map); + static void mapTest(boolean isSoft, Supplier, String>> supplier) { + Map map = ReferencedKeyMap.create(isSoft, supplier); + var strongKeys = populate(map); // Retain references to the keys + methods(map); + Reference.reachabilityFence(strongKeys); + + strongKeys = null; // drop strong key references if (!isSoft) { if (!collect(() -> map.isEmpty())) { throw new RuntimeException("WeakReference map not collecting!"); } } - populate(map); - methods(map); } - static void setTest(boolean isSoft, Supplier, ReferenceKey>> supplier) { - ReferencedKeySet set = ReferencedKeySet.create(isSoft, supplier); - populate(set); + static void setTest(boolean isSoft, Supplier, ReferenceKey>> supplier) { + ReferencedKeySet set = ReferencedKeySet.create(isSoft, supplier); + var strongKeys = populate(set); // Retain references to the keys + methods(set); + Reference.reachabilityFence(strongKeys); + + strongKeys = null; // drop strong key references if (!isSoft) { if (!collect(() -> set.isEmpty())) { throw new RuntimeException("WeakReference set not collecting!"); } } - populate(set); - methods(set); } - static void methods(Map map) { + static void methods(Map map) { assertTrue(map.size() == 26, "missing key"); - assertTrue(map.containsKey(BASE_KEY + 'a' -'a'), "missing key"); - assertTrue(map.get(BASE_KEY + 'b' -'a').equals("b"), "wrong key"); + assertTrue(map.containsKey(genKey('a' -'a')), "missing key"); + assertTrue(map.get(genKey('b' -'a')).equals("b"), "wrong key"); assertTrue(map.containsValue("c"), "missing value"); - map.remove(BASE_KEY + 'd' -'a'); - assertTrue(map.get(BASE_KEY + 'd' -'a') == null, "not removed"); - map.putAll(Map.of(1L, "A", 2L, "B")); - assertTrue(map.get(2L).equals("B"), "collection not added"); - assertTrue(map.containsKey(1L), "key missing"); + map.remove(genKey('d' -'a')); + assertTrue(map.get(genKey('d' -'a')) == null, "not removed"); + map.putAll(Map.of(genKey(1), "A", genKey(2), "B")); + assertTrue(map.get(genKey(2)).equals("B"), "collection not added"); + assertTrue(map.containsKey(genKey(1)), "key missing"); assertTrue(map.containsValue("A"), "key missing"); - assertTrue(map.entrySet().contains(Map.entry(1L, "A")), "key missing"); - map.putIfAbsent(3L, "C"); - assertTrue(map.get(3L).equals("C"), "key missing"); - map.putIfAbsent(2L, "D"); - assertTrue(map.get(2L).equals("B"), "key replaced"); - map.remove(3L); - assertTrue(map.get(3L) == null, "key not removed"); - map.replace(2L, "D"); - assertTrue(map.get(2L).equals("D"), "key not replaced"); - map.replace(2L, "B", "E"); - assertTrue(map.get(2L).equals("D"), "key replaced"); + assertTrue(map.entrySet().contains(Map.entry(genKey(1), "A")), "key missing"); + map.putIfAbsent(genKey(3), "C"); + assertTrue(map.get(genKey(3)).equals("C"), "key missing"); + map.putIfAbsent(genKey(2), "D"); + assertTrue(map.get(genKey(2)).equals("B"), "key replaced"); + map.remove(genKey(3)); + assertTrue(map.get(genKey(3)) == null, "key not removed"); + map.replace(genKey(2), "D"); + assertTrue(map.get(genKey(2)).equals("D"), "key not replaced"); + map.replace(genKey(2), "B", "E"); + assertTrue(map.get(genKey(2)).equals("D"), "key replaced"); } - static void methods(ReferencedKeySet set) { + static void methods(ReferencedKeySet set) { assertTrue(set.size() == 26, "missing key"); - assertTrue(set.contains(BASE_KEY + 3), "missing key"); - set.remove(BASE_KEY + 3); - assertTrue(!set.contains(BASE_KEY + 3), "not removed"); - Long element1 = set.get(BASE_KEY + 2); - Long element2 = set.get(BASE_KEY + 3); - Long element3 = set.get(BASE_KEY + 4); - Long intern1 = set.intern(BASE_KEY + 2); - Long intern2 = set.intern(BASE_KEY + 3); - Long intern3 = set.intern(BASE_KEY + 4, e -> e); + assertTrue(set.contains(genKey(3)), "missing key"); + set.remove(genKey(3)); + assertTrue(!set.contains(genKey(3)), "not removed"); + String element1 = set.get(genKey(2)); + String element2 = set.get(genKey(3)); + String element3 = set.get(genKey(4)); + String intern1 = set.intern(genKey(2)); + String intern2 = set.intern(genKey(3)); + String intern3 = set.intern(genKey(4), e -> e); assertTrue(element1 != null, "missing key"); assertTrue(element2 == null, "not removed"); assertTrue(element1 == intern1, "intern failed"); // must be same object assertTrue(intern2 != null, "intern failed"); assertTrue(element3 == intern3, "intern failed"); - Long value1 = Long.valueOf(BASE_KEY + 999); - Long value2 = Long.valueOf(BASE_KEY + 999); + String value1 = genKey(999); + String value2 = genKey(999); assertTrue(set.add(value1), "key not added"); assertTrue(!set.add(value1), "key added after second attempt"); assertTrue(!set.add(value2), "key should not have been added"); @@ -164,18 +181,23 @@ public class ReferencedKeyTest { return booleanSupplier.getAsBoolean(); } - static void populate(Map map) { - for (int i = 0; i < 26; i++) { - Long key = BASE_KEY + i; - String value = String.valueOf((char) ('a' + i)); - map.put(key, value); + static List populate(Map map) { + var keyRefs = genStrings(0, 26, ReferencedKeyTest::genKey); + var valueRefs = genStrings(0, 26, ReferencedKeyTest::genValue); + for (int i = 0; i < keyRefs.size(); i++) { + map.put(keyRefs.get(i), valueRefs.get(i)); } + return keyRefs; } - static void populate(Set set) { - for (int i = 0; i < 26; i++) { - Long value = BASE_KEY + i; - set.add(value); - } + static List populate(Set set) { + var keyRefs = genStrings(0, 26, ReferencedKeyTest::genKey); + set.addAll(keyRefs); + return keyRefs; + } + + // Generate a List of consecutive strings using a function int -> String + static List genStrings(int min, int maxExclusive, Function genString) { + return IntStream.range(min, maxExclusive).mapToObj(i -> genString.apply(i)).toList(); } }