1 /* 2 * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 24 package test.java.util.Collections; 25 26 /** 27 * @test 28 * @bug 8048209 29 * @summary Check that Collections.synchronizedNavigableSet().tailSet() is using 30 * the same lock object as it's source. 31 * @modules java.base/java.util:open 32 * @run testng SyncSubMutexes 33 */ 34 import java.lang.reflect.Field; 35 import java.util.*; 36 import java.util.Set; 37 import java.util.Arrays; 38 39 import org.testng.annotations.Test; 40 import org.testng.annotations.DataProvider; 41 import static org.testng.Assert.assertSame; 42 43 public class SyncSubMutexes { 44 45 @Test(dataProvider = "Collections") testCollections(Collection<String> instance)46 public void testCollections(Collection<String> instance) { 47 // nothing to test, no subset methods 48 } 49 50 @Test(dataProvider = "Lists") testLists(List<String> instance)51 public void testLists(List<String> instance) { 52 assertSame(getSyncCollectionMutex(instance.subList(0, 1)), getSyncCollectionMutex(instance)); 53 } 54 55 @Test(dataProvider = "Sets") testSets(Set<String> instance)56 public void testSets(Set<String> instance) { 57 // nothing to test, no subset methods 58 59 } 60 61 @Test(dataProvider = "SortedSets") testSortedSets(SortedSet<String> instance)62 public void testSortedSets(SortedSet<String> instance) { 63 assertSame(getSyncCollectionMutex(instance.headSet("Echo")), getSyncCollectionMutex(instance)); 64 assertSame(getSyncCollectionMutex(instance.tailSet("Charlie")), getSyncCollectionMutex(instance)); 65 assertSame(getSyncCollectionMutex(instance.subSet("Charlie", "Echo")), getSyncCollectionMutex(instance)); 66 67 } 68 69 @Test(dataProvider = "NavigableSets") testNavigableSets(NavigableSet<String> instance)70 public void testNavigableSets(NavigableSet<String> instance) { 71 assertSame(getSyncCollectionMutex(instance.descendingSet()), getSyncCollectionMutex(instance)); 72 assertSame(getSyncCollectionMutex(instance.headSet("Echo")), getSyncCollectionMutex(instance)); 73 assertSame(getSyncCollectionMutex(instance.headSet("Echo", true)), getSyncCollectionMutex(instance)); 74 assertSame(getSyncCollectionMutex(instance.tailSet("Charlie")), getSyncCollectionMutex(instance)); 75 assertSame(getSyncCollectionMutex(instance.tailSet("Charlie", true)), getSyncCollectionMutex(instance)); 76 assertSame(getSyncCollectionMutex(instance.subSet("Charlie", "Echo")), getSyncCollectionMutex(instance)); 77 assertSame(getSyncCollectionMutex(instance.subSet("Charlie", true, "Echo", true)), getSyncCollectionMutex(instance)); 78 } 79 80 @Test(dataProvider = "Maps") testMaps(Map<String, String> instance)81 public void testMaps(Map<String, String> instance) { 82 assertSame(getSyncCollectionMutex(instance.entrySet()), getSyncMapMutex(instance)); 83 assertSame(getSyncCollectionMutex(instance.keySet()), getSyncMapMutex(instance)); 84 assertSame(getSyncCollectionMutex(instance.values()), getSyncMapMutex(instance)); 85 } 86 87 @Test(dataProvider = "SortedMaps") testSortedMaps(SortedMap<String, String> instance)88 public void testSortedMaps(SortedMap<String, String> instance) { 89 assertSame(getSyncCollectionMutex(instance.entrySet()), getSyncMapMutex(instance)); 90 assertSame(getSyncCollectionMutex(instance.keySet()), getSyncMapMutex(instance)); 91 assertSame(getSyncCollectionMutex(instance.values()), getSyncMapMutex(instance)); 92 assertSame(getSyncMapMutex(instance.headMap("Echo")), getSyncMapMutex(instance)); 93 assertSame(getSyncMapMutex(instance.tailMap("Charlie")), getSyncMapMutex(instance)); 94 assertSame(getSyncMapMutex(instance.subMap("Charlie", "Echo")), getSyncMapMutex(instance)); 95 } 96 97 @Test(dataProvider = "NavigableMaps") testNavigableMaps(NavigableMap<String, String> instance)98 public void testNavigableMaps(NavigableMap<String, String> instance) { 99 assertSame(getSyncMapMutex(instance.descendingMap()), getSyncMapMutex(instance)); 100 assertSame(getSyncCollectionMutex(instance.entrySet()), getSyncMapMutex(instance)); 101 assertSame(getSyncCollectionMutex(instance.keySet()), getSyncMapMutex(instance)); 102 assertSame(getSyncCollectionMutex(instance.descendingKeySet()), getSyncMapMutex(instance)); 103 assertSame(getSyncCollectionMutex(instance.values()), getSyncMapMutex(instance)); 104 assertSame(getSyncMapMutex(instance.headMap("Echo")), getSyncMapMutex(instance)); 105 assertSame(getSyncMapMutex(instance.headMap("Echo", true)), getSyncMapMutex(instance)); 106 assertSame(getSyncMapMutex(instance.tailMap("Charlie")), getSyncMapMutex(instance)); 107 assertSame(getSyncMapMutex(instance.tailMap("Charlie", true)), getSyncMapMutex(instance)); 108 assertSame(getSyncMapMutex(instance.subMap("Charlie", true, "Echo", true)), getSyncMapMutex(instance)); 109 assertSame(getSyncMapMutex(instance.subMap("Charlie", true, "Echo", true)), getSyncMapMutex(instance)); 110 } 111 112 @DataProvider(name = "Collections", parallel = true) collectionProvider()113 public static Iterator<Object[]> collectionProvider() { 114 return makeCollections().iterator(); 115 } 116 117 @DataProvider(name = "Lists", parallel = true) listProvider()118 public static Iterator<Object[]> listProvider() { 119 return makeLists().iterator(); 120 } 121 122 @DataProvider(name = "Sets", parallel = true) setProvider()123 public static Iterator<Object[]> setProvider() { 124 return makeSets().iterator(); 125 } 126 127 @DataProvider(name = "SortedSets", parallel = true) sortedsetProvider()128 public static Iterator<Object[]> sortedsetProvider() { 129 return makeSortedSets().iterator(); 130 } 131 132 @DataProvider(name = "NavigableSets", parallel = true) navigablesetProvider()133 public static Iterator<Object[]> navigablesetProvider() { 134 return makeNavigableSets().iterator(); 135 } 136 137 @DataProvider(name = "Maps", parallel = true) mapProvider()138 public static Iterator<Object[]> mapProvider() { 139 return makeMaps().iterator(); 140 } 141 142 @DataProvider(name = "SortedMaps", parallel = true) sortedmapProvider()143 public static Iterator<Object[]> sortedmapProvider() { 144 return makeSortedMaps().iterator(); 145 } 146 147 @DataProvider(name = "NavigableMaps", parallel = true) navigablemapProvider()148 public static Iterator<Object[]> navigablemapProvider() { 149 return makeNavigableMaps().iterator(); 150 } 151 152 private static final Collection<String> BASE_COLLECTION = Collections.unmodifiableCollection( 153 Arrays.asList("Alpha", "Bravo", "Charlie", "Delta", "Echo", "Foxtrot", "Golf") 154 ); 155 private static final Map<String, String> BASE_MAP; 156 157 static { 158 Map<String, String> map = new HashMap<>(); 159 for(String each : BASE_COLLECTION) { map.put(each, "*" + each + "*")160 map.put(each, "*" + each + "*"); 161 } 162 BASE_MAP = Collections.unmodifiableMap(map); 163 } 164 makeCollections()165 public static Collection<Object[]> makeCollections() { 166 Collection<Object[]> instances = new ArrayList<>(); 167 instances.add(new Object[] {Collections.synchronizedCollection(new ArrayList<>(BASE_COLLECTION))}); 168 instances.addAll(makeLists()); 169 170 return instances; 171 } 172 makeLists()173 public static Collection<Object[]> makeLists() { 174 Collection<Object[]> instances = new ArrayList<>(); 175 instances.add(new Object[] {Collections.synchronizedList(new ArrayList<>(BASE_COLLECTION))}); 176 instances.add(new Object[] {Collections.synchronizedList(new ArrayList<>(BASE_COLLECTION)).subList(1, 2)}); 177 178 return instances; 179 } 180 makeSets()181 public static Collection<Object[]> makeSets() { 182 Collection<Object[]> instances = new ArrayList<>(); 183 184 instances.add(new Object[] {Collections.synchronizedSet(new TreeSet<>(BASE_COLLECTION))}); 185 instances.addAll(makeSortedSets()); 186 return instances; 187 } 188 makeSortedSets()189 public static Collection<Object[]> makeSortedSets() { 190 Collection<Object[]> instances = new ArrayList<>(); 191 instances.add(new Object[] {Collections.synchronizedSortedSet(new TreeSet<>(BASE_COLLECTION))}); 192 instances.add(new Object[] {Collections.synchronizedSortedSet(new TreeSet<>(BASE_COLLECTION)).headSet("Foxtrot")}); 193 instances.add(new Object[] {Collections.synchronizedSortedSet(new TreeSet<>(BASE_COLLECTION)).tailSet("Bravo")}); 194 instances.add(new Object[] {Collections.synchronizedSortedSet(new TreeSet<>(BASE_COLLECTION)).subSet("Bravo", "Foxtrot")}); 195 instances.addAll(makeNavigableSets()); 196 197 return instances; 198 } 199 makeNavigableSets()200 public static Collection<Object[]> makeNavigableSets() { 201 Collection<Object[]> instances = new ArrayList<>(); 202 203 instances.add(new Object[] {Collections.synchronizedNavigableSet(new TreeSet<>(BASE_COLLECTION))}); 204 instances.add(new Object[] {Collections.synchronizedNavigableSet(new TreeSet<>(BASE_COLLECTION)).descendingSet().descendingSet()}); 205 instances.add(new Object[] {Collections.synchronizedNavigableSet(new TreeSet<>(BASE_COLLECTION)).headSet("Foxtrot")}); 206 instances.add(new Object[] {Collections.synchronizedNavigableSet(new TreeSet<>(BASE_COLLECTION)).headSet("Foxtrot", true)}); 207 instances.add(new Object[] {Collections.synchronizedNavigableSet(new TreeSet<>(BASE_COLLECTION)).tailSet("Bravo")}); 208 instances.add(new Object[] {Collections.synchronizedNavigableSet(new TreeSet<>(BASE_COLLECTION)).tailSet("Bravo", true)}); 209 instances.add(new Object[] {Collections.synchronizedNavigableSet(new TreeSet<>(BASE_COLLECTION)).subSet("Bravo", "Foxtrot")}); 210 instances.add(new Object[] {Collections.synchronizedNavigableSet(new TreeSet<>(BASE_COLLECTION)).subSet("Bravo", true, "Foxtrot", true)}); 211 212 return instances; 213 } 214 makeMaps()215 public static Collection<Object[]> makeMaps() { 216 Collection<Object[]> instances = new ArrayList<>(); 217 218 instances.add(new Object[] {Collections.synchronizedMap(new HashMap<>(BASE_MAP))}); 219 instances.addAll(makeSortedMaps()); 220 221 return instances; 222 } 223 makeSortedMaps()224 public static Collection<Object[]> makeSortedMaps() { 225 Collection<Object[]> instances = new ArrayList<>(); 226 227 instances.add(new Object[] {Collections.synchronizedSortedMap(new TreeMap<>(BASE_MAP))}); 228 instances.add(new Object[] {Collections.synchronizedSortedMap(new TreeMap<>(BASE_MAP)).headMap("Foxtrot")}); 229 instances.add(new Object[] {Collections.synchronizedSortedMap(new TreeMap<>(BASE_MAP)).tailMap("Bravo")}); 230 instances.add(new Object[] {Collections.synchronizedSortedMap(new TreeMap<>(BASE_MAP)).subMap("Bravo", "Foxtrot")}); 231 instances.addAll(makeNavigableMaps()); 232 233 return instances; 234 } 235 makeNavigableMaps()236 public static Collection<Object[]> makeNavigableMaps() { 237 Collection<Object[]> instances = new ArrayList<>(); 238 239 instances.add(new Object[] {Collections.synchronizedNavigableMap(new TreeMap<>(BASE_MAP))}); 240 instances.add(new Object[] {Collections.synchronizedNavigableMap(new TreeMap<>(BASE_MAP).descendingMap().descendingMap())}); 241 instances.add(new Object[] {Collections.synchronizedNavigableMap(new TreeMap<>(BASE_MAP)).headMap("Foxtrot")}); 242 instances.add(new Object[] {Collections.synchronizedNavigableMap(new TreeMap<>(BASE_MAP)).headMap("Foxtrot", true)}); 243 instances.add(new Object[] {Collections.synchronizedNavigableMap(new TreeMap<>(BASE_MAP)).tailMap("Bravo")}); 244 instances.add(new Object[] {Collections.synchronizedNavigableMap(new TreeMap<>(BASE_MAP)).tailMap("Bravo", true)}); 245 instances.add(new Object[] {Collections.synchronizedNavigableMap(new TreeMap<>(BASE_MAP)).subMap("Bravo", "Foxtrot")}); 246 instances.add(new Object[] {Collections.synchronizedNavigableMap(new TreeMap<>(BASE_MAP)).subMap("Bravo", true, "Foxtrot", true)}); 247 248 return instances; 249 } 250 getSyncCollectionMutex(Collection<?> from)251 private static Object getSyncCollectionMutex(Collection<?> from) { 252 try { 253 Class<?> synchronizedCollectionClazz = Class.forName("java.util.Collections$SynchronizedCollection"); 254 Field f = synchronizedCollectionClazz.getDeclaredField("mutex"); 255 f.setAccessible(true); 256 return f.get(from); 257 } catch ( ClassNotFoundException | NoSuchFieldException | IllegalAccessException e) { 258 throw new RuntimeException("Unable to get mutex field.", e); 259 } 260 } 261 getSyncMapMutex(Map<?,?> from)262 private static Object getSyncMapMutex(Map<?,?> from) { 263 try { 264 Class<?> synchronizedMapClazz = Class.forName("java.util.Collections$SynchronizedMap"); 265 Field f = synchronizedMapClazz.getDeclaredField("mutex"); 266 f.setAccessible(true); 267 return f.get(from); 268 } catch ( ClassNotFoundException | NoSuchFieldException | IllegalAccessException e) { 269 throw new RuntimeException("Unable to get mutex field.", e); 270 } 271 } 272 273 } 274