| /* |
| * Copyright (c) 2014, 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 |
| * under the terms of the GNU General Public License version 2 only, as |
| * published by the Free Software Foundation. |
| * |
| * This code is distributed in the hope that it will be useful, but WITHOUT |
| * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
| * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
| * version 2 for more details (a copy is included in the LICENSE file that |
| * accompanied this code). |
| * |
| * You should have received a copy of the GNU General Public License version |
| * 2 along with this work; if not, write to the Free Software Foundation, |
| * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
| * |
| * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
| * or visit www.oracle.com if you need additional information or have any |
| * questions. |
| */ |
| |
| /** |
| * @test |
| * @bug 8048209 |
| * @summary Check that Collections.synchronizedNavigableSet().tailSet() is using |
| * the same lock object as it's source. |
| * @modules java.base/java.util:open |
| * @run testng SyncSubMutexes |
| */ |
| import java.lang.reflect.Field; |
| import java.util.*; |
| import java.util.Set; |
| import java.util.Arrays; |
| |
| import org.testng.annotations.Test; |
| import org.testng.annotations.DataProvider; |
| import static org.testng.Assert.assertSame; |
| |
| public class SyncSubMutexes { |
| |
| @Test(dataProvider = "Collections") |
| public void testCollections(Collection<String> instance) { |
| // nothing to test, no subset methods |
| } |
| |
| @Test(dataProvider = "Lists") |
| public void testLists(List<String> instance) { |
| assertSame(getSyncCollectionMutex(instance.subList(0, 1)), getSyncCollectionMutex(instance)); |
| } |
| |
| @Test(dataProvider = "Sets") |
| public void testSets(Set<String> instance) { |
| // nothing to test, no subset methods |
| |
| } |
| |
| @Test(dataProvider = "SortedSets") |
| public void testSortedSets(SortedSet<String> instance) { |
| assertSame(getSyncCollectionMutex(instance.headSet("Echo")), getSyncCollectionMutex(instance)); |
| assertSame(getSyncCollectionMutex(instance.tailSet("Charlie")), getSyncCollectionMutex(instance)); |
| assertSame(getSyncCollectionMutex(instance.subSet("Charlie", "Echo")), getSyncCollectionMutex(instance)); |
| |
| } |
| |
| @Test(dataProvider = "NavigableSets") |
| public void testNavigableSets(NavigableSet<String> instance) { |
| assertSame(getSyncCollectionMutex(instance.descendingSet()), getSyncCollectionMutex(instance)); |
| assertSame(getSyncCollectionMutex(instance.headSet("Echo")), getSyncCollectionMutex(instance)); |
| assertSame(getSyncCollectionMutex(instance.headSet("Echo", true)), getSyncCollectionMutex(instance)); |
| assertSame(getSyncCollectionMutex(instance.tailSet("Charlie")), getSyncCollectionMutex(instance)); |
| assertSame(getSyncCollectionMutex(instance.tailSet("Charlie", true)), getSyncCollectionMutex(instance)); |
| assertSame(getSyncCollectionMutex(instance.subSet("Charlie", "Echo")), getSyncCollectionMutex(instance)); |
| assertSame(getSyncCollectionMutex(instance.subSet("Charlie", true, "Echo", true)), getSyncCollectionMutex(instance)); |
| } |
| |
| @Test(dataProvider = "Maps") |
| public void testMaps(Map<String, String> instance) { |
| assertSame(getSyncCollectionMutex(instance.entrySet()), getSyncMapMutex(instance)); |
| assertSame(getSyncCollectionMutex(instance.keySet()), getSyncMapMutex(instance)); |
| assertSame(getSyncCollectionMutex(instance.values()), getSyncMapMutex(instance)); |
| } |
| |
| @Test(dataProvider = "SortedMaps") |
| public void testSortedMaps(SortedMap<String, String> instance) { |
| assertSame(getSyncCollectionMutex(instance.entrySet()), getSyncMapMutex(instance)); |
| assertSame(getSyncCollectionMutex(instance.keySet()), getSyncMapMutex(instance)); |
| assertSame(getSyncCollectionMutex(instance.values()), getSyncMapMutex(instance)); |
| assertSame(getSyncMapMutex(instance.headMap("Echo")), getSyncMapMutex(instance)); |
| assertSame(getSyncMapMutex(instance.tailMap("Charlie")), getSyncMapMutex(instance)); |
| assertSame(getSyncMapMutex(instance.subMap("Charlie", "Echo")), getSyncMapMutex(instance)); |
| } |
| |
| @Test(dataProvider = "NavigableMaps") |
| public void testNavigableMaps(NavigableMap<String, String> instance) { |
| assertSame(getSyncMapMutex(instance.descendingMap()), getSyncMapMutex(instance)); |
| assertSame(getSyncCollectionMutex(instance.entrySet()), getSyncMapMutex(instance)); |
| assertSame(getSyncCollectionMutex(instance.keySet()), getSyncMapMutex(instance)); |
| assertSame(getSyncCollectionMutex(instance.descendingKeySet()), getSyncMapMutex(instance)); |
| assertSame(getSyncCollectionMutex(instance.values()), getSyncMapMutex(instance)); |
| assertSame(getSyncMapMutex(instance.headMap("Echo")), getSyncMapMutex(instance)); |
| assertSame(getSyncMapMutex(instance.headMap("Echo", true)), getSyncMapMutex(instance)); |
| assertSame(getSyncMapMutex(instance.tailMap("Charlie")), getSyncMapMutex(instance)); |
| assertSame(getSyncMapMutex(instance.tailMap("Charlie", true)), getSyncMapMutex(instance)); |
| assertSame(getSyncMapMutex(instance.subMap("Charlie", true, "Echo", true)), getSyncMapMutex(instance)); |
| assertSame(getSyncMapMutex(instance.subMap("Charlie", true, "Echo", true)), getSyncMapMutex(instance)); |
| } |
| |
| @DataProvider(name = "Collections", parallel = true) |
| public static Iterator<Object[]> collectionProvider() { |
| return makeCollections().iterator(); |
| } |
| |
| @DataProvider(name = "Lists", parallel = true) |
| public static Iterator<Object[]> listProvider() { |
| return makeLists().iterator(); |
| } |
| |
| @DataProvider(name = "Sets", parallel = true) |
| public static Iterator<Object[]> setProvider() { |
| return makeSets().iterator(); |
| } |
| |
| @DataProvider(name = "SortedSets", parallel = true) |
| public static Iterator<Object[]> sortedsetProvider() { |
| return makeSortedSets().iterator(); |
| } |
| |
| @DataProvider(name = "NavigableSets", parallel = true) |
| public static Iterator<Object[]> navigablesetProvider() { |
| return makeNavigableSets().iterator(); |
| } |
| |
| @DataProvider(name = "Maps", parallel = true) |
| public static Iterator<Object[]> mapProvider() { |
| return makeMaps().iterator(); |
| } |
| |
| @DataProvider(name = "SortedMaps", parallel = true) |
| public static Iterator<Object[]> sortedmapProvider() { |
| return makeSortedMaps().iterator(); |
| } |
| |
| @DataProvider(name = "NavigableMaps", parallel = true) |
| public static Iterator<Object[]> navigablemapProvider() { |
| return makeNavigableMaps().iterator(); |
| } |
| |
| private static final Collection<String> BASE_COLLECTION = Collections.unmodifiableCollection( |
| Arrays.asList("Alpha", "Bravo", "Charlie", "Delta", "Echo", "Foxtrot", "Golf") |
| ); |
| private static final Map<String, String> BASE_MAP; |
| |
| static { |
| Map<String, String> map = new HashMap<>(); |
| for(String each : BASE_COLLECTION) { |
| map.put(each, "*" + each + "*"); |
| } |
| BASE_MAP = Collections.unmodifiableMap(map); |
| } |
| |
| public static Collection<Object[]> makeCollections() { |
| Collection<Object[]> instances = new ArrayList<>(); |
| instances.add(new Object[] {Collections.synchronizedCollection(new ArrayList<>(BASE_COLLECTION))}); |
| instances.addAll(makeLists()); |
| |
| return instances; |
| } |
| |
| public static Collection<Object[]> makeLists() { |
| Collection<Object[]> instances = new ArrayList<>(); |
| instances.add(new Object[] {Collections.synchronizedList(new ArrayList<>(BASE_COLLECTION))}); |
| instances.add(new Object[] {Collections.synchronizedList(new ArrayList<>(BASE_COLLECTION)).subList(1, 2)}); |
| |
| return instances; |
| } |
| |
| public static Collection<Object[]> makeSets() { |
| Collection<Object[]> instances = new ArrayList<>(); |
| |
| instances.add(new Object[] {Collections.synchronizedSet(new TreeSet<>(BASE_COLLECTION))}); |
| instances.addAll(makeSortedSets()); |
| return instances; |
| } |
| |
| public static Collection<Object[]> makeSortedSets() { |
| Collection<Object[]> instances = new ArrayList<>(); |
| instances.add(new Object[] {Collections.synchronizedSortedSet(new TreeSet<>(BASE_COLLECTION))}); |
| instances.add(new Object[] {Collections.synchronizedSortedSet(new TreeSet<>(BASE_COLLECTION)).headSet("Foxtrot")}); |
| instances.add(new Object[] {Collections.synchronizedSortedSet(new TreeSet<>(BASE_COLLECTION)).tailSet("Bravo")}); |
| instances.add(new Object[] {Collections.synchronizedSortedSet(new TreeSet<>(BASE_COLLECTION)).subSet("Bravo", "Foxtrot")}); |
| instances.addAll(makeNavigableSets()); |
| |
| return instances; |
| } |
| |
| public static Collection<Object[]> makeNavigableSets() { |
| Collection<Object[]> instances = new ArrayList<>(); |
| |
| instances.add(new Object[] {Collections.synchronizedNavigableSet(new TreeSet<>(BASE_COLLECTION))}); |
| instances.add(new Object[] {Collections.synchronizedNavigableSet(new TreeSet<>(BASE_COLLECTION)).descendingSet().descendingSet()}); |
| instances.add(new Object[] {Collections.synchronizedNavigableSet(new TreeSet<>(BASE_COLLECTION)).headSet("Foxtrot")}); |
| instances.add(new Object[] {Collections.synchronizedNavigableSet(new TreeSet<>(BASE_COLLECTION)).headSet("Foxtrot", true)}); |
| instances.add(new Object[] {Collections.synchronizedNavigableSet(new TreeSet<>(BASE_COLLECTION)).tailSet("Bravo")}); |
| instances.add(new Object[] {Collections.synchronizedNavigableSet(new TreeSet<>(BASE_COLLECTION)).tailSet("Bravo", true)}); |
| instances.add(new Object[] {Collections.synchronizedNavigableSet(new TreeSet<>(BASE_COLLECTION)).subSet("Bravo", "Foxtrot")}); |
| instances.add(new Object[] {Collections.synchronizedNavigableSet(new TreeSet<>(BASE_COLLECTION)).subSet("Bravo", true, "Foxtrot", true)}); |
| |
| return instances; |
| } |
| |
| public static Collection<Object[]> makeMaps() { |
| Collection<Object[]> instances = new ArrayList<>(); |
| |
| instances.add(new Object[] {Collections.synchronizedMap(new HashMap<>(BASE_MAP))}); |
| instances.addAll(makeSortedMaps()); |
| |
| return instances; |
| } |
| |
| public static Collection<Object[]> makeSortedMaps() { |
| Collection<Object[]> instances = new ArrayList<>(); |
| |
| instances.add(new Object[] {Collections.synchronizedSortedMap(new TreeMap<>(BASE_MAP))}); |
| instances.add(new Object[] {Collections.synchronizedSortedMap(new TreeMap<>(BASE_MAP)).headMap("Foxtrot")}); |
| instances.add(new Object[] {Collections.synchronizedSortedMap(new TreeMap<>(BASE_MAP)).tailMap("Bravo")}); |
| instances.add(new Object[] {Collections.synchronizedSortedMap(new TreeMap<>(BASE_MAP)).subMap("Bravo", "Foxtrot")}); |
| instances.addAll(makeNavigableMaps()); |
| |
| return instances; |
| } |
| |
| public static Collection<Object[]> makeNavigableMaps() { |
| Collection<Object[]> instances = new ArrayList<>(); |
| |
| instances.add(new Object[] {Collections.synchronizedNavigableMap(new TreeMap<>(BASE_MAP))}); |
| instances.add(new Object[] {Collections.synchronizedNavigableMap(new TreeMap<>(BASE_MAP).descendingMap().descendingMap())}); |
| instances.add(new Object[] {Collections.synchronizedNavigableMap(new TreeMap<>(BASE_MAP)).headMap("Foxtrot")}); |
| instances.add(new Object[] {Collections.synchronizedNavigableMap(new TreeMap<>(BASE_MAP)).headMap("Foxtrot", true)}); |
| instances.add(new Object[] {Collections.synchronizedNavigableMap(new TreeMap<>(BASE_MAP)).tailMap("Bravo")}); |
| instances.add(new Object[] {Collections.synchronizedNavigableMap(new TreeMap<>(BASE_MAP)).tailMap("Bravo", true)}); |
| instances.add(new Object[] {Collections.synchronizedNavigableMap(new TreeMap<>(BASE_MAP)).subMap("Bravo", "Foxtrot")}); |
| instances.add(new Object[] {Collections.synchronizedNavigableMap(new TreeMap<>(BASE_MAP)).subMap("Bravo", true, "Foxtrot", true)}); |
| |
| return instances; |
| } |
| |
| private static Object getSyncCollectionMutex(Collection<?> from) { |
| try { |
| Class<?> synchronizedCollectionClazz = Class.forName("java.util.Collections$SynchronizedCollection"); |
| Field f = synchronizedCollectionClazz.getDeclaredField("mutex"); |
| f.setAccessible(true); |
| return f.get(from); |
| } catch ( ClassNotFoundException | NoSuchFieldException | IllegalAccessException e) { |
| throw new RuntimeException("Unable to get mutex field.", e); |
| } |
| } |
| |
| private static Object getSyncMapMutex(Map<?,?> from) { |
| try { |
| Class<?> synchronizedMapClazz = Class.forName("java.util.Collections$SynchronizedMap"); |
| Field f = synchronizedMapClazz.getDeclaredField("mutex"); |
| f.setAccessible(true); |
| return f.get(from); |
| } catch ( ClassNotFoundException | NoSuchFieldException | IllegalAccessException e) { |
| throw new RuntimeException("Unable to get mutex field.", e); |
| } |
| } |
| |
| } |