1 /* 2 * Copyright (C) 2008 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.testing; 18 19 import static com.google.common.base.Preconditions.checkNotNull; 20 import static com.google.common.collect.testing.features.MapFeature.ALLOWS_NULL_KEYS; 21 import static com.google.common.collect.testing.features.MapFeature.ALLOWS_NULL_VALUES; 22 23 import com.google.common.collect.Lists; 24 import com.google.common.collect.Maps; 25 import com.google.common.collect.testing.features.CollectionFeature; 26 import com.google.common.collect.testing.features.CollectionSize; 27 import com.google.common.collect.testing.features.Feature; 28 import com.google.common.collect.testing.features.MapFeature; 29 import java.util.AbstractMap; 30 import java.util.AbstractSet; 31 import java.util.Collection; 32 import java.util.Collections; 33 import java.util.HashMap; 34 import java.util.Iterator; 35 import java.util.List; 36 import java.util.Map; 37 import java.util.Map.Entry; 38 import java.util.Set; 39 import java.util.function.Predicate; 40 import junit.framework.Test; 41 import junit.framework.TestCase; 42 import junit.framework.TestSuite; 43 44 /** 45 * Tests {@link MapTestSuiteBuilder} by using it against maps that have various negative behaviors. 46 * 47 * @author George van den Driessche 48 */ 49 public final class MapTestSuiteBuilderTests extends TestCase { MapTestSuiteBuilderTests()50 private MapTestSuiteBuilderTests() {} 51 suite()52 public static Test suite() { 53 TestSuite suite = new TestSuite(MapTestSuiteBuilderTests.class.getSimpleName()); 54 suite.addTest(testsForHashMapNullKeysForbidden()); 55 suite.addTest(testsForHashMapNullValuesForbidden()); 56 return suite; 57 } 58 59 private abstract static class WrappedHashMapGenerator extends TestStringMapGenerator { 60 @Override create(Entry<String, String>[] entries)61 protected final Map<String, String> create(Entry<String, String>[] entries) { 62 HashMap<String, String> map = Maps.newHashMap(); 63 for (Entry<String, String> entry : entries) { 64 map.put(entry.getKey(), entry.getValue()); 65 } 66 return wrap(map); 67 } 68 wrap(HashMap<String, String> map)69 abstract Map<String, String> wrap(HashMap<String, String> map); 70 } 71 wrappedHashMapTests( WrappedHashMapGenerator generator, String name, Feature<?>... features)72 private static TestSuite wrappedHashMapTests( 73 WrappedHashMapGenerator generator, String name, Feature<?>... features) { 74 List<Feature<?>> featuresList = Lists.newArrayList(features); 75 Collections.addAll( 76 featuresList, 77 MapFeature.GENERAL_PURPOSE, 78 CollectionFeature.SUPPORTS_ITERATOR_REMOVE, 79 CollectionSize.ANY); 80 return MapTestSuiteBuilder.using(generator) 81 .named(name) 82 .withFeatures(featuresList) 83 .createTestSuite(); 84 } 85 86 // TODO: consider being null-hostile in these tests 87 testsForHashMapNullKeysForbidden()88 private static Test testsForHashMapNullKeysForbidden() { 89 return wrappedHashMapTests( 90 new WrappedHashMapGenerator() { 91 @Override 92 Map<String, String> wrap(final HashMap<String, String> map) { 93 if (map.containsKey(null)) { 94 throw new NullPointerException(); 95 } 96 return new AbstractMap<String, String>() { 97 @Override 98 public Set<Entry<String, String>> entrySet() { 99 return map.entrySet(); 100 } 101 102 @Override 103 public String put(String key, String value) { 104 checkNotNull(key); 105 return map.put(key, value); 106 } 107 }; 108 } 109 }, 110 "HashMap w/out null keys", 111 ALLOWS_NULL_VALUES); 112 } 113 114 private static Test testsForHashMapNullValuesForbidden() { 115 return wrappedHashMapTests( 116 new WrappedHashMapGenerator() { 117 @Override 118 Map<String, String> wrap(final HashMap<String, String> map) { 119 if (map.containsValue(null)) { 120 throw new NullPointerException(); 121 } 122 123 return new AbstractMap<String, String>() { 124 @Override 125 public Set<Entry<String, String>> entrySet() { 126 return new EntrySet(); 127 } 128 129 @Override 130 public int hashCode() { 131 return map.hashCode(); 132 } 133 134 @Override 135 public boolean equals(Object o) { 136 return map.equals(o); 137 } 138 139 @Override 140 public String toString() { 141 return map.toString(); 142 } 143 144 @Override 145 public String remove(Object key) { 146 return map.remove(key); 147 } 148 149 @Override 150 public boolean remove(Object key, Object value) { 151 return map.remove(key, value); 152 } 153 154 class EntrySet extends AbstractSet<Map.Entry<String, String>> { 155 @Override 156 public Iterator<Entry<String, String>> iterator() { 157 return new Iterator<Entry<String, String>>() { 158 159 final Iterator<Entry<String, String>> iterator = map.entrySet().iterator(); 160 161 @Override 162 public void remove() { 163 iterator.remove(); 164 } 165 166 @Override 167 public boolean hasNext() { 168 return iterator.hasNext(); 169 } 170 171 @Override 172 public Entry<String, String> next() { 173 return transform(iterator.next()); 174 } 175 176 private Entry<String, String> transform(final Entry<String, String> next) { 177 return new Entry<String, String>() { 178 179 @Override 180 public String setValue(String value) { 181 checkNotNull(value); 182 return next.setValue(value); 183 } 184 185 @Override 186 public String getValue() { 187 return next.getValue(); 188 } 189 190 @Override 191 public String getKey() { 192 return next.getKey(); 193 } 194 195 @Override 196 public boolean equals(Object obj) { 197 return next.equals(obj); 198 } 199 200 @Override 201 public int hashCode() { 202 return next.hashCode(); 203 } 204 }; 205 } 206 }; 207 } 208 209 @Override 210 public int size() { 211 return map.size(); 212 } 213 214 @Override 215 public boolean remove(Object o) { 216 return map.entrySet().remove(o); 217 } 218 219 @Override 220 public boolean removeIf(Predicate<? super Entry<String, String>> filter) { 221 return map.entrySet().removeIf(filter); 222 } 223 224 @Override 225 public boolean containsAll(Collection<?> c) { 226 return map.entrySet().containsAll(c); 227 } 228 229 @Override 230 public boolean removeAll(Collection<?> c) { 231 return map.entrySet().removeAll(c); 232 } 233 234 @Override 235 public boolean retainAll(Collection<?> c) { 236 return map.entrySet().retainAll(c); 237 } 238 239 @Override 240 public int hashCode() { 241 return map.entrySet().hashCode(); 242 } 243 244 @Override 245 public boolean equals(Object o) { 246 return map.entrySet().equals(o); 247 } 248 249 @Override 250 public String toString() { 251 return map.entrySet().toString(); 252 } 253 } 254 255 @Override 256 public String put(String key, String value) { 257 checkNotNull(value); 258 return map.put(key, value); 259 } 260 }; 261 } 262 }, 263 "HashMap w/out null values", 264 ALLOWS_NULL_KEYS); 265 } 266 } 267