View Javadoc
1   /*
2    * Copyright (C) 2012 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.reflect;
18  
19  import static com.google.common.truth.Truth.assertThat;
20  
21  import com.google.common.collect.ImmutableList;
22  import com.google.common.collect.ImmutableMap;
23  import com.google.common.collect.testing.MapTestSuiteBuilder;
24  import com.google.common.collect.testing.features.CollectionFeature;
25  import com.google.common.collect.testing.features.CollectionSize;
26  import com.google.common.collect.testing.features.MapFeature;
27  import com.google.common.collect.testing.testers.MapPutTester;
28  import com.google.common.reflect.ImmutableTypeToInstanceMapTest.TestTypeToInstanceMapGenerator;
29  
30  import junit.framework.Test;
31  import junit.framework.TestCase;
32  import junit.framework.TestSuite;
33  
34  import java.lang.reflect.Method;
35  import java.util.Map;
36  import java.util.Map.Entry;
37  
38  /**
39   * Unit test of {@link MutableTypeToInstanceMap}.
40   *
41   * @author Ben Yu
42   */
43  public class MutableTypeToInstanceMapTest extends TestCase {
44  
45    public static Test suite() {
46      TestSuite suite = new TestSuite();
47      suite.addTestSuite(MutableTypeToInstanceMapTest.class);
48  
49      // Suppress this one because the tester framework doesn't understand that
50      // *some* remappings will be allowed and others not.
51      Method remapTest = null;
52      try {
53        remapTest = MapPutTester.class.getMethod(
54            "testPut_replaceNullValueWithNonNullSupported");
55      } catch (NoSuchMethodException e) {
56        throw new AssertionError();
57      }
58  
59      suite.addTest(MapTestSuiteBuilder
60          .using(new TestTypeToInstanceMapGenerator() {
61            // Other tests will verify what real, warning-free usage looks like
62            // but here we have to do some serious fudging
63            @Override
64            @SuppressWarnings("unchecked")
65            public Map<TypeToken, Object> create(Object... elements) {
66              MutableTypeToInstanceMap<Object> map
67                  = new MutableTypeToInstanceMap<Object>();
68              for (Object object : elements) {
69                Entry<TypeToken, Object> entry = (Entry<TypeToken, Object>) object;
70                map.putInstance(entry.getKey(), entry.getValue());
71              }
72              return (Map) map;
73            }
74          })
75          .named("MutableTypeToInstanceMap")
76          .withFeatures(
77              MapFeature.SUPPORTS_REMOVE,
78              MapFeature.RESTRICTS_KEYS,
79              MapFeature.ALLOWS_NULL_VALUES,
80              CollectionFeature.SUPPORTS_ITERATOR_REMOVE,
81              CollectionSize.ANY,
82              MapFeature.ALLOWS_ANY_NULL_QUERIES)
83          .suppressing(remapTest)
84          .createTestSuite());
85  
86      return suite;
87    }
88  
89    private TypeToInstanceMap<Object> map;
90  
91    @Override protected void setUp() throws Exception {
92      map = new MutableTypeToInstanceMap<Object>();
93    }
94  
95    public void testPutThrows() {
96      try {
97        map.put(TypeToken.of(Integer.class), new Integer(5));
98        fail();
99      } catch (UnsupportedOperationException expected) {}
100   }
101 
102   public void testPutAllThrows() {
103     try {
104       map.putAll(ImmutableMap.of(TypeToken.of(Integer.class), new Integer(5)));
105       fail();
106     } catch (UnsupportedOperationException expected) {}
107   }
108 
109   public void testEntrySetMutationThrows() {
110     map.putInstance(String.class, "test");
111     assertEquals(TypeToken.of(String.class), map.entrySet().iterator().next().getKey());
112     assertEquals("test", map.entrySet().iterator().next().getValue());
113     try {
114       map.entrySet().iterator().next().setValue(1);
115       fail();
116     } catch (UnsupportedOperationException expected) {}
117   }
118 
119   public void testEntrySetToArrayMutationThrows() {
120     map.putInstance(String.class, "test");
121     @SuppressWarnings("unchecked") // Should get a CCE later if cast is wrong
122     Entry<Object, Object> entry = (Entry<Object, Object>) map.entrySet().toArray()[0];
123     assertEquals(TypeToken.of(String.class), entry.getKey());
124     assertEquals("test", entry.getValue());
125     try {
126       entry.setValue(1);
127       fail();
128     } catch (UnsupportedOperationException expected) {}
129   }
130 
131   public void testEntrySetToTypedArrayMutationThrows() {
132     map.putInstance(String.class, "test");
133     @SuppressWarnings("unchecked") // Should get a CCE later if cast is wrong
134     Entry<Object, Object> entry = map.entrySet().toArray(new Entry[0])[0];
135     assertEquals(TypeToken.of(String.class), entry.getKey());
136     assertEquals("test", entry.getValue());
137     try {
138       entry.setValue(1);
139       fail();
140     } catch (UnsupportedOperationException expected) {}
141   }
142 
143   public void testPutAndGetInstance() {
144     assertNull(map.putInstance(Integer.class, new Integer(5)));
145 
146     Integer oldValue = map.putInstance(Integer.class, new Integer(7));
147     assertEquals(5, (int) oldValue);
148 
149     Integer newValue = map.getInstance(Integer.class);
150     assertEquals(7, (int) newValue);
151     assertEquals(7, (int) map.getInstance(TypeToken.of(Integer.class)));
152 
153     // Won't compile: map.putInstance(Double.class, new Long(42));
154   }
155 
156   public void testNull() {
157     try {
158       map.putInstance((TypeToken) null, new Integer(1));
159       fail();
160     } catch (NullPointerException expected) {
161     }
162     map.putInstance(Integer.class, null);
163     assertNull(map.get(Integer.class));
164     assertNull(map.getInstance(Integer.class));
165 
166     map.putInstance(Long.class, null);
167     assertNull(map.get(Long.class));
168     assertNull(map.getInstance(Long.class));
169   }
170 
171   public void testPrimitiveAndWrapper() {
172     assertNull(map.getInstance(int.class));
173     assertNull(map.getInstance(Integer.class));
174 
175     assertNull(map.putInstance(int.class, 0));
176     assertNull(map.putInstance(Integer.class, 1));
177     assertEquals(2, map.size());
178 
179     assertEquals(0, (int) map.getInstance(int.class));
180     assertEquals(1, (int) map.getInstance(Integer.class));
181 
182     assertEquals(0, (int) map.putInstance(int.class, null));
183     assertEquals(1, (int) map.putInstance(Integer.class, null));
184 
185     assertNull(map.getInstance(int.class));
186     assertNull(map.getInstance(Integer.class));
187     assertEquals(2, map.size());
188   }
189 
190   public void testParameterizedType() {
191     TypeToken<ImmutableList<Integer>> type = new TypeToken<ImmutableList<Integer>>() {};
192     map.putInstance(type, ImmutableList.of(1));
193     assertEquals(1, map.size());
194     assertEquals(ImmutableList.of(1), map.getInstance(type));
195   }
196 
197   public void testGenericArrayType() {
198     @SuppressWarnings("unchecked") // Trying to test generic array
199     ImmutableList<Integer>[] array = new ImmutableList[] {ImmutableList.of(1)};
200     TypeToken<ImmutableList<Integer>[]> type = new TypeToken<ImmutableList<Integer>[]>() {};
201     map.putInstance(type, array);
202     assertEquals(1, map.size());
203     assertThat(map.getInstance(type)).asList().has().exactly(array[0]).inOrder();
204   }
205 
206   public void testWildcardType() {
207     TypeToken<ImmutableList<?>> type = new TypeToken<ImmutableList<?>>() {};
208     map.putInstance(type, ImmutableList.of(1));
209     assertEquals(1, map.size());
210     assertEquals(ImmutableList.of(1), map.getInstance(type));
211   }
212 
213   public void testGetInstance_withTypeVariable() {
214     try {
215       map.getInstance(this.<Number>anyIterableType());
216       fail();
217     } catch (IllegalArgumentException expected) {}
218   }
219 
220   public void testPutInstance_withTypeVariable() {
221     try {
222       map.putInstance(this.<Integer>anyIterableType(), ImmutableList.of(1));
223       fail();
224     } catch (IllegalArgumentException expected) {}
225   }
226 
227   private <T> TypeToken<Iterable<T>> anyIterableType() {
228     return new TypeToken<Iterable<T>>() {};
229   }
230 }