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