• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Protocol Buffers - Google's data interchange format
2 // Copyright 2008 Google Inc.  All rights reserved.
3 // https://developers.google.com/protocol-buffers/
4 //
5 // Redistribution and use in source and binary forms, with or without
6 // modification, are permitted provided that the following conditions are
7 // met:
8 //
9 //     * Redistributions of source code must retain the above copyright
10 // notice, this list of conditions and the following disclaimer.
11 //     * Redistributions in binary form must reproduce the above
12 // copyright notice, this list of conditions and the following disclaimer
13 // in the documentation and/or other materials provided with the
14 // distribution.
15 //     * Neither the name of Google Inc. nor the names of its
16 // contributors may be used to endorse or promote products derived from
17 // this software without specific prior written permission.
18 //
19 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 
31 package com.google.protobuf;
32 
33 import java.util.ArrayList;
34 import java.util.Arrays;
35 import java.util.HashMap;
36 import java.util.Iterator;
37 import java.util.List;
38 import java.util.Map;
39 import java.util.Set;
40 import java.util.TreeSet;
41 import junit.framework.TestCase;
42 
43 /** @author darick@google.com Darick Tong */
44 public class SmallSortedMapTest extends TestCase {
45   // java.util.AbstractMap.SimpleEntry is private in JDK 1.5. We re-implement it
46   // here for JDK 1.5 users.
47   private static class SimpleEntry<K, V> implements Map.Entry<K, V> {
48     private final K key;
49     private V value;
50 
SimpleEntry(K key, V value)51     SimpleEntry(K key, V value) {
52       this.key = key;
53       this.value = value;
54     }
55 
56     @Override
getKey()57     public K getKey() {
58       return key;
59     }
60 
61     @Override
getValue()62     public V getValue() {
63       return value;
64     }
65 
66     @Override
setValue(V value)67     public V setValue(V value) {
68       V oldValue = this.value;
69       this.value = value;
70       return oldValue;
71     }
72 
eq(Object o1, Object o2)73     private static boolean eq(Object o1, Object o2) {
74       return o1 == null ? o2 == null : o1.equals(o2);
75     }
76 
77     @Override
equals(Object o)78     public boolean equals(Object o) {
79       if (!(o instanceof Map.Entry)) {
80         return false;
81       }
82       Map.Entry e = (Map.Entry) o;
83       return eq(key, e.getKey()) && eq(value, e.getValue());
84     }
85 
86     @Override
hashCode()87     public int hashCode() {
88       return ((key == null) ? 0 : key.hashCode()) ^ ((value == null) ? 0 : value.hashCode());
89     }
90   }
91 
testPutAndGetArrayEntriesOnly()92   public void testPutAndGetArrayEntriesOnly() {
93     runPutAndGetTest(3);
94   }
95 
testPutAndGetOverflowEntries()96   public void testPutAndGetOverflowEntries() {
97     runPutAndGetTest(6);
98   }
99 
runPutAndGetTest(int numElements)100   private void runPutAndGetTest(int numElements) {
101     // Test with even and odd arraySize
102     SmallSortedMap<Integer, Integer> map1 = SmallSortedMap.newInstanceForTest(3);
103     SmallSortedMap<Integer, Integer> map2 = SmallSortedMap.newInstanceForTest(4);
104     SmallSortedMap<Integer, Integer> map3 = SmallSortedMap.newInstanceForTest(3);
105     SmallSortedMap<Integer, Integer> map4 = SmallSortedMap.newInstanceForTest(4);
106 
107     // Test with puts in ascending order.
108     for (int i = 0; i < numElements; i++) {
109       assertNull(map1.put(i, i + 1));
110       assertNull(map2.put(i, i + 1));
111     }
112     // Test with puts in descending order.
113     for (int i = numElements - 1; i >= 0; i--) {
114       assertNull(map3.put(i, i + 1));
115       assertNull(map4.put(i, i + 1));
116     }
117 
118     assertEquals(Math.min(3, numElements), map1.getNumArrayEntries());
119     assertEquals(Math.min(4, numElements), map2.getNumArrayEntries());
120     assertEquals(Math.min(3, numElements), map3.getNumArrayEntries());
121     assertEquals(Math.min(4, numElements), map4.getNumArrayEntries());
122 
123     List<SmallSortedMap<Integer, Integer>> allMaps =
124         new ArrayList<SmallSortedMap<Integer, Integer>>();
125     allMaps.add(map1);
126     allMaps.add(map2);
127     allMaps.add(map3);
128     allMaps.add(map4);
129 
130     for (SmallSortedMap<Integer, Integer> map : allMaps) {
131       assertEquals(numElements, map.size());
132       for (int i = 0; i < numElements; i++) {
133         assertEquals(Integer.valueOf(i + 1), map.get(i));
134       }
135     }
136 
137     assertEquals(map1, map2);
138     assertEquals(map2, map3);
139     assertEquals(map3, map4);
140   }
141 
testReplacingPut()142   public void testReplacingPut() {
143     SmallSortedMap<Integer, Integer> map = SmallSortedMap.newInstanceForTest(3);
144     for (int i = 0; i < 6; i++) {
145       assertNull(map.put(i, i + 1));
146       assertNull(map.remove(i + 1));
147     }
148     for (int i = 0; i < 6; i++) {
149       assertEquals(Integer.valueOf(i + 1), map.put(i, i + 2));
150     }
151   }
152 
testRemove()153   public void testRemove() {
154     SmallSortedMap<Integer, Integer> map = SmallSortedMap.newInstanceForTest(3);
155     for (int i = 0; i < 6; i++) {
156       assertNull(map.put(i, i + 1));
157       assertNull(map.remove(i + 1));
158     }
159 
160     assertEquals(3, map.getNumArrayEntries());
161     assertEquals(3, map.getNumOverflowEntries());
162     assertEquals(6, map.size());
163     assertEquals(makeSortedKeySet(0, 1, 2, 3, 4, 5), map.keySet());
164 
165     assertEquals(Integer.valueOf(2), map.remove(1));
166     assertEquals(3, map.getNumArrayEntries());
167     assertEquals(2, map.getNumOverflowEntries());
168     assertEquals(5, map.size());
169     assertEquals(makeSortedKeySet(0, 2, 3, 4, 5), map.keySet());
170 
171     assertEquals(Integer.valueOf(5), map.remove(4));
172     assertEquals(3, map.getNumArrayEntries());
173     assertEquals(1, map.getNumOverflowEntries());
174     assertEquals(4, map.size());
175     assertEquals(makeSortedKeySet(0, 2, 3, 5), map.keySet());
176 
177     assertEquals(Integer.valueOf(4), map.remove(3));
178     assertEquals(3, map.getNumArrayEntries());
179     assertEquals(0, map.getNumOverflowEntries());
180     assertEquals(3, map.size());
181     assertEquals(makeSortedKeySet(0, 2, 5), map.keySet());
182 
183     assertNull(map.remove(3));
184     assertEquals(3, map.getNumArrayEntries());
185     assertEquals(0, map.getNumOverflowEntries());
186     assertEquals(3, map.size());
187 
188     assertEquals(Integer.valueOf(1), map.remove(0));
189     assertEquals(2, map.getNumArrayEntries());
190     assertEquals(0, map.getNumOverflowEntries());
191     assertEquals(2, map.size());
192   }
193 
testClear()194   public void testClear() {
195     SmallSortedMap<Integer, Integer> map = SmallSortedMap.newInstanceForTest(3);
196     for (int i = 0; i < 6; i++) {
197       assertNull(map.put(i, i + 1));
198     }
199     map.clear();
200     assertEquals(0, map.getNumArrayEntries());
201     assertEquals(0, map.getNumOverflowEntries());
202     assertEquals(0, map.size());
203   }
204 
testGetArrayEntryAndOverflowEntries()205   public void testGetArrayEntryAndOverflowEntries() {
206     SmallSortedMap<Integer, Integer> map = SmallSortedMap.newInstanceForTest(3);
207     for (int i = 0; i < 6; i++) {
208       assertNull(map.put(i, i + 1));
209     }
210     assertEquals(3, map.getNumArrayEntries());
211     for (int i = 0; i < 3; i++) {
212       Map.Entry<Integer, Integer> entry = map.getArrayEntryAt(i);
213       assertEquals(Integer.valueOf(i), entry.getKey());
214       assertEquals(Integer.valueOf(i + 1), entry.getValue());
215     }
216     Iterator<Map.Entry<Integer, Integer>> it = map.getOverflowEntries().iterator();
217     for (int i = 3; i < 6; i++) {
218       assertTrue(it.hasNext());
219       Map.Entry<Integer, Integer> entry = it.next();
220       assertEquals(Integer.valueOf(i), entry.getKey());
221       assertEquals(Integer.valueOf(i + 1), entry.getValue());
222     }
223     assertFalse(it.hasNext());
224   }
225 
testEntrySetContains()226   public void testEntrySetContains() {
227     SmallSortedMap<Integer, Integer> map = SmallSortedMap.newInstanceForTest(3);
228     for (int i = 0; i < 6; i++) {
229       assertNull(map.put(i, i + 1));
230     }
231     Set<Map.Entry<Integer, Integer>> entrySet = map.entrySet();
232     for (int i = 0; i < 6; i++) {
233       assertTrue(entrySet.contains(new SimpleEntry<Integer, Integer>(i, i + 1)));
234       assertFalse(entrySet.contains(new SimpleEntry<Integer, Integer>(i, i)));
235     }
236   }
237 
testEntrySetAdd()238   public void testEntrySetAdd() {
239     SmallSortedMap<Integer, Integer> map = SmallSortedMap.newInstanceForTest(3);
240     Set<Map.Entry<Integer, Integer>> entrySet = map.entrySet();
241     for (int i = 0; i < 6; i++) {
242       Map.Entry<Integer, Integer> entry = new SimpleEntry<Integer, Integer>(i, i + 1);
243       assertTrue(entrySet.add(entry));
244       assertFalse(entrySet.add(entry));
245     }
246     for (int i = 0; i < 6; i++) {
247       assertEquals(Integer.valueOf(i + 1), map.get(i));
248     }
249     assertEquals(3, map.getNumArrayEntries());
250     assertEquals(3, map.getNumOverflowEntries());
251     assertEquals(6, map.size());
252   }
253 
testEntrySetRemove()254   public void testEntrySetRemove() {
255     SmallSortedMap<Integer, Integer> map = SmallSortedMap.newInstanceForTest(3);
256     Set<Map.Entry<Integer, Integer>> entrySet = map.entrySet();
257     for (int i = 0; i < 6; i++) {
258       assertNull(map.put(i, i + 1));
259     }
260     for (int i = 0; i < 6; i++) {
261       Map.Entry<Integer, Integer> entry = new SimpleEntry<Integer, Integer>(i, i + 1);
262       assertTrue(entrySet.remove(entry));
263       assertFalse(entrySet.remove(entry));
264     }
265     assertTrue(map.isEmpty());
266     assertEquals(0, map.getNumArrayEntries());
267     assertEquals(0, map.getNumOverflowEntries());
268     assertEquals(0, map.size());
269   }
270 
testEntrySetClear()271   public void testEntrySetClear() {
272     SmallSortedMap<Integer, Integer> map = SmallSortedMap.newInstanceForTest(3);
273     for (int i = 0; i < 6; i++) {
274       assertNull(map.put(i, i + 1));
275     }
276     map.clear();
277     assertTrue(map.isEmpty());
278     assertEquals(0, map.getNumArrayEntries());
279     assertEquals(0, map.getNumOverflowEntries());
280     assertEquals(0, map.size());
281   }
282 
testEntrySetIteratorNext()283   public void testEntrySetIteratorNext() {
284     SmallSortedMap<Integer, Integer> map = SmallSortedMap.newInstanceForTest(3);
285     for (int i = 0; i < 6; i++) {
286       assertNull(map.put(i, i + 1));
287     }
288     Iterator<Map.Entry<Integer, Integer>> it = map.entrySet().iterator();
289     for (int i = 0; i < 6; i++) {
290       assertTrue(it.hasNext());
291       Map.Entry<Integer, Integer> entry = it.next();
292       assertEquals(Integer.valueOf(i), entry.getKey());
293       assertEquals(Integer.valueOf(i + 1), entry.getValue());
294     }
295     assertFalse(it.hasNext());
296   }
297 
testEntrySetIteratorRemove()298   public void testEntrySetIteratorRemove() {
299     SmallSortedMap<Integer, Integer> map = SmallSortedMap.newInstanceForTest(3);
300     for (int i = 0; i < 6; i++) {
301       assertNull(map.put(i, i + 1));
302     }
303     Iterator<Map.Entry<Integer, Integer>> it = map.entrySet().iterator();
304     for (int i = 0; i < 6; i++) {
305       assertTrue(map.containsKey(i));
306       it.next();
307       it.remove();
308       assertFalse(map.containsKey(i));
309       assertEquals(6 - i - 1, map.size());
310     }
311   }
312 
testMapEntryModification()313   public void testMapEntryModification() {
314     SmallSortedMap<Integer, Integer> map = SmallSortedMap.newInstanceForTest(3);
315     for (int i = 0; i < 6; i++) {
316       assertNull(map.put(i, i + 1));
317     }
318     Iterator<Map.Entry<Integer, Integer>> it = map.entrySet().iterator();
319     for (int i = 0; i < 6; i++) {
320       Map.Entry<Integer, Integer> entry = it.next();
321       entry.setValue(i + 23);
322     }
323     for (int i = 0; i < 6; i++) {
324       assertEquals(Integer.valueOf(i + 23), map.get(i));
325     }
326   }
327 
testMakeImmutable()328   public void testMakeImmutable() {
329     SmallSortedMap<Integer, Integer> map = SmallSortedMap.newInstanceForTest(3);
330     for (int i = 0; i < 6; i++) {
331       assertNull(map.put(i, i + 1));
332     }
333     map.makeImmutable();
334     assertEquals(Integer.valueOf(1), map.get(0));
335     assertEquals(6, map.size());
336 
337     try {
338       map.put(23, 23);
339       fail("Expected UnsupportedOperationException");
340     } catch (UnsupportedOperationException expected) {
341     }
342 
343     Map<Integer, Integer> other = new HashMap<Integer, Integer>();
344     other.put(23, 23);
345     try {
346       map.putAll(other);
347       fail("Expected UnsupportedOperationException");
348     } catch (UnsupportedOperationException expected) {
349     }
350 
351     try {
352       map.remove(0);
353       fail("Expected UnsupportedOperationException");
354     } catch (UnsupportedOperationException expected) {
355     }
356 
357     try {
358       map.clear();
359       fail("Expected UnsupportedOperationException");
360     } catch (UnsupportedOperationException expected) {
361     }
362 
363     Set<Map.Entry<Integer, Integer>> entrySet = map.entrySet();
364     try {
365       entrySet.clear();
366       fail("Expected UnsupportedOperationException");
367     } catch (UnsupportedOperationException expected) {
368     }
369 
370     Iterator<Map.Entry<Integer, Integer>> it = entrySet.iterator();
371     while (it.hasNext()) {
372       Map.Entry<Integer, Integer> entry = it.next();
373       try {
374         entry.setValue(0);
375         fail("Expected UnsupportedOperationException");
376       } catch (UnsupportedOperationException expected) {
377       }
378       try {
379         it.remove();
380         fail("Expected UnsupportedOperationException");
381       } catch (UnsupportedOperationException expected) {
382       }
383     }
384 
385     Set<Integer> keySet = map.keySet();
386     try {
387       keySet.clear();
388       fail("Expected UnsupportedOperationException");
389     } catch (UnsupportedOperationException expected) {
390     }
391 
392     Iterator<Integer> keys = keySet.iterator();
393     while (keys.hasNext()) {
394       Integer key = keys.next();
395       try {
396         keySet.remove(key);
397         fail("Expected UnsupportedOperationException");
398       } catch (UnsupportedOperationException expected) {
399       }
400       try {
401         keys.remove();
402         fail("Expected UnsupportedOperationException");
403       } catch (UnsupportedOperationException expected) {
404       }
405     }
406   }
407 
makeSortedKeySet(Integer... keys)408   private Set<Integer> makeSortedKeySet(Integer... keys) {
409     return new TreeSet<Integer>(Arrays.<Integer>asList(keys));
410   }
411 }
412