| /** |
| * 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 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 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 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")); |
| |
| 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(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>(); |
| |
| // this is wrong!!! you should use entrySet |
| for (String key : map.keySet()) { |
| Object value = map.get(key); |
| other.put(key, value); |
| } |
| |
| // now the keys will be in lower case |
| assertEquals(true, other.containsKey("foo")); |
| assertEquals(false, other.containsKey("Foo")); |
| assertEquals(true, other.containsKey("bar")); |
| assertEquals(false, 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 |
| map.putAll(foo); |
| |
| latch.countDown(); |
| } |
| }); |
| } |
| |
| 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); |
| } |
| |
| |
| } |