/** * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.camel.util; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; import junit.framework.TestCase; /** * @version */ public class CaseInsensitiveMapTest extends TestCase { public void testLookupCaseAgnostic() { Map<String, Object> map = new CaseInsensitiveMap(); assertNull(map.get("foo")); map.put("foo", "cheese"); assertEquals("cheese", map.get("foo")); assertEquals("cheese", map.get("Foo")); assertEquals("cheese", map.get("FOO")); } public void testLookupCaseAgnosticAddHeader() { Map<String, Object> map = new CaseInsensitiveMap(); assertNull(map.get("foo")); map.put("foo", "cheese"); assertEquals("cheese", map.get("foo")); assertEquals("cheese", map.get("Foo")); assertEquals("cheese", map.get("FOO")); assertNull(map.get("unknown")); map.put("bar", "beer"); assertEquals("beer", map.get("bar")); assertEquals("beer", map.get("Bar")); assertEquals("beer", map.get("BAR")); assertNull(map.get("unknown")); } public void testLookupCaseAgnosticAddHeader2() { Map<String, Object> map = new CaseInsensitiveMap(); assertNull(map.get("foo")); map.put("foo", "cheese"); assertEquals("cheese", map.get("FOO")); assertEquals("cheese", map.get("foo")); assertEquals("cheese", map.get("Foo")); assertNull(map.get("unknown")); map.put("bar", "beer"); assertEquals("beer", map.get("BAR")); assertEquals("beer", map.get("bar")); assertEquals("beer", map.get("Bar")); assertNull(map.get("unknown")); } public void testLookupCaseAgnosticAddHeaderRemoveHeader() { Map<String, Object> map = new CaseInsensitiveMap(); assertNull(map.get("foo")); map.put("foo", "cheese"); assertEquals("cheese", map.get("foo")); assertEquals("cheese", map.get("Foo")); assertEquals("cheese", map.get("FOO")); assertNull(map.get("unknown")); map.put("bar", "beer"); assertEquals("beer", map.get("bar")); assertEquals("beer", map.get("Bar")); assertEquals("beer", map.get("BAR")); assertNull(map.get("unknown")); map.remove("bar"); assertNull(map.get("bar")); assertNull(map.get("unknown")); } public void testSetWithDifferentCase() { Map<String, Object> map = new CaseInsensitiveMap(); assertNull(map.get("foo")); map.put("foo", "cheese"); map.put("Foo", "bar"); assertEquals("bar", map.get("FOO")); assertEquals("bar", map.get("foo")); assertEquals("bar", map.get("Foo")); } public void testRemoveWithDifferentCase() { Map<String, Object> map = new CaseInsensitiveMap(); assertNull(map.get("foo")); map.put("foo", "cheese"); map.put("Foo", "bar"); assertEquals("bar", map.get("FOO")); assertEquals("bar", map.get("foo")); assertEquals("bar", map.get("Foo")); map.remove("FOO"); assertEquals(null, map.get("foo")); assertEquals(null, map.get("Foo")); assertEquals(null, map.get("FOO")); assertTrue(map.isEmpty()); } public void testPutAll() { Map<String, Object> map = new CaseInsensitiveMap(); assertNull(map.get("foo")); Map<String, Object> other = new CaseInsensitiveMap(); other.put("Foo", "cheese"); other.put("bar", 123); map.putAll(other); assertEquals("cheese", map.get("FOO")); assertEquals("cheese", map.get("foo")); assertEquals("cheese", map.get("Foo")); assertEquals(123, map.get("BAR")); assertEquals(123, map.get("bar")); assertEquals(123, map.get("BaR")); // key case should be preserved Map<String, Object> keys = new HashMap<String, Object>(); keys.putAll(map); assertEquals("cheese", keys.get("Foo")); assertNull(keys.get("foo")); assertNull(keys.get("FOO")); assertEquals(123, keys.get("bar")); assertNull(keys.get("Bar")); assertNull(keys.get("BAR")); } public void testPutAllOther() { Map<String, Object> map = new CaseInsensitiveMap(); assertNull(map.get("foo")); Map<String, Object> other = new HashMap<String, Object>(); other.put("Foo", "cheese"); other.put("bar", 123); map.putAll(other); assertEquals("cheese", map.get("FOO")); assertEquals("cheese", map.get("foo")); assertEquals("cheese", map.get("Foo")); assertEquals(123, map.get("BAR")); assertEquals(123, map.get("bar")); assertEquals(123, map.get("BaR")); } public void testPutAllEmpty() { Map<String, Object> map = new CaseInsensitiveMap(); map.put("foo", "cheese"); Map<String, Object> other = new HashMap<String, Object>(); map.putAll(other); assertEquals("cheese", map.get("FOO")); assertEquals("cheese", map.get("foo")); assertEquals("cheese", map.get("Foo")); assertEquals(1, map.size()); } public void testConstructFromOther() { Map<String, Object> other = new HashMap<String, Object>(); other.put("Foo", "cheese"); other.put("bar", 123); Map<String, Object> map = new CaseInsensitiveMap(other); assertEquals("cheese", map.get("FOO")); assertEquals("cheese", map.get("foo")); assertEquals("cheese", map.get("Foo")); assertEquals(123, map.get("BAR")); assertEquals(123, map.get("bar")); assertEquals(123, map.get("BaR")); } public void testKeySet() { Map<String, Object> map = new CaseInsensitiveMap(); map.put("Foo", "cheese"); map.put("BAR", 123); map.put("baZ", "beer"); Set<String> keys = map.keySet(); // we should be able to lookup no matter what case assertTrue(keys.contains("Foo")); assertTrue(keys.contains("foo")); assertTrue(keys.contains("FOO")); assertTrue(keys.contains("BAR")); assertTrue(keys.contains("bar")); assertTrue(keys.contains("Bar")); assertTrue(keys.contains("baZ")); assertTrue(keys.contains("baz")); assertTrue(keys.contains("Baz")); assertTrue(keys.contains("BAZ")); } public void testRetainKeysCopyToAnotherMap() { Map<String, Object> map = new CaseInsensitiveMap(); map.put("Foo", "cheese"); map.put("BAR", 123); map.put("baZ", "beer"); Map<String, Object> other = new HashMap<String, Object>(map); // we should retain the cases of the original keys // when its copied to another map assertTrue(other.containsKey("Foo")); assertFalse(other.containsKey("foo")); assertFalse(other.containsKey("FOO")); assertTrue(other.containsKey("BAR")); assertFalse(other.containsKey("bar")); assertFalse(other.containsKey("Bar")); assertTrue(other.containsKey("baZ")); assertFalse(other.containsKey("baz")); assertFalse(other.containsKey("Baz")); assertFalse(other.containsKey("BAZ")); } public void testValues() { Map<String, Object> map = new CaseInsensitiveMap(); map.put("Foo", "cheese"); map.put("BAR", "123"); map.put("baZ", "Beer"); Iterator<Object> it = map.values().iterator(); // should be String values assertEquals("String", it.next().getClass().getSimpleName()); assertEquals("String", it.next().getClass().getSimpleName()); assertEquals("String", it.next().getClass().getSimpleName()); Collection<Object> values = map.values(); assertEquals(3, values.size()); assertTrue(values.contains("cheese")); assertTrue(values.contains("123")); assertTrue(values.contains("Beer")); } public void testRomeks() { Map<String, Object> map = new CaseInsensitiveMap(); map.put("foo", "cheese"); assertEquals(1, map.size()); assertEquals("cheese", map.get("fOo")); assertEquals(true, map.containsKey("foo")); assertEquals(true, map.containsKey("FOO")); assertEquals(true, map.keySet().contains("FOO")); assertEquals(true, map.keySet().contains("FoO")); assertEquals(true, map.keySet().contains("Foo")); assertEquals(true, map.keySet().contains("foo")); assertEquals(true, map.keySet().contains("fOO")); map.put("FOO", "cake"); assertEquals(1, map.size()); assertEquals(true, map.containsKey("foo")); assertEquals(true, map.containsKey("FOO")); assertEquals("cake", map.get("fOo")); } public void testRomeksUsingRegularHashMap() { Map<String, Object> map = new HashMap<String, Object>(); map.put("foo", "cheese"); assertEquals(1, map.size()); assertEquals(null, map.get("fOo")); assertEquals(true, map.containsKey("foo")); assertEquals(false, map.containsKey("FOO")); assertEquals(false, map.keySet().contains("FOO")); map.put("FOO", "cake"); assertEquals(2, map.size()); assertEquals(true, map.containsKey("foo")); assertEquals(true, map.containsKey("FOO")); assertEquals(null, map.get("fOo")); assertEquals("cheese", map.get("foo")); assertEquals("cake", map.get("FOO")); } public void testRomeksTransferredToHashMapAfterwards() { Map<String, Object> map = new CaseInsensitiveMap(); map.put("Foo", "cheese"); map.put("FOO", "cake"); assertEquals(1, map.size()); assertEquals(true, map.containsKey("foo")); assertEquals(true, map.containsKey("FOO")); Map<String, Object> other = new HashMap<String, Object>(map); assertEquals(false, other.containsKey("foo")); assertEquals(false, other.containsKey("FOO")); // CaseInsensitiveMap preserves the original keys, which would be the 1st key we put assertEquals(true, other.containsKey("Foo")); assertEquals(1, other.size()); } public void testSerialization() throws Exception { CaseInsensitiveMap testMap = new CaseInsensitiveMap(); testMap.put("key", "value"); // force entry set to be created which could cause the map to be non serializable testMap.entrySet(); ByteArrayOutputStream bStream = new ByteArrayOutputStream(); ObjectOutputStream objStream = new ObjectOutputStream(bStream); objStream.writeObject(testMap); ObjectInputStream inStream = new ObjectInputStream(new ByteArrayInputStream(bStream.toByteArray())); CaseInsensitiveMap testMapCopy = (CaseInsensitiveMap) inStream.readObject(); assertTrue(testMapCopy.containsKey("key")); } public void testCopyToAnotherMapPreserveKeyCaseEntrySet() { Map<String, Object> map = new CaseInsensitiveMap(); map.put("Foo", "cheese"); map.put("BAR", "cake"); assertEquals(2, map.size()); assertEquals(true, map.containsKey("foo")); assertEquals(true, map.containsKey("bar")); Map<String, Object> other = new HashMap<String, Object>(); for (Map.Entry<String, Object> entry : map.entrySet()) { String key = entry.getKey(); Object value = entry.getValue(); other.put(key, value); } assertEquals(false, other.containsKey("foo")); assertEquals(true, other.containsKey("Foo")); assertEquals(false, other.containsKey("bar")); assertEquals(true, other.containsKey("BAR")); assertEquals(2, other.size()); } public void testCopyToAnotherMapPreserveKeyCasePutAll() { Map<String, Object> map = new CaseInsensitiveMap(); map.put("Foo", "cheese"); map.put("BAR", "cake"); assertEquals(2, map.size()); assertEquals(true, map.containsKey("foo")); assertEquals(true, map.containsKey("bar")); Map<String, Object> other = new HashMap<String, Object>(); other.putAll(map); assertEquals(false, other.containsKey("foo")); assertEquals(true, other.containsKey("Foo")); assertEquals(false, other.containsKey("bar")); assertEquals(true, other.containsKey("BAR")); assertEquals(2, other.size()); } public void testCopyToAnotherMapPreserveKeyCaseCtr() { Map<String, Object> map = new CaseInsensitiveMap(); map.put("Foo", "cheese"); map.put("BAR", "cake"); assertEquals(2, map.size()); assertEquals(true, map.containsKey("foo")); assertEquals(true, map.containsKey("bar")); Map<String, Object> other = new HashMap<String, Object>(map); assertEquals(false, other.containsKey("foo")); assertEquals(true, other.containsKey("Foo")); assertEquals(false, other.containsKey("bar")); assertEquals(true, other.containsKey("BAR")); assertEquals(2, other.size()); } public void testCopyToAnotherMapPreserveKeyKeySet() { Map<String, Object> map = new CaseInsensitiveMap(); map.put("Foo", "cheese"); map.put("BAR", "cake"); assertEquals(2, map.size()); assertEquals(true, map.containsKey("foo")); assertEquals(true, map.containsKey("bar")); Map<String, Object> other = new HashMap<String, Object>(); for (String key : map.keySet()) { Object value = map.get(key); other.put(key, value); } // the original case of the keys should be preserved assertEquals(false, other.containsKey("foo")); assertEquals(true, other.containsKey("Foo")); assertEquals(false, other.containsKey("bar")); assertEquals(true, other.containsKey("BAR")); assertEquals(2, other.size()); } public void testConcurrent() throws Exception { ExecutorService service = Executors.newFixedThreadPool(5); final CountDownLatch latch = new CountDownLatch(1000); final Map<String, Object> map = new CaseInsensitiveMap(); // do some stuff concurrently for (int i = 0; i < 1000; i++) { final int count = i; service.submit(new Runnable() { public void run() { Map<String, Object> foo = new CaseInsensitiveMap(); foo.put("counter" + count, count); foo.put("foo", 123); foo.put("bar", 456); foo.put("cake", "cheese"); // copy foo to map as map is a shared resource synchronized (map) { map.putAll(foo); } latch.countDown(); } }); } assertTrue(latch.await(10, TimeUnit.SECONDS)); assertEquals(1003, map.size()); assertEquals(true, map.containsKey("counter0")); assertEquals(true, map.containsKey("counter500")); assertEquals(true, map.containsKey("counter999")); assertEquals(123, map.get("FOO")); assertEquals(456, map.get("Bar")); assertEquals("cheese", map.get("cAKe")); service.shutdownNow(); } public void testCopyMapWithCamelHeadersTest() throws Exception { Map<String, Object> map = new CaseInsensitiveMap(); map.put("CamelA", "A"); map.put("CamelB", "B"); map.put("CamelC", "C"); // retain maps so we can profile that the map doesn't duplicate // camel keys as they are intern List<Map<?, ?>> maps = new ArrayList<Map<?, ?>>(); for (int i = 0; i < 10000; i++) { Map<String, Object> copy = new CaseInsensitiveMap(map); assertEquals(3, copy.size()); assertEquals("A", copy.get("CamelA")); assertEquals("B", copy.get("CamelB")); assertEquals("C", copy.get("CamelC")); maps.add(copy); } assertEquals(10000, maps.size()); assertEquals(3, map.size()); assertEquals("A", map.get("CamelA")); assertEquals("B", map.get("CamelB")); assertEquals("C", map.get("CamelC")); // use a memory profiler to see memory allocation // often you may want to give it time to run so you // have chance to capture memory snapshot in profiler // Thread.sleep(9999999); } }