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   * Abstract test class for {@link java.util.SortedMap} methods and contracts.
35   */
36  public abstract class AbstractSortedMapTest<K, V> extends AbstractMapTest<K, V> {
37  
38      public static class TestHeadMap<K, V> extends TestViewMap<K, V> {
39          static final int SUBSIZE = 6;
40          final K toKey;
41  
42          public TestHeadMap(final AbstractMapTest<K, V> main) {
43              super("SortedMap.HeadMap", main);
44              final Map<K, V> sm = main.makeFullMap();
45              for (final Entry<K, V> entry : sm.entrySet()) {
46                  this.subSortedKeys.add(entry.getKey());
47                  this.subSortedValues.add(entry.getValue());
48              }
49              this.toKey = this.subSortedKeys.get(SUBSIZE);
50              this.subSortedKeys.subList(SUBSIZE, this.subSortedKeys.size()).clear();
51              this.subSortedValues.subList(SUBSIZE, this.subSortedValues.size()).clear();
52              this.subSortedNewValues.addAll(Arrays.asList(main.getNewSampleValues()).subList(0, SUBSIZE));
53          }
54          @Override
55          public String getCompatibilityVersion() {
56              return main.getCompatibilityVersion() + ".HeadMapView";
57          }
58          @Override
59          public SortedMap<K, V> makeFullMap() {
60              return ((SortedMap<K, V>) main.makeFullMap()).headMap(toKey);
61          }
62  
63          @Override
64          public SortedMap<K, V> makeObject() {
65              // done this way so toKey is correctly set in the returned map
66              return ((SortedMap<K, V>) main.makeObject()).headMap(toKey);
67          }
68          @Test
69          public void testHeadMapOutOfRange() {
70              if (!isPutAddSupported()) {
71                  return;
72              }
73              resetEmpty();
74              assertThrows(IllegalArgumentException.class, () -> getMap().put(toKey, subSortedValues.get(0)));
75              verify();
76          }
77  
78  //        public void testCreate() throws Exception {
79  //            Map map = makeEmptyMap();
80  //            writeExternalFormToDisk(
81  //                (java.io.Serializable) map,
82  //                "D:/dev/collections/data/test/FixedSizeSortedMap.emptyCollection.version3.1.HeadMapView.obj");
83  //            map = makeFullMap();
84  //            writeExternalFormToDisk(
85  //                (java.io.Serializable) map,
86  //                "D:/dev/collections/data/test/FixedSizeSortedMap.fullCollection.version3.1.HeadMapView.obj");
87  //        }
88      }
89  
90      public static class TestSubMap<K, V> extends TestViewMap<K, V> {
91          static final int SUBSIZE = 3;
92          final K fromKey;
93          final K toKey;
94  
95          public TestSubMap(final AbstractMapTest<K, V> main) {
96              super("SortedMap.SubMap", main);
97              final Map<K, V> sm = main.makeFullMap();
98              for (final Entry<K, V> entry : sm.entrySet()) {
99                  this.subSortedKeys.add(entry.getKey());
100                 this.subSortedValues.add(entry.getValue());
101             }
102             this.fromKey = this.subSortedKeys.get(SUBSIZE);
103             this.toKey = this.subSortedKeys.get(this.subSortedKeys.size() - SUBSIZE);
104 
105             this.subSortedKeys.subList(0, SUBSIZE).clear();
106             this.subSortedKeys.subList(this.subSortedKeys.size() - SUBSIZE, this.subSortedKeys.size()).clear();
107 
108             this.subSortedValues.subList(0, SUBSIZE).clear();
109             this.subSortedValues.subList(this.subSortedValues.size() - SUBSIZE, this.subSortedValues.size()).clear();
110 
111             this.subSortedNewValues.addAll(Arrays.asList(main.getNewSampleValues()).subList(
112                 SUBSIZE, this.main.getNewSampleValues().length - SUBSIZE));
113         }
114 
115         @Override
116         public String getCompatibilityVersion() {
117             return main.getCompatibilityVersion() + ".SubMapView";
118         }
119         @Override
120         public SortedMap<K, V> makeFullMap() {
121             return ((SortedMap<K, V>) main.makeFullMap()).subMap(fromKey, toKey);
122         }
123 
124         @Override
125         public SortedMap<K, V> makeObject() {
126             // done this way so toKey is correctly set in the returned map
127             return ((SortedMap<K, V>) main.makeObject()).subMap(fromKey, toKey);
128         }
129         @Test
130         public void testSubMapOutOfRange() {
131             if (!isPutAddSupported()) {
132                 return;
133             }
134             resetEmpty();
135             assertThrows(IllegalArgumentException.class, () -> getMap().put(toKey, subSortedValues.get(0)));
136             verify();
137         }
138 
139 //        public void testCreate() throws Exception {
140 //            Map map = makeEmptyMap();
141 //            writeExternalFormToDisk(
142 //                (java.io.Serializable) map,
143 //                "D:/dev/collections/data/test/TransformedSortedMap.emptyCollection.version3.1.SubMapView.obj");
144 //            map = makeFullMap();
145 //            writeExternalFormToDisk(
146 //                (java.io.Serializable) map,
147 //                "D:/dev/collections/data/test/TransformedSortedMap.fullCollection.version3.1.SubMapView.obj");
148 //        }
149     }
150 
151     public static class TestTailMap<K, V> extends TestViewMap<K, V> {
152         static final int SUBSIZE = 6;
153         final K fromKey;
154         final K invalidKey;
155 
156         public TestTailMap(final AbstractMapTest<K, V> main) {
157             super("SortedMap.TailMap", main);
158             final Map<K, V> sm = main.makeFullMap();
159             for (final Entry<K, V> entry : sm.entrySet()) {
160                 this.subSortedKeys.add(entry.getKey());
161                 this.subSortedValues.add(entry.getValue());
162             }
163             this.fromKey = this.subSortedKeys.get(this.subSortedKeys.size() - SUBSIZE);
164             this.invalidKey = this.subSortedKeys.get(this.subSortedKeys.size() - SUBSIZE - 1);
165             this.subSortedKeys.subList(0, this.subSortedKeys.size() - SUBSIZE).clear();
166             this.subSortedValues.subList(0, this.subSortedValues.size() - SUBSIZE).clear();
167             this.subSortedNewValues.addAll(Arrays.asList(main.getNewSampleValues()).subList(0, SUBSIZE));
168         }
169         @Override
170         public String getCompatibilityVersion() {
171             return main.getCompatibilityVersion() + ".TailMapView";
172         }
173         @Override
174         public SortedMap<K, V> makeFullMap() {
175             return ((SortedMap<K, V>) main.makeFullMap()).tailMap(fromKey);
176         }
177 
178         @Override
179         public SortedMap<K, V> makeObject() {
180             // done this way so toKey is correctly set in the returned map
181             return ((SortedMap<K, V>) main.makeObject()).tailMap(fromKey);
182         }
183         @Test
184         public void testTailMapOutOfRange() {
185             if (!isPutAddSupported()) {
186                 return;
187             }
188             resetEmpty();
189             assertThrows(IllegalArgumentException.class, () -> getMap().put(invalidKey, subSortedValues.get(0)));
190             verify();
191         }
192 
193 //        public void testCreate() throws Exception {
194 //            Map map = makeEmptyMap();
195 //            writeExternalFormToDisk(
196 //                (java.io.Serializable) map,
197 //                "D:/dev/collections/data/test/FixedSizeSortedMap.emptyCollection.version3.1.TailMapView.obj");
198 //            map = makeFullMap();
199 //            writeExternalFormToDisk(
200 //                (java.io.Serializable) map,
201 //                "D:/dev/collections/data/test/FixedSizeSortedMap.fullCollection.version3.1.TailMapView.obj");
202 //        }
203     }
204 
205     public abstract static class TestViewMap<K, V> extends AbstractSortedMapTest<K, V> {
206         protected final AbstractMapTest<K, V> main;
207         protected final List<K> subSortedKeys = new ArrayList<>();
208         protected final List<V> subSortedValues = new ArrayList<>();
209         protected final List<V> subSortedNewValues = new ArrayList<>();
210 
211         public TestViewMap(final String name, final AbstractMapTest<K, V> main) {
212             super(name);
213             this.main = main;
214         }
215         @Override
216         public BulkTest bulkTestHeadMap() {
217             return null;  // block infinite recursion
218         }
219         @Override
220         public BulkTest bulkTestSubMap() {
221             return null;  // block infinite recursion
222         }
223         @Override
224         public BulkTest bulkTestTailMap() {
225             return null;  // block infinite recursion
226         }
227         @Override
228         @SuppressWarnings("unchecked")
229         public V[] getNewSampleValues() {
230             return (V[]) subSortedNewValues.toArray();
231         }
232         @Override
233         @SuppressWarnings("unchecked")
234         public K[] getSampleKeys() {
235             return (K[]) subSortedKeys.toArray();
236         }
237         @Override
238         @SuppressWarnings("unchecked")
239         public V[] getSampleValues() {
240             return (V[]) subSortedValues.toArray();
241         }
242 
243         @Override
244         public boolean isAllowNullKey() {
245             return main.isAllowNullKey();
246         }
247         @Override
248         public boolean isAllowNullValue() {
249             return main.isAllowNullValue();
250         }
251         @Override
252         public boolean isPutAddSupported() {
253             return main.isPutAddSupported();
254         }
255 
256         @Override
257         public boolean isPutChangeSupported() {
258             return main.isPutChangeSupported();
259         }
260         @Override
261         public boolean isRemoveSupported() {
262             return main.isRemoveSupported();
263         }
264         @Override
265         public boolean isTestSerialization() {
266             return false;
267         }
268 //        public void testSimpleSerialization() throws Exception {
269 //            if (main.isSubMapViewsSerializable() == false) return;
270 //            super.testSimpleSerialization();
271 //        }
272 //        public void testSerializeDeserializeThenCompare() throws Exception {
273 //            if (main.isSubMapViewsSerializable() == false) return;
274 //            super.testSerializeDeserializeThenCompare();
275 //        }
276 //        public void testEmptyMapCompatibility() throws Exception {
277 //            if (main.isSubMapViewsSerializable() == false) return;
278 //            super.testEmptyMapCompatibility();
279 //        }
280 //        public void testFullMapCompatibility() throws Exception {
281 //            if (main.isSubMapViewsSerializable() == false) return;
282 //            super.testFullMapCompatibility();
283 //        }
284         @Override
285         public void resetEmpty() {
286             // needed to init verify correctly
287             main.resetEmpty();
288             super.resetEmpty();
289         }
290         @Override
291         public void resetFull() {
292             // needed to init verify correctly
293             main.resetFull();
294             super.resetFull();
295         }
296         @Override
297         public void verify() {
298             // cross verify changes on view with changes on main map
299             super.verify();
300             main.verify();
301         }
302     }
303 
304     /**
305      * JUnit constructor.
306      *
307      * @param testName  the test name
308      */
309     public AbstractSortedMapTest(final String testName) {
310         super(testName);
311     }
312 
313     public BulkTest bulkTestHeadMap() {
314         return new TestHeadMap<>(this);
315     }
316 
317     public BulkTest bulkTestSubMap() {
318         return new TestSubMap<>(this);
319     }
320 
321     public BulkTest bulkTestTailMap() {
322         return new TestTailMap<>(this);
323     }
324 
325     /**
326      * {@inheritDoc}
327      */
328     @Override
329     public SortedMap<K, V> getConfirmed() {
330         return (SortedMap<K, V>) super.getConfirmed();
331     }
332 
333     /**
334      * {@inheritDoc}
335      */
336     @Override
337     public SortedMap<K, V> getMap() {
338         return (SortedMap<K, V>) super.getMap();
339     }
340 
341     /**
342      * Can't sort null keys.
343      *
344      * @return false
345      */
346     @Override
347     public boolean isAllowNullKey() {
348         return false;
349     }
350 
351     /**
352      * SortedMap uses TreeMap as its known comparison.
353      *
354      * @return a map that is known to be valid
355      */
356     @Override
357     public SortedMap<K, V> makeConfirmedMap() {
358         return new TreeMap<>();
359     }
360 
361     /**
362      * {@inheritDoc}
363      */
364     @Override
365     public SortedMap<K, V> makeFullMap() {
366         return (SortedMap<K, V>) super.makeFullMap();
367     }
368 
369     /**
370      * {@inheritDoc}
371      */
372     @Override
373     public abstract SortedMap<K, V> makeObject();
374 
375     @Test
376     public void testComparator() {
377 //        SortedMap<K, V> sm = makeFullMap();
378         // no tests I can think of
379     }
380 
381     @Test
382     public void testFirstKey() {
383         final SortedMap<K, V> sm = makeFullMap();
384         assertSame(sm.keySet().iterator().next(), sm.firstKey());
385     }
386 
387     @Test
388     public void testLastKey() {
389         final SortedMap<K, V> sm = makeFullMap();
390         K obj = null;
391         for (final K k : sm.keySet()) {
392             obj = k;
393         }
394         assertSame(obj, sm.lastKey());
395     }
396 
397 }