blob: dc2e7e3a95154a5183db2110ac3de37dafec1e5f [file] [log] [blame]
/*
* 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);
}
}
}