1
2
3
4
5
6
7
8
9
10
11
12
13
14
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 java.util.Collection;
25 import java.util.Collections;
26 import java.util.Comparator;
27 import java.util.Iterator;
28 import java.util.Map;
29 import java.util.SortedMap;
30
31 import org.junit.Test;
32
33 public class CopyOnWriteSortedMapTest {
34
35 private static final class ReverseComparator<T> implements Comparator<T> {
36 private final Comparator<T> comparator;
37
38 ReverseComparator(final Comparator<T> comparator) {
39 this.comparator = comparator;
40 }
41
42 public int compare(final T o1, final T o2) {
43 return 0 - comparator.compare(o1, o2);
44 };
45 }
46
47 private static final class StringComparator implements Comparator<String> {
48 public int compare(final String o1, final String o2) {
49 return o1.compareTo(o2);
50 };
51 }
52
53 @Test
54 public void mapConstructor() {
55 final MapBuilder<String, String> builder = MapBuilder.builder();
56 builder.add("one", "value").add("two", "value").add("three", "value");
57 final SortedMap<String, String> map = CopyOnWriteSortedMap.newTreeMap(builder.toMap());
58
59 assertEquals(3, map.size());
60 }
61
62 @Test
63 public void mapComparatorConstructor() {
64 final MapBuilder<String, String> builder = MapBuilder.builder();
65 builder.add("one", "value").add("two", "value").add("three", "value");
66 final SortedMap<String, String> map = CopyOnWriteSortedMap.newTreeMap(builder.toMap(), new ReverseComparator<String>(new StringComparator()));
67
68 assertEquals(3, map.size());
69 }
70
71 @SuppressWarnings("unchecked")
72 @Test(expected = IllegalArgumentException.class)
73 public void mapNullConstructor() {
74 CopyOnWriteSortedMap.newTreeMap((Map) null);
75 }
76
77 @SuppressWarnings("unchecked")
78 @Test(expected = IllegalArgumentException.class)
79 public void comparatorNullConstructor() {
80 CopyOnWriteSortedMap.newTreeMap((Comparator) null);
81 }
82
83 @Test(expected = IllegalArgumentException.class)
84 public void mapNullComparatorConstructor() {
85 CopyOnWriteSortedMap.newTreeMap(null, new StringComparator());
86 }
87
88 @Test(expected = IllegalArgumentException.class)
89 public void mapComparatorNullConstructor() {
90 CopyOnWriteSortedMap.newTreeMap(Collections.emptyMap(), null);
91 }
92
93 @Test
94 public void comparator() {
95 final Comparator<String> comparator = new StringComparator();
96 final SortedMap<String, String> map = CopyOnWriteSortedMap.newTreeMap(comparator);
97 assertNotNull(map.comparator());
98 assertEquals(comparator, map.comparator());
99 map.put("one", "two");
100 assertNotNull(map.comparator());
101 assertEquals(1, map.size());
102 assertEquals(comparator, map.comparator());
103 map.put("two", "value");
104 assertEquals(2, map.size());
105 map.put("three", "value");
106 assertEquals(3, map.size());
107 }
108
109 @Test
110 public void firstKey() {
111 final SortedMap<String, String> map = CopyOnWriteSortedMap.newTreeMap();
112 map.put("one", "value");
113 map.put("two", "value");
114 map.put("three", "value");
115 assertEquals("one", map.firstKey());
116 }
117
118 @Test
119 public void firstKeyWithReverse() {
120 final MapBuilder<String, String> builder = MapBuilder.builder();
121 builder.add("one", "value").add("two", "value").add("three", "value");
122 final SortedMap<String, String> map = CopyOnWriteSortedMap.newTreeMap(builder.toMap(), new ReverseComparator<String>(new StringComparator()));
123 map.put("one", "value");
124 map.put("two", "value");
125 map.put("three", "value");
126
127 assertEquals(3, map.size());
128 assertEquals("two", map.firstKey());
129 }
130
131 @Test
132 public void lastKey() {
133 final SortedMap<String, String> map = CopyOnWriteSortedMap.newTreeMap();
134 map.put("one", "value");
135 map.put("two", "value");
136 map.put("three", "value");
137 assertEquals("two", map.lastKey());
138 }
139
140 @Test
141 public void lastKeyWithReverse() {
142 final MapBuilder<String, String> builder = MapBuilder.builder();
143 builder.add("one", "value").add("two", "value").add("three", "value");
144 final SortedMap<String, String> map = CopyOnWriteSortedMap.newTreeMap(builder.toMap(), new ReverseComparator<String>(new StringComparator()));
145
146 assertEquals(3, map.size());
147 assertEquals("one", map.lastKey());
148 }
149
150 @Test
151 public void headMap() {
152 final SortedMap<String, String> map = CopyOnWriteSortedMap.newTreeMap();
153 map.put("1", "one");
154 map.put("2", "two");
155 map.put("3", "three");
156 final SortedMap<String, String> headMap = map.headMap("3");
157 assertEquals(2, headMap.size());
158 assertTrue(headMap.containsKey("1"));
159 assertTrue(headMap.containsKey("2"));
160 assertTrue(headMap.containsValue("one"));
161 assertTrue(headMap.containsValue("two"));
162
163 assertUnmodifiableMap(headMap, "3", "three");
164 }
165
166 @Test
167 public void tailMap() {
168 final SortedMap<String, String> map = CopyOnWriteSortedMap.newTreeMap();
169 map.put("1", "one");
170 map.put("2", "two");
171 map.put("3", "three");
172 final SortedMap<String, String> tailMap = map.tailMap("2");
173 assertEquals(2, tailMap.size());
174 assertTrue(tailMap.containsKey("2"));
175 assertTrue(tailMap.containsKey("3"));
176 assertTrue(tailMap.containsValue("two"));
177 assertTrue(tailMap.containsValue("three"));
178
179 assertUnmodifiableMap(tailMap, "1", "one");
180 }
181
182 @Test
183 public void subMap() {
184 final CopyOnWriteSortedMap<String, String> map = CopyOnWriteSortedMap.newTreeMap();
185 map.put("1", "one");
186 map.put("2", "two");
187 map.put("3", "three");
188 map.put("4", "four");
189 final SortedMap<String, String> subMap = map.subMap("2", "4");
190 assertEquals(2, subMap.size());
191 assertTrue(subMap.containsKey("2"));
192 assertTrue(subMap.containsKey("3"));
193 assertTrue(subMap.containsValue("two"));
194 assertTrue(subMap.containsValue("three"));
195
196 assertUnmodifiableMap(subMap, "1", "one");
197 }
198
199 @Test
200 public void serializableTreeMap() {
201 final CopyOnWriteSortedMap<Object, Object> map = CopyOnWriteSortedMap.newTreeMap();
202 CopyOnWriteMapTest.assertMutableMapSerializable(map);
203 }
204
205 static <K, V> void assertUnmodifiableMap(final Map<K, V> map, final K key, final V value) {
206 assertThrowsUnsupportedOp(new Runnable() {
207 public void run() {
208 map.put(key, value);
209 }
210 });
211 assertThrowsUnsupportedOp(new Runnable() {
212 public void run() {
213 map.remove(key);
214 }
215 });
216 assertThrowsUnsupportedOp(new Runnable() {
217 public void run() {
218 map.clear();
219 }
220 });
221
222 assertUnmodifiableCollection(map.keySet(), key);
223 assertUnmodifiableCollection(map.values(), value);
224 }
225
226 private static <T> void assertUnmodifiableCollection(final Collection<T> coll, final T element) {
227 assertThrowsUnsupportedOp(new Runnable() {
228 public void run() {
229 coll.clear();
230 }
231 });
232
233 assertThrowsUnsupportedOp(new Runnable() {
234 public void run() {
235 coll.remove(element);
236 }
237 });
238
239 assertThrowsUnsupportedOp(new Runnable() {
240 public void run() {
241 coll.removeAll(Collections.EMPTY_LIST);
242 }
243 });
244
245 assertThrowsUnsupportedOp(new Runnable() {
246 public void run() {
247 coll.add(element);
248 }
249 });
250
251 final Collection<T> empty = Collections.emptyList();
252 assertThrowsUnsupportedOp(new Runnable() {
253 public void run() {
254 coll.addAll(empty);
255 }
256 });
257
258 assertThrowsUnsupportedOp(new Runnable() {
259 public void run() {
260 coll.retainAll(empty);
261 }
262 });
263
264 assertThrowsUnsupportedOp(new Runnable() {
265 public void run() {
266 final Iterator<?> it = coll.iterator();
267 it.next();
268 it.remove();
269 }
270 });
271 }
272
273 static void assertThrowsUnsupportedOp(final Runnable runnable) {
274 try {
275 runnable.run();
276 fail("should have thrown UnsupportedOperationException");
277 } catch (final UnsupportedOperationException ignore) {}
278 }
279 }