View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.apache.commons.collections4.map;
18  
19  import static org.junit.jupiter.api.Assertions.assertSame;
20  import static org.junit.jupiter.api.Assertions.assertThrows;
21  
22  import java.util.ArrayList;
23  import java.util.Arrays;
24  import java.util.List;
25  import java.util.Map;
26  import java.util.Map.Entry;
27  import java.util.SortedMap;
28  import java.util.TreeMap;
29  
30  import org.apache.commons.collections4.BulkTest;
31  import org.junit.jupiter.api.Test;
32  
33  /**
34   * Tests {@link java.util.SortedMap}.
35   *
36   * @param <K> the key type.
37   * @param <V> the value type.
38   */
39  public abstract class AbstractSortedMapTest<K, V> extends AbstractMapTest<SortedMap<K, V>, K, V> {
40  
41      public static class TestHeadMap<K, V> extends TestViewMap<K, V> {
42          static final int SUBSIZE = 6;
43          final K toKey;
44  
45          public TestHeadMap(final AbstractMapTest<SortedMap<K, V>, K, V> main) {
46              super(main);
47              final Map<K, V> sm = main.makeFullMap();
48              for (final Entry<K, V> entry : sm.entrySet()) {
49                  this.subSortedKeys.add(entry.getKey());
50                  this.subSortedValues.add(entry.getValue());
51              }
52              this.toKey = this.subSortedKeys.get(SUBSIZE);
53              this.subSortedKeys.subList(SUBSIZE, this.subSortedKeys.size()).clear();
54              this.subSortedValues.subList(SUBSIZE, this.subSortedValues.size()).clear();
55              this.subSortedNewValues.addAll(Arrays.asList(main.getNewSampleValues()).subList(0, SUBSIZE));
56          }
57  
58          @Override
59          public String getCompatibilityVersion() {
60              return main.getCompatibilityVersion() + ".HeadMapView";
61          }
62  
63          @Override
64          public SortedMap<K, V> makeFullMap() {
65              return main.makeFullMap().headMap(toKey);
66          }
67  
68          @Override
69          public SortedMap<K, V> makeObject() {
70              // done this way so toKey is correctly set in the returned map
71              return main.makeObject().headMap(toKey);
72          }
73  
74          @Test
75          public void testHeadMapOutOfRange() {
76              if (!isPutAddSupported()) {
77                  return;
78              }
79              resetEmpty();
80              assertThrows(IllegalArgumentException.class, () -> getMap().put(toKey, subSortedValues.get(0)));
81              verify();
82          }
83  
84  //        public void testCreate() throws Exception {
85  //            Map map = makeEmptyMap();
86  //            writeExternalFormToDisk(
87  //                (java.io.Serializable) map,
88  //                "D:/dev/collections/data/test/FixedSizeSortedMap.emptyCollection.version3.1.HeadMapView.obj");
89  //            map = makeFullMap();
90  //            writeExternalFormToDisk(
91  //                (java.io.Serializable) map,
92  //                "D:/dev/collections/data/test/FixedSizeSortedMap.fullCollection.version3.1.HeadMapView.obj");
93  //        }
94      }
95  
96      public static class TestSubMap<K, V> extends TestViewMap<K, V> {
97          static final int SUBSIZE = 3;
98          final K fromKey;
99          final K toKey;
100 
101         public TestSubMap(final AbstractMapTest<SortedMap<K, V>, K, V> main) {
102             super(main);
103             final Map<K, V> sm = main.makeFullMap();
104             for (final Entry<K, V> entry : sm.entrySet()) {
105                 this.subSortedKeys.add(entry.getKey());
106                 this.subSortedValues.add(entry.getValue());
107             }
108             this.fromKey = this.subSortedKeys.get(SUBSIZE);
109             this.toKey = this.subSortedKeys.get(this.subSortedKeys.size() - SUBSIZE);
110 
111             this.subSortedKeys.subList(0, SUBSIZE).clear();
112             this.subSortedKeys.subList(this.subSortedKeys.size() - SUBSIZE, this.subSortedKeys.size()).clear();
113 
114             this.subSortedValues.subList(0, SUBSIZE).clear();
115             this.subSortedValues.subList(this.subSortedValues.size() - SUBSIZE, this.subSortedValues.size()).clear();
116 
117             this.subSortedNewValues.addAll(Arrays.asList(main.getNewSampleValues()).subList(
118                 SUBSIZE, this.main.getNewSampleValues().length - SUBSIZE));
119         }
120 
121         @Override
122         public String getCompatibilityVersion() {
123             return main.getCompatibilityVersion() + ".SubMapView";
124         }
125 
126         @Override
127         public SortedMap<K, V> makeFullMap() {
128             return main.makeFullMap().subMap(fromKey, toKey);
129         }
130 
131         @Override
132         public SortedMap<K, V> makeObject() {
133             // done this way so toKey is correctly set in the returned map
134             return main.makeObject().subMap(fromKey, toKey);
135         }
136 
137         @Test
138         public void testSubMapOutOfRange() {
139             if (!isPutAddSupported()) {
140                 return;
141             }
142             resetEmpty();
143             assertThrows(IllegalArgumentException.class, () -> getMap().put(toKey, subSortedValues.get(0)));
144             verify();
145         }
146 
147 //        public void testCreate() throws Exception {
148 //            Map map = makeEmptyMap();
149 //            writeExternalFormToDisk(
150 //                (java.io.Serializable) map,
151 //                "D:/dev/collections/data/test/TransformedSortedMap.emptyCollection.version3.1.SubMapView.obj");
152 //            map = makeFullMap();
153 //            writeExternalFormToDisk(
154 //                (java.io.Serializable) map,
155 //                "D:/dev/collections/data/test/TransformedSortedMap.fullCollection.version3.1.SubMapView.obj");
156 //        }
157     }
158 
159     public static class TestTailMap<K, V> extends TestViewMap<K, V> {
160         static final int SUBSIZE = 6;
161         final K fromKey;
162         final K invalidKey;
163 
164         public TestTailMap(final AbstractMapTest<SortedMap<K, V>, K, V> main) {
165             super(main);
166             final Map<K, V> sm = main.makeFullMap();
167             for (final Entry<K, V> entry : sm.entrySet()) {
168                 this.subSortedKeys.add(entry.getKey());
169                 this.subSortedValues.add(entry.getValue());
170             }
171             this.fromKey = this.subSortedKeys.get(this.subSortedKeys.size() - SUBSIZE);
172             this.invalidKey = this.subSortedKeys.get(this.subSortedKeys.size() - SUBSIZE - 1);
173             this.subSortedKeys.subList(0, this.subSortedKeys.size() - SUBSIZE).clear();
174             this.subSortedValues.subList(0, this.subSortedValues.size() - SUBSIZE).clear();
175             this.subSortedNewValues.addAll(Arrays.asList(main.getNewSampleValues()).subList(0, SUBSIZE));
176         }
177 
178         @Override
179         public String getCompatibilityVersion() {
180             return main.getCompatibilityVersion() + ".TailMapView";
181         }
182 
183         @Override
184         public SortedMap<K, V> makeFullMap() {
185             return main.makeFullMap().tailMap(fromKey);
186         }
187 
188         @Override
189         public SortedMap<K, V> makeObject() {
190             // done this way so toKey is correctly set in the returned map
191             return main.makeObject().tailMap(fromKey);
192         }
193 
194         @Test
195         public void testTailMapOutOfRange() {
196             if (!isPutAddSupported()) {
197                 return;
198             }
199             resetEmpty();
200             assertThrows(IllegalArgumentException.class, () -> getMap().put(invalidKey, subSortedValues.get(0)));
201             verify();
202         }
203 
204 //        public void testCreate() throws Exception {
205 //            Map map = makeEmptyMap();
206 //            writeExternalFormToDisk(
207 //                (java.io.Serializable) map,
208 //                "D:/dev/collections/data/test/FixedSizeSortedMap.emptyCollection.version3.1.TailMapView.obj");
209 //            map = makeFullMap();
210 //            writeExternalFormToDisk(
211 //                (java.io.Serializable) map,
212 //                "D:/dev/collections/data/test/FixedSizeSortedMap.fullCollection.version3.1.TailMapView.obj");
213 //        }
214     }
215 
216     public abstract static class TestViewMap<K, V> extends AbstractSortedMapTest<K, V> {
217         protected final AbstractMapTest<SortedMap<K, V>, K, V> main;
218         protected final List<K> subSortedKeys = new ArrayList<>();
219         protected final List<V> subSortedValues = new ArrayList<>();
220         protected final List<V> subSortedNewValues = new ArrayList<>();
221 
222         public TestViewMap(final AbstractMapTest<SortedMap<K, V>, K, V> main) {
223             this.main = main;
224         }
225 
226         @Override
227         public BulkTest bulkTestHeadMap() {
228             return null;  // block infinite recursion
229         }
230 
231         @Override
232         public BulkTest bulkTestSubMap() {
233             return null;  // block infinite recursion
234         }
235 
236         @Override
237         public BulkTest bulkTestTailMap() {
238             return null;  // block infinite recursion
239         }
240 
241         @Override
242         @SuppressWarnings("unchecked")
243         public V[] getNewSampleValues() {
244             return (V[]) subSortedNewValues.toArray();
245         }
246 
247         @Override
248         @SuppressWarnings("unchecked")
249         public K[] getSampleKeys() {
250             return (K[]) subSortedKeys.toArray();
251         }
252 
253         @Override
254         @SuppressWarnings("unchecked")
255         public V[] getSampleValues() {
256             return (V[]) subSortedValues.toArray();
257         }
258 
259         @Override
260         public boolean isAllowNullKey() {
261             return main.isAllowNullKey();
262         }
263 
264         @Override
265         public boolean isAllowNullValue() {
266             return main.isAllowNullValue();
267         }
268 
269         @Override
270         public boolean isAllowNullValueGet() {
271             return main.isAllowNullValueGet();
272         }
273 
274         @Override
275         public boolean isAllowNullValuePut() {
276             return main.isAllowNullValuePut();
277         }
278 
279         @Override
280         public boolean isPutAddSupported() {
281             return main.isPutAddSupported();
282         }
283 
284         @Override
285         public boolean isPutChangeSupported() {
286             return main.isPutChangeSupported();
287         }
288 
289         @Override
290         public boolean isRemoveSupported() {
291             return main.isRemoveSupported();
292         }
293 
294         @Override
295         public boolean isTestSerialization() {
296             return false;
297         }
298 //        public void testSimpleSerialization() throws Exception {
299 //            if (main.isSubMapViewsSerializable() == false) return;
300 //            super.testSimpleSerialization();
301 //        }
302 //        public void testSerializeDeserializeThenCompare() throws Exception {
303 //            if (main.isSubMapViewsSerializable() == false) return;
304 //            super.testSerializeDeserializeThenCompare();
305 //        }
306 //        public void testEmptyMapCompatibility() throws Exception {
307 //            if (main.isSubMapViewsSerializable() == false) return;
308 //            super.testEmptyMapCompatibility();
309 //        }
310 //        public void testFullMapCompatibility() throws Exception {
311 //            if (main.isSubMapViewsSerializable() == false) return;
312 //            super.testFullMapCompatibility();
313 //        }
314 
315         @Override
316         public void resetEmpty() {
317             // needed to init verify correctly
318             main.resetEmpty();
319             super.resetEmpty();
320         }
321 
322         @Override
323         public void resetFull() {
324             // needed to init verify correctly
325             main.resetFull();
326             super.resetFull();
327         }
328 
329         @Override
330         public void verify() {
331             // cross verify changes on view with changes on main map
332             super.verify();
333             main.verify();
334         }
335     }
336 
337     public BulkTest bulkTestHeadMap() {
338         return new TestHeadMap<>(this);
339     }
340 
341     public BulkTest bulkTestSubMap() {
342         return new TestSubMap<>(this);
343     }
344 
345     public BulkTest bulkTestTailMap() {
346         return new TestTailMap<>(this);
347     }
348 
349     /**
350      * {@inheritDoc}
351      */
352     @Override
353     public SortedMap<K, V> getConfirmed() {
354         return (SortedMap<K, V>) super.getConfirmed();
355     }
356 
357     /**
358      * {@inheritDoc}
359      */
360     @Override
361     public SortedMap<K, V> getMap() {
362         return super.getMap();
363     }
364 
365     /**
366      * Can't sort null keys.
367      *
368      * @return false
369      */
370     @Override
371     public boolean isAllowNullKey() {
372         return false;
373     }
374 
375     /**
376      * SortedMap uses TreeMap as its known comparison.
377      *
378      * @return a map that is known to be valid
379      */
380     @Override
381     public SortedMap<K, V> makeConfirmedMap() {
382         return new TreeMap<>();
383     }
384 
385     /**
386      * {@inheritDoc}
387      */
388     @Override
389     public SortedMap<K, V> makeFullMap() {
390         return super.makeFullMap();
391     }
392 
393     /**
394      * {@inheritDoc}
395      */
396     @Override
397     public abstract SortedMap<K, V> makeObject();
398 
399     @Test
400     public void testComparator() {
401 //        SortedMap<K, V> sm = makeFullMap();
402         // no tests I can think of
403     }
404 
405     @Test
406     public void testFirstKey() {
407         final SortedMap<K, V> sm = makeFullMap();
408         assertSame(sm.keySet().iterator().next(), sm.firstKey());
409     }
410 
411     @Test
412     public void testLastKey() {
413         final SortedMap<K, V> sm = makeFullMap();
414         K obj = null;
415         for (final K k : sm.keySet()) {
416             obj = k;
417         }
418         assertSame(obj, sm.lastKey());
419     }
420 
421 }