1   /**
2    * Copyright 2008 Atlassian Pty Ltd 
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.atlassian.util.concurrent;
18  
19  import static org.junit.Assert.assertEquals;
20  import static org.junit.Assert.assertNotNull;
21  import static org.junit.Assert.assertTrue;
22  import static org.junit.Assert.fail;
23  
24  import org.junit.Test;
25  
26  import java.util.Collection;
27  import java.util.Collections;
28  import java.util.Iterator;
29  import java.util.Map;
30  import java.util.SortedMap;
31  
32  public class CopyOnWriteSortedMapTest {
33  
34      @Test public void comparator() {
35          final SortedMap<String, String> map = CopyOnWriteMaps.newTreeMap(String.CASE_INSENSITIVE_ORDER);
36          assertNotNull(map.comparator());
37          assertEquals(String.CASE_INSENSITIVE_ORDER, map.comparator());
38          map.put("one", "two");
39          assertNotNull(map.comparator());
40          assertEquals(String.CASE_INSENSITIVE_ORDER, map.comparator());
41      }
42  
43      @Test public void firstKey() {
44          final SortedMap<String, String> map = CopyOnWriteMaps.newTreeMap();
45          map.put("one", "value");
46          map.put("two", "value");
47          map.put("three", "value");
48          assertEquals("one", map.firstKey());
49      }
50  
51      @Test public void lastKey() {
52          final SortedMap<String, String> map = CopyOnWriteMaps.newTreeMap();
53          map.put("one", "value");
54          map.put("two", "value");
55          map.put("three", "value");
56          assertEquals("two", map.lastKey());
57      }
58  
59      @Test public void headMap() {
60          final SortedMap<String, String> map = CopyOnWriteMaps.newTreeMap();
61          map.put("1", "one");
62          map.put("2", "two");
63          map.put("3", "three");
64          final SortedMap<String, String> headMap = map.headMap("3");
65          assertEquals(2, headMap.size());
66          assertTrue(headMap.containsKey("1"));
67          assertTrue(headMap.containsKey("2"));
68          assertTrue(headMap.containsValue("one"));
69          assertTrue(headMap.containsValue("two"));
70  
71          assertUnmodifiableMap(headMap, "3", "three");
72      }
73  
74      @Test public void tailMap() {
75          final SortedMap<String, String> map = CopyOnWriteMaps.newTreeMap();
76          map.put("1", "one");
77          map.put("2", "two");
78          map.put("3", "three");
79          final SortedMap<String, String> tailMap = map.tailMap("2");
80          assertEquals(2, tailMap.size());
81          assertTrue(tailMap.containsKey("2"));
82          assertTrue(tailMap.containsKey("3"));
83          assertTrue(tailMap.containsValue("two"));
84          assertTrue(tailMap.containsValue("three"));
85  
86          assertUnmodifiableMap(tailMap, "1", "one");
87      }
88  
89      @Test public void subMap() {
90          final CopyOnWriteSortedMap<String, String> map = CopyOnWriteMaps.newTreeMap();
91          map.put("1", "one");
92          map.put("2", "two");
93          map.put("3", "three");
94          map.put("4", "four");
95          final SortedMap<String, String> subMap = map.subMap("2", "4");
96          assertEquals(2, subMap.size());
97          assertTrue(subMap.containsKey("2"));
98          assertTrue(subMap.containsKey("3"));
99          assertTrue(subMap.containsValue("two"));
100         assertTrue(subMap.containsValue("three"));
101 
102         assertUnmodifiableMap(subMap, "1", "one");
103     }
104 
105     static <K, V> void assertUnmodifiableMap(final Map<K, V> map, final K key, final V value) {
106         assertThrowsUnsupportedOp(new Runnable() {
107             public void run() {
108                 map.put(key, value);
109             }
110         });
111         assertThrowsUnsupportedOp(new Runnable() {
112             public void run() {
113                 map.remove(key);
114             }
115         });
116         assertThrowsUnsupportedOp(new Runnable() {
117             public void run() {
118                 map.clear();
119             }
120         });
121 
122         assertUnmodifiableCollection(map.keySet(), key);
123         assertUnmodifiableCollection(map.values(), value);
124     }
125 
126     private static <T> void assertUnmodifiableCollection(final Collection<T> coll, final T element) {
127         assertThrowsUnsupportedOp(new Runnable() {
128             public void run() {
129                 coll.clear();
130             }
131         });
132 
133         assertThrowsUnsupportedOp(new Runnable() {
134             public void run() {
135                 coll.remove(element);
136             }
137         });
138 
139         assertThrowsUnsupportedOp(new Runnable() {
140             public void run() {
141                 coll.removeAll(Collections.EMPTY_LIST);
142             }
143         });
144 
145         assertThrowsUnsupportedOp(new Runnable() {
146             public void run() {
147                 coll.add(element);
148             }
149         });
150 
151         final Collection<T> empty = Collections.emptyList();
152         assertThrowsUnsupportedOp(new Runnable() {
153             public void run() {
154                 coll.addAll(empty);
155             }
156         });
157 
158         assertThrowsUnsupportedOp(new Runnable() {
159             public void run() {
160                 coll.retainAll(empty);
161             }
162         });
163 
164         assertThrowsUnsupportedOp(new Runnable() {
165             public void run() {
166                 final Iterator<?> it = coll.iterator();
167                 it.next();
168                 it.remove();
169             }
170         });
171     }
172 
173     static void assertThrowsUnsupportedOp(final Runnable runnable) {
174         try {
175             runnable.run();
176             fail("should have thrown UnsupportedOperationException");
177         }
178         catch (final UnsupportedOperationException ignore) {}
179     }
180 }