1 /* 2 * Copyright (C) 2007 The Guava Authors 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.google.common.collect; 18 19 import static com.google.common.base.Preconditions.checkArgument; 20 21 import com.google.common.collect.Synchronized.SynchronizedBiMap; 22 import com.google.common.collect.Synchronized.SynchronizedSet; 23 import com.google.common.collect.testing.features.CollectionFeature; 24 import com.google.common.collect.testing.features.CollectionSize; 25 import com.google.common.collect.testing.features.MapFeature; 26 import com.google.common.collect.testing.google.BiMapInverseTester; 27 import com.google.common.collect.testing.google.BiMapTestSuiteBuilder; 28 import com.google.common.collect.testing.google.TestStringBiMapGenerator; 29 import java.util.Map.Entry; 30 import java.util.Set; 31 import java.util.function.BiFunction; 32 import junit.framework.TestSuite; 33 34 /** 35 * Tests for {@code Synchronized#biMap}. 36 * 37 * @author Mike Bostock 38 */ 39 public class SynchronizedBiMapTest extends SynchronizedMapTest { 40 suite()41 public static TestSuite suite() { 42 TestSuite suite = new TestSuite(SynchronizedBiMapTest.class); 43 suite.addTest( 44 BiMapTestSuiteBuilder.using(new SynchTestingBiMapGenerator()) 45 .named("Synchronized.biMap[TestBiMap]") 46 .withFeatures( 47 CollectionSize.ANY, 48 CollectionFeature.SUPPORTS_ITERATOR_REMOVE, 49 MapFeature.ALLOWS_NULL_KEYS, 50 MapFeature.ALLOWS_NULL_VALUES, 51 MapFeature.ALLOWS_ANY_NULL_QUERIES, 52 MapFeature.GENERAL_PURPOSE, 53 MapFeature.REJECTS_DUPLICATES_AT_CREATION) 54 .createTestSuite()); 55 suite.addTest( 56 BiMapTestSuiteBuilder.using(new SynchronizedHashBiMapGenerator()) 57 .named("synchronizedBiMap[HashBiMap]") 58 .withFeatures( 59 CollectionSize.ANY, 60 CollectionFeature.SUPPORTS_ITERATOR_REMOVE, 61 MapFeature.ALLOWS_NULL_KEYS, 62 MapFeature.ALLOWS_NULL_VALUES, 63 MapFeature.ALLOWS_ANY_NULL_QUERIES, 64 MapFeature.GENERAL_PURPOSE, 65 MapFeature.REJECTS_DUPLICATES_AT_CREATION, 66 CollectionFeature.SERIALIZABLE) 67 .suppressing(BiMapInverseTester.getInverseSameAfterSerializingMethods()) 68 .createTestSuite()); 69 return suite; 70 } 71 72 @Override create()73 protected <K, V> BiMap<K, V> create() { 74 TestBiMap<K, V> inner = new TestBiMap<>(HashBiMap.<K, V>create(), mutex); 75 BiMap<K, V> outer = Synchronized.biMap(inner, mutex); 76 return outer; 77 } 78 79 public static final class SynchronizedHashBiMapGenerator extends TestStringBiMapGenerator { 80 @Override create(Entry<String, String>[] entries)81 protected BiMap<String, String> create(Entry<String, String>[] entries) { 82 Object mutex = new Object(); 83 BiMap<String, String> result = HashBiMap.create(); 84 for (Entry<String, String> entry : entries) { 85 checkArgument(!result.containsKey(entry.getKey())); 86 result.put(entry.getKey(), entry.getValue()); 87 } 88 return Maps.synchronizedBiMap(result); 89 } 90 } 91 92 public static final class SynchTestingBiMapGenerator extends TestStringBiMapGenerator { 93 @Override create(Entry<String, String>[] entries)94 protected BiMap<String, String> create(Entry<String, String>[] entries) { 95 Object mutex = new Object(); 96 BiMap<String, String> backing = new TestBiMap<>(HashBiMap.<String, String>create(), mutex); 97 BiMap<String, String> result = Synchronized.biMap(backing, mutex); 98 for (Entry<String, String> entry : entries) { 99 checkArgument(!result.containsKey(entry.getKey())); 100 result.put(entry.getKey(), entry.getValue()); 101 } 102 return result; 103 } 104 } 105 106 static class TestBiMap<K, V> extends TestMap<K, V> implements BiMap<K, V> { 107 private final BiMap<K, V> delegate; 108 TestBiMap(BiMap<K, V> delegate, Object mutex)109 public TestBiMap(BiMap<K, V> delegate, Object mutex) { 110 super(delegate, mutex); 111 this.delegate = delegate; 112 } 113 114 @Override forcePut(K key, V value)115 public V forcePut(K key, V value) { 116 assertTrue(Thread.holdsLock(mutex)); 117 return delegate.forcePut(key, value); 118 } 119 120 @Override inverse()121 public BiMap<V, K> inverse() { 122 assertTrue(Thread.holdsLock(mutex)); 123 return delegate.inverse(); 124 } 125 126 @Override replaceAll(BiFunction<? super K, ? super V, ? extends V> function)127 public void replaceAll(BiFunction<? super K, ? super V, ? extends V> function) { 128 assertTrue(Thread.holdsLock(mutex)); 129 delegate.replaceAll(function); 130 } 131 132 @Override values()133 public Set<V> values() { 134 assertTrue(Thread.holdsLock(mutex)); 135 return delegate.values(); 136 } 137 138 private static final long serialVersionUID = 0; 139 } 140 testForcePut()141 public void testForcePut() { 142 create().forcePut(null, null); 143 } 144 testInverse()145 public void testInverse() { 146 BiMap<String, Integer> bimap = create(); 147 BiMap<Integer, String> inverse = bimap.inverse(); 148 assertSame(bimap, inverse.inverse()); 149 assertTrue(inverse instanceof SynchronizedBiMap); 150 assertSame(mutex, ((SynchronizedBiMap<?, ?>) inverse).mutex); 151 } 152 153 @Override testValues()154 public void testValues() { 155 BiMap<String, Integer> map = create(); 156 Set<Integer> values = map.values(); 157 assertTrue(values instanceof SynchronizedSet); 158 assertSame(mutex, ((SynchronizedSet<?>) values).mutex); 159 } 160 } 161