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 import org.checkerframework.checker.nullness.qual.Nullable; 34 35 /** 36 * Tests for {@code Synchronized#biMap}. 37 * 38 * @author Mike Bostock 39 */ 40 public class SynchronizedBiMapTest extends SynchronizedMapTest { 41 suite()42 public static TestSuite suite() { 43 TestSuite suite = new TestSuite(SynchronizedBiMapTest.class); 44 suite.addTest( 45 BiMapTestSuiteBuilder.using(new SynchTestingBiMapGenerator()) 46 .named("Synchronized.biMap[TestBiMap]") 47 .withFeatures( 48 CollectionSize.ANY, 49 CollectionFeature.SUPPORTS_ITERATOR_REMOVE, 50 MapFeature.ALLOWS_NULL_KEYS, 51 MapFeature.ALLOWS_NULL_VALUES, 52 MapFeature.ALLOWS_ANY_NULL_QUERIES, 53 MapFeature.GENERAL_PURPOSE, 54 MapFeature.REJECTS_DUPLICATES_AT_CREATION) 55 .createTestSuite()); 56 suite.addTest( 57 BiMapTestSuiteBuilder.using(new SynchronizedHashBiMapGenerator()) 58 .named("synchronizedBiMap[HashBiMap]") 59 .withFeatures( 60 CollectionSize.ANY, 61 CollectionFeature.SUPPORTS_ITERATOR_REMOVE, 62 MapFeature.ALLOWS_NULL_KEYS, 63 MapFeature.ALLOWS_NULL_VALUES, 64 MapFeature.ALLOWS_ANY_NULL_QUERIES, 65 MapFeature.GENERAL_PURPOSE, 66 MapFeature.REJECTS_DUPLICATES_AT_CREATION, 67 CollectionFeature.SERIALIZABLE) 68 .suppressing(BiMapInverseTester.getInverseSameAfterSerializingMethods()) 69 .createTestSuite()); 70 return suite; 71 } 72 73 @Override create()74 protected <K, V> BiMap<K, V> create() { 75 TestBiMap<K, V> inner = new TestBiMap<>(HashBiMap.<K, V>create(), mutex); 76 BiMap<K, V> outer = Synchronized.biMap(inner, mutex); 77 return outer; 78 } 79 80 public static final class SynchronizedHashBiMapGenerator extends TestStringBiMapGenerator { 81 @Override create(Entry<String, String>[] entries)82 protected BiMap<String, String> create(Entry<String, String>[] entries) { 83 Object mutex = new Object(); 84 BiMap<String, String> result = HashBiMap.create(); 85 for (Entry<String, String> entry : entries) { 86 checkArgument(!result.containsKey(entry.getKey())); 87 result.put(entry.getKey(), entry.getValue()); 88 } 89 return Maps.synchronizedBiMap(result); 90 } 91 } 92 93 public static final class SynchTestingBiMapGenerator extends TestStringBiMapGenerator { 94 @Override create(Entry<String, String>[] entries)95 protected BiMap<String, String> create(Entry<String, String>[] entries) { 96 Object mutex = new Object(); 97 BiMap<String, String> backing = new TestBiMap<>(HashBiMap.<String, String>create(), mutex); 98 BiMap<String, String> result = Synchronized.biMap(backing, mutex); 99 for (Entry<String, String> entry : entries) { 100 checkArgument(!result.containsKey(entry.getKey())); 101 result.put(entry.getKey(), entry.getValue()); 102 } 103 return result; 104 } 105 } 106 107 static class TestBiMap<K, V> extends TestMap<K, V> implements BiMap<K, V> { 108 private final BiMap<K, V> delegate; 109 TestBiMap(BiMap<K, V> delegate, Object mutex)110 public TestBiMap(BiMap<K, V> delegate, Object mutex) { 111 super(delegate, mutex); 112 this.delegate = delegate; 113 } 114 115 @Override forcePut(K key, V value)116 public @Nullable V forcePut(K key, V value) { 117 assertTrue(Thread.holdsLock(mutex)); 118 return delegate.forcePut(key, value); 119 } 120 121 @Override inverse()122 public BiMap<V, K> inverse() { 123 assertTrue(Thread.holdsLock(mutex)); 124 return delegate.inverse(); 125 } 126 127 @Override replaceAll(BiFunction<? super K, ? super V, ? extends V> function)128 public void replaceAll(BiFunction<? super K, ? super V, ? extends V> function) { 129 assertTrue(Thread.holdsLock(mutex)); 130 delegate.replaceAll(function); 131 } 132 133 @Override values()134 public Set<V> values() { 135 assertTrue(Thread.holdsLock(mutex)); 136 return delegate.values(); 137 } 138 139 private static final long serialVersionUID = 0; 140 } 141 testForcePut()142 public void testForcePut() { 143 create().forcePut(null, null); 144 } 145 testInverse()146 public void testInverse() { 147 BiMap<String, Integer> bimap = create(); 148 BiMap<Integer, String> inverse = bimap.inverse(); 149 assertSame(bimap, inverse.inverse()); 150 assertTrue(inverse instanceof SynchronizedBiMap); 151 assertSame(mutex, ((SynchronizedBiMap<?, ?>) inverse).mutex); 152 } 153 154 @Override testValues()155 public void testValues() { 156 BiMap<String, Integer> map = create(); 157 Set<Integer> values = map.values(); 158 assertTrue(values instanceof SynchronizedSet); 159 assertSame(mutex, ((SynchronizedSet<?>) values).mutex); 160 } 161 } 162