--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/Collections/SyncSubMutexes.java Thu Jul 24 09:01:00 2014 -0700
@@ -0,0 +1,270 @@
+/*
+ * 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.
+ * @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);
+ }
+ }
+
+}