001: // Copyright 2007 The Apache Software Foundation
002: //
003: // Licensed under the Apache License, Version 2.0 (the "License");
004: // you may not use this file except in compliance with the License.
005: // You may obtain a copy of the License at
006: //
007: // http://www.apache.org/licenses/LICENSE-2.0
008: //
009: // Unless required by applicable law or agreed to in writing, software
010: // distributed under the License is distributed on an "AS IS" BASIS,
011: // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
012: // See the License for the specific language governing permissions and
013: // limitations under the License.
014:
015: package org.apache.tapestry.ioc.util;
016:
017: import static org.apache.tapestry.ioc.internal.util.CollectionFactory.newCaseInsensitiveMap;
018:
019: import java.io.ByteArrayInputStream;
020: import java.io.ByteArrayOutputStream;
021: import java.io.ObjectInputStream;
022: import java.io.ObjectOutputStream;
023: import java.util.Arrays;
024: import java.util.Collections;
025: import java.util.ConcurrentModificationException;
026: import java.util.Iterator;
027: import java.util.List;
028: import java.util.Map;
029: import java.util.NoSuchElementException;
030: import java.util.Set;
031:
032: import org.apache.tapestry.ioc.internal.util.CollectionFactory;
033: import org.testng.Assert;
034: import org.testng.annotations.Test;
035:
036: public class CaseInsensitiveMapTest extends Assert {
037: @Test
038: public void basic_get_put_remove() {
039: Map<String, String> map = newCaseInsensitiveMap();
040:
041: String value = "flintstone";
042:
043: map.put("fred", value);
044:
045: assertEquals(map.toString(), "{fred=flintstone}");
046:
047: assertSame(map.get("fred"), value);
048: assertSame(map.get("Fred"), value);
049:
050: assertSame(map.remove("FRED"), value);
051:
052: assertFalse(map.containsKey("fred"));
053:
054: assertTrue(map.isEmpty());
055: }
056:
057: @Test
058: public void copy_map_constructor() {
059: Map<String, String> map = newCaseInsensitiveMap();
060:
061: map.put("fred", "flintstone");
062: map.put("barney", "rubble");
063: map.put("wilma", "flinstone");
064: map.put("betty", "rubble");
065:
066: Map<String, String> copy = newCaseInsensitiveMap(map);
067:
068: assertEquals(copy, map);
069: }
070:
071: @Test
072: public void put_with_different_case_replaces() {
073: Map<String, String> map = newCaseInsensitiveMap();
074:
075: map.put("fred", "flintstone");
076:
077: String value = "Murray";
078:
079: map.put("Fred", value);
080:
081: assertEquals(map.size(), 1);
082:
083: assertSame(map.get("fred"), value);
084:
085: assertEquals(map.toString(), "{Fred=Murray}");
086: }
087:
088: @Test
089: public void get_with_missing_key_is_null() {
090: Map<String, String> map = newCaseInsensitiveMap();
091:
092: map.put("fred", "flintstone");
093:
094: assertNull(map.get("barney"));
095: }
096:
097: @SuppressWarnings("unchecked")
098: @Test
099: public void get_with_non_string_key_is_null() {
100: Map map = newCaseInsensitiveMap();
101:
102: map.put("fred", "flintstone");
103:
104: assertNull(map.get(this ));
105: }
106:
107: /**
108: * Add a large number of keys which should stress the code that adds and expands values into the
109: * map.
110: */
111: @Test
112: public void expansion_of_internal_entry_array() {
113: Map<String, Integer> map = newCaseInsensitiveMap();
114:
115: int COUNT = 2000;
116:
117: for (int i = 0; i < COUNT; i++) {
118: assertNull(map.put("key_" + i, i));
119: }
120:
121: // Now check that the values are still there.
122:
123: for (int i = 0; i < COUNT; i++) {
124: assertEquals(map.get("KEY_" + i).intValue(), i);
125: }
126:
127: assertEquals(map.size(), COUNT);
128: assertEquals(map.entrySet().size(), COUNT);
129:
130: map.clear();
131:
132: assertEquals(map.size(), 0);
133: }
134:
135: @Test
136: public void change_value_via_entry_set() {
137: Map<String, String> map = newCaseInsensitiveMap();
138:
139: map.put("fred", "flintstone");
140:
141: Map.Entry<String, String> me = map.entrySet().iterator().next();
142:
143: String value = "murray";
144:
145: me.setValue(value);
146:
147: assertSame(map.get("fred"), value);
148: }
149:
150: @Test(expectedExceptions={ConcurrentModificationException.class})
151: public void iterator_fail_fast_after_remove() {
152: Map<String, String> map = newCaseInsensitiveMap();
153:
154: map.put("fred", "flintstone");
155: map.put("barney", "rubble");
156: map.put("wilma", "flinstone");
157: map.put("betty", "rubble");
158:
159: Iterator i = map.entrySet().iterator();
160:
161: i.next();
162:
163: map.remove("betty");
164:
165: i.next();
166: }
167:
168: @Test(expectedExceptions={ConcurrentModificationException.class})
169: public void iterator_fail_fast_on_next() {
170: Map<String, String> map = newCaseInsensitiveMap();
171:
172: map.put("fred", "flintstone");
173: map.put("barney", "rubble");
174: map.put("wilma", "flinstone");
175: map.put("betty", "rubble");
176:
177: Iterator<Map.Entry<String, String>> i = map.entrySet()
178: .iterator();
179:
180: while (i.hasNext()) {
181: if (i.next().getKey().equals("betty"))
182: map.put("pebbles", "flintstone");
183: }
184: }
185:
186: @Test
187: public void iterator_may_remove_without_concurrent_exception() {
188: Map<String, String> map = newCaseInsensitiveMap();
189:
190: map.put("fred", "flintstone");
191: map.put("barney", "rubble");
192: map.put("wilma", "flinstone");
193: map.put("betty", "rubble");
194:
195: Iterator<Map.Entry<String, String>> i = map.entrySet()
196: .iterator();
197:
198: while (i.hasNext()) {
199: if (i.next().getKey().equals("wilma"))
200: i.remove();
201: }
202:
203: List<String> keys = CollectionFactory.newList(map.keySet());
204: Collections.sort(keys);
205:
206: assertEquals(keys, Arrays.asList("barney", "betty", "fred"));
207: }
208:
209: @Test
210: public void contains_via_entry_set() {
211: Map<String, String> map = newCaseInsensitiveMap();
212:
213: map.put("fred", "flintstone");
214: map.put("barney", "rubble");
215: map.put("wilma", "flinstone");
216: map.put("betty", "rubble");
217:
218: Set<Map.Entry<String, String>> entrySet = map.entrySet();
219:
220: assertTrue(entrySet.contains(newMapEntry("fred", "flintstone")));
221: assertTrue(entrySet.contains(newMapEntry("Fred", "flintstone")));
222:
223: assertFalse(entrySet
224: .contains(newMapEntry("Zaphod", "Beeblebox")));
225: assertFalse(entrySet.contains(newMapEntry("fred", "murray")));
226: }
227:
228: @Test
229: public void remove_via_entry_set() {
230: Map<String, String> map = newCaseInsensitiveMap();
231:
232: map.put("fred", "flintstone");
233: map.put("barney", "rubble");
234: map.put("wilma", "flinstone");
235: map.put("betty", "rubble");
236:
237: Set<Map.Entry<String, String>> entrySet = map.entrySet();
238:
239: assertFalse(entrySet.remove(newMapEntry("Zaphod", "Beeblebox")));
240: assertFalse(entrySet.remove(newMapEntry("fred", "murray")));
241:
242: assertTrue(entrySet.remove(newMapEntry("Fred", "flintstone")));
243: }
244:
245: @Test
246: public void null_key() {
247: Map<String, String> map = newCaseInsensitiveMap();
248:
249: map.put(null, "NULL");
250:
251: assertEquals(map.get(null), "NULL");
252: }
253:
254: @Test
255: public void clear_entry_set_clears_map() {
256: Map<String, String> map = newCaseInsensitiveMap();
257:
258: map.put("fred", "flintstone");
259:
260: map.entrySet().clear();
261:
262: assertTrue(map.isEmpty());
263: }
264:
265: @Test(expectedExceptions={NoSuchElementException.class})
266: public void next_after_last_entry_is_failure() {
267: Map<String, String> map = newCaseInsensitiveMap();
268:
269: map.put("fred", "flintstone");
270:
271: Iterator i = map.entrySet().iterator();
272:
273: while (i.hasNext())
274: i.next();
275:
276: i.next();
277: }
278:
279: @Test
280: public void entry_set_iterator_sees_all_keys() {
281: Map<String, String> map = newCaseInsensitiveMap();
282:
283: map.put("fred", "flintstone");
284: map.put("barney", "rubble");
285: map.put("wilma", "flinstone");
286: map.put("betty", "rubble");
287:
288: Iterator<Map.Entry<String, String>> i = map.entrySet()
289: .iterator();
290: List<String> keys = CollectionFactory.newList();
291:
292: while (i.hasNext())
293: keys.add(i.next().getKey());
294:
295: Collections.sort(keys);
296:
297: assertEquals(keys, Arrays.asList("barney", "betty", "fred",
298: "wilma"));
299: }
300:
301: @SuppressWarnings("unchecked")
302: @Test
303: public void serialize_deserialize() throws Exception {
304: Map<String, String> map = newCaseInsensitiveMap();
305:
306: map.put("fred", "flintstone");
307: map.put("barney", "rubble");
308: map.put("wilma", "flinstone");
309: map.put("betty", "rubble");
310:
311: ByteArrayOutputStream baos = new ByteArrayOutputStream();
312: ObjectOutputStream oos = new ObjectOutputStream(baos);
313:
314: oos.writeObject(map);
315: oos.close();
316:
317: ByteArrayInputStream bais = new ByteArrayInputStream(baos
318: .toByteArray());
319: ObjectInputStream ois = new ObjectInputStream(bais);
320:
321: Map<String, String> copy = (Map<String, String>) ois
322: .readObject();
323:
324: assertEquals(copy, map);
325: }
326:
327: @SuppressWarnings("unchecked")
328: private <K, V> Map.Entry<K, V> newMapEntry(final K key,
329: final V value) {
330: return new Map.Entry() {
331:
332: public Object getKey() {
333: return key;
334: }
335:
336: public Object getValue() {
337: return value;
338: }
339:
340: public Object setValue(Object value) {
341: throw new UnsupportedOperationException();
342: }
343:
344: };
345: }
346: }
|