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.comparators;
18  
19  import static org.junit.jupiter.api.Assertions.assertEquals;
20  import static org.junit.jupiter.api.Assertions.assertInstanceOf;
21  import static org.junit.jupiter.api.Assertions.fail;
22  
23  import java.io.FileNotFoundException;
24  import java.io.IOException;
25  import java.io.Serializable;
26  import java.util.Collections;
27  import java.util.Comparator;
28  import java.util.LinkedList;
29  import java.util.List;
30  
31  import org.apache.commons.collections4.AbstractObjectTest;
32  import org.junit.jupiter.api.Test;
33  
34  /**
35   * Abstract test class for testing the Comparator interface.
36   * <p>
37   * Concrete subclasses declare the comparator to be tested.
38   * They also declare certain aspects of the tests.
39   */
40  public abstract class AbstractComparatorTest<T> extends AbstractObjectTest {
41  
42      public String getCanonicalComparatorName(final Object object) {
43          final StringBuilder retval = new StringBuilder();
44          retval.append(TEST_DATA_PATH);
45          String colName = object.getClass().getName();
46          colName = colName.substring(colName.lastIndexOf(".") + 1);
47          retval.append(colName);
48          retval.append(".version");
49          retval.append(getCompatibilityVersion());
50          retval.append(".obj");
51          return retval.toString();
52      }
53  
54      /**
55       * Implement this method to return a list of sorted objects.
56       *
57       * @return sorted objects
58       */
59      public abstract List<T> getComparableObjectsOrdered();
60  
61      /**
62       * Implements the abstract superclass method to return the comparator.
63       *
64       * @return a full iterator
65       */
66      @Override
67      public abstract Comparator<T> makeObject();
68  
69      /**
70       * Randomize the list.
71       */
72      protected void randomizeObjects(final List<?> list) {
73          Collections.shuffle(list);
74      }
75  
76      /**
77       * Reverse the list.
78       */
79      protected void reverseObjects(final List<?> list) {
80          Collections.reverse(list);
81      }
82  
83      /**
84       * Sort the list.
85       */
86      protected void sortObjects(final List<T> list, final Comparator<? super T> comparator) {
87          list.sort(comparator);
88      }
89  
90      /**
91       * Overrides superclass to block tests.
92       */
93      @Override
94      public boolean supportsEmptyCollections() {
95          return false;
96      }
97  
98      /**
99       * Overrides superclass to block tests.
100      */
101     @Override
102     public boolean supportsFullCollections() {
103         return false;
104     }
105 
106     /**
107      * Compare the current serialized form of the Comparator
108      * against the canonical version in SCM.
109      */
110     @Test
111     @SuppressWarnings("unchecked")
112     public void testComparatorCompatibility() throws IOException, ClassNotFoundException {
113         if (!skipSerializedCanonicalTests()) {
114             Comparator<T> comparator = null;
115             // test to make sure the canonical form has been preserved
116             try {
117                 comparator = (Comparator<T>) readExternalFormFromDisk(getCanonicalComparatorName(makeObject()));
118             } catch (final FileNotFoundException e) {
119                 final boolean autoCreateSerialized = false;
120                 if (autoCreateSerialized) {
121                     comparator = makeObject();
122                     final String fileName = getCanonicalComparatorName(comparator);
123                     writeExternalFormToDisk((Serializable) comparator, fileName);
124                     fail("Serialized form could not be found.  A serialized version " + "has now been written (and should be added to CVS): " + fileName);
125                 } else {
126                     fail("The Serialized form could be located to test serialization " + "compatibility: " + e.getMessage());
127                 }
128             }
129             // make sure the canonical form produces the ordering we currently
130             // expect
131             final List<T> randomList = getComparableObjectsOrdered();
132             reverseObjects(randomList);
133             sortObjects(randomList, comparator);
134             final List<T> orderedList = getComparableObjectsOrdered();
135             assertEquals(orderedList, randomList, "Comparator did not reorder the List correctly");
136         }
137     }
138 
139     /**
140      * Nearly all Comparators should be Serializable.
141      */
142     @Test
143     public void testComparatorIsSerializable() {
144         final Comparator<T> comparator = makeObject();
145         assertInstanceOf(Serializable.class, comparator, "This comparator should be Serializable.");
146     }
147 
148     /**
149      * Test sorting an empty list
150      */
151     @Test
152     public void testEmptyListSort() {
153         final List<T> list = new LinkedList<>();
154         sortObjects(list, makeObject());
155         final List<T> list2 = new LinkedList<>();
156         assertEquals(list2, list, "Comparator cannot sort empty lists");
157     }
158 
159     /**
160      * Test sorting a random list.
161      */
162     @Test
163     public void testRandomListSort() {
164         final Comparator<T> comparator = makeObject();
165         final List<T> randomList = getComparableObjectsOrdered();
166         randomizeObjects(randomList);
167         sortObjects(randomList, comparator);
168         final List<T> orderedList = getComparableObjectsOrdered();
169         /* debug
170         Iterator i = randomList.iterator();
171         while (i.hasNext()) {
172             System.out.println(i.next());
173         }
174         */
175         assertEquals(orderedList, randomList, "Comparator did not reorder the List correctly");
176     }
177 
178     /**
179      * Test sorting a reversed list.
180      */
181     @Test
182     public void testReverseListSort() {
183         final Comparator<T> comparator = makeObject();
184         final List<T> randomList = getComparableObjectsOrdered();
185         reverseObjects(randomList);
186         sortObjects(randomList, comparator);
187         final List<T> orderedList = getComparableObjectsOrdered();
188         assertEquals(orderedList, randomList, "Comparator did not reorder the List correctly");
189     }
190 }