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
17package com.google.common.collect;
18
19import com.google.common.collect.Synchronized.SynchronizedBiMap;
20import com.google.common.collect.Synchronized.SynchronizedSet;
21
22import junit.framework.TestSuite;
23
24import java.util.Set;
25
26/**
27 * Tests for {@code Synchronized#biMap}.
28 *
29 * @author Mike Bostock
30 */
31public class SynchronizedBiMapTest extends SynchronizedMapTest {
32
33  public static TestSuite suite() {
34    TestSuite suite = new TestSuite(SynchronizedBiMapTest.class);
35    suite.addTestSuite(AbstractBiMapTests.class);
36    return suite;
37  }
38
39  @Override protected <K, V> BiMap<K, V> create() {
40    TestBiMap<K, V> inner =
41        new TestBiMap<K, V>(HashBiMap.<K, V>create(), mutex);
42    BiMap<K, V> outer = Synchronized.biMap(inner, mutex);
43    return outer;
44  }
45
46  static class TestBiMap<K, V> extends TestMap<K, V> implements BiMap<K, V> {
47    private final BiMap<K, V> delegate;
48
49    public TestBiMap(BiMap<K, V> delegate, Object mutex) {
50      super(delegate, mutex);
51      this.delegate = delegate;
52    }
53
54    @Override
55    public V forcePut(K key, V value) {
56      assertTrue(Thread.holdsLock(mutex));
57      return delegate.forcePut(key, value);
58    }
59
60    @Override
61    public BiMap<V, K> inverse() {
62      assertTrue(Thread.holdsLock(mutex));
63      return delegate.inverse();
64    }
65
66    @Override public Set<V> values() {
67      assertTrue(Thread.holdsLock(mutex));
68      return delegate.values();
69    }
70
71    private static final long serialVersionUID = 0;
72  }
73
74  public void testForcePut() {
75    create().forcePut(null, null);
76  }
77
78  public void testInverse() {
79    BiMap<String, Integer> bimap = create();
80    BiMap<Integer, String> inverse = bimap.inverse();
81    assertSame(bimap, inverse.inverse());
82    assertTrue(inverse instanceof SynchronizedBiMap);
83    assertSame(mutex, ((SynchronizedBiMap<?, ?>) inverse).mutex);
84  }
85
86  @Override public void testValues() {
87    BiMap<String, Integer> map = create();
88    Set<Integer> values = map.values();
89    assertTrue(values instanceof SynchronizedSet);
90    assertSame(mutex, ((SynchronizedSet<?>) values).mutex);
91  }
92
93  public static class AbstractBiMapTests extends AbstractBiMapTest {
94    public final Object mutex = new Integer(1); // something Serializable
95
96    @Override protected BiMap<Integer, String> create() {
97      TestBiMap<Integer, String> inner = new TestBiMap<Integer, String>(
98          HashBiMap.<Integer, String>create(), mutex);
99      BiMap<Integer, String> outer = Synchronized.biMap(inner, mutex);
100      return outer;
101    }
102
103    /**
104     * If you serialize a synchronized bimap and its inverse together, the
105     * reserialized bimaps will have backing maps that stay in sync, as shown
106     * by the {@code testSerializationWithInverseEqual()} test. However, the
107     * inverse of one won't be the same as the other.
108     *
109     * To make them the same, the inverse synchronized bimap would need a custom
110     * serialized form, similar to what {@code AbstractBiMap.Inverse} does.
111     */
112    @Override public void testSerializationWithInverseSame() {}
113  }
114}
115