3789983e89
Reviewed-by: darcy, ihse
272 lines
13 KiB
Java
272 lines
13 KiB
Java
/*
|
|
* 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);
|
|
}
|
|
}
|
|
|
|
}
|