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