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 17package com.google.common.reflect; 18 19import static com.google.common.truth.Truth.assertThat; 20 21import com.google.common.collect.ImmutableList; 22import com.google.common.collect.ImmutableMap; 23import com.google.common.collect.testing.MapTestSuiteBuilder; 24import com.google.common.collect.testing.features.CollectionFeature; 25import com.google.common.collect.testing.features.CollectionSize; 26import com.google.common.collect.testing.features.MapFeature; 27import com.google.common.collect.testing.testers.MapPutTester; 28import com.google.common.reflect.ImmutableTypeToInstanceMapTest.TestTypeToInstanceMapGenerator; 29 30import junit.framework.Test; 31import junit.framework.TestCase; 32import junit.framework.TestSuite; 33 34import java.lang.reflect.Method; 35import java.util.Map; 36import java.util.Map.Entry; 37 38/** 39 * Unit test of {@link MutableTypeToInstanceMap}. 40 * 41 * @author Ben Yu 42 */ 43public 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} 231