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.assertFalse;
21  import static org.junit.jupiter.api.Assertions.assertThrows;
22  import static org.junit.jupiter.api.Assertions.assertTrue;
23  
24  import java.util.Arrays;
25  import java.util.Comparator;
26  import java.util.LinkedList;
27  import java.util.List;
28  import java.util.Random;
29  
30  import org.apache.commons.lang3.ArrayUtils;
31  import org.junit.jupiter.api.Nested;
32  import org.junit.jupiter.api.Test;
33  
34  /**
35   * Test class for FixedOrderComparator.
36   */
37  public class FixedOrderComparatorTest extends AbstractComparatorTest<String> {
38  
39      @Nested
40      class Equals {
41  
42          @Test
43          void expectFalseWhenBothComparatorsWithDifferentItems() {
44              final FixedOrderComparator<Integer> comparator1 = new FixedOrderComparator<>(1, 2, 3);
45              final FixedOrderComparator<Integer> comparator2 = new FixedOrderComparator<>(2, 3, 4);
46              assertFalse(comparator1.equals(comparator2));
47          }
48  
49          @Test
50          void expectFalseWhenBothComparatorsWithDifferentUnknownObjectBehavior() {
51              final FixedOrderComparator<Integer> comparator1 = new FixedOrderComparator<>();
52              comparator1.setUnknownObjectBehavior(FixedOrderComparator.UnknownObjectBehavior.BEFORE);
53              final FixedOrderComparator<Integer> comparator2 = new FixedOrderComparator<>();
54              comparator2.setUnknownObjectBehavior(FixedOrderComparator.UnknownObjectBehavior.AFTER);
55              assertFalse(comparator1.equals(comparator2));
56          }
57  
58          @Test
59          void expectFalseWhenFixedOrderComparatorIsComparedWithNull() {
60              final FixedOrderComparator<Integer> comparator = new FixedOrderComparator<>();
61              assertFalse(comparator.equals(null));
62          }
63  
64  
65          @Test
66          void expectFalseWhenFixedOrderComparatorIsComparedWithOtherObject() {
67              final FixedOrderComparator<Integer> comparator = new FixedOrderComparator<>();
68              assertFalse(comparator.equals(new Object()));
69          }
70  
71          @Test
72          void expectFalseWhenOneComparatorIsLocked() {
73              final FixedOrderComparator<Integer> comparator1 = new FixedOrderComparator<>(1, 2, 3);
74              final FixedOrderComparator<Integer> comparator2 = new FixedOrderComparator<>(1, 2, 3);
75              comparator2.compare(1, 2);
76              assertFalse(comparator1.equals(comparator2));
77          }
78  
79          @Test
80          void expectFalseWhenOneComparatorsWithDuplicateItems() {
81              final FixedOrderComparator<Integer> comparator1 = new FixedOrderComparator<>(1, 2, 3);
82              final FixedOrderComparator<Integer> comparator2 = new FixedOrderComparator<>(1, 2, 3, 3);
83              assertFalse(comparator1.equals(comparator2));
84          }
85  
86          @Test
87          void expectTrueWhenBothComparatorsAreLocked() {
88              final FixedOrderComparator<Integer> comparator1 = new FixedOrderComparator<>(1, 2, 3);
89              final FixedOrderComparator<Integer> comparator2 = new FixedOrderComparator<>(1, 2, 3);
90              comparator1.compare(1, 2);
91              comparator2.compare(1, 2);
92              assertTrue(comparator1.equals(comparator2));
93          }
94  
95          @Test
96          void expectTrueWhenBothComparatorsWithoutAnyItems() {
97              final FixedOrderComparator<Integer> comparator1 = new FixedOrderComparator<>();
98              final FixedOrderComparator<Integer> comparator2 = new FixedOrderComparator<>();
99              assertTrue(comparator1.equals(comparator2));
100         }
101 
102         @Test
103         void expectTrueWhenBothObjectsAreSame() {
104             final FixedOrderComparator<Integer> comparator = new FixedOrderComparator<>();
105             assertTrue(comparator.equals(comparator));
106         }
107     }
108 
109     //
110     // Initialization and busywork
111     //
112 
113     /**
114      * Top cities of the world, by population including metro areas.
115      */
116     private static final String[] topCities = {
117         "Tokyo",
118         "Mexico City",
119         "Mumbai",
120         "Sao Paulo",
121         "New York",
122         "Shanghai",
123         "Lagos",
124         "Los Angeles",
125         "Calcutta",
126         "Buenos Aires"
127     };
128 
129     //
130     // Set up and tear down
131     //
132 
133     public FixedOrderComparatorTest() {
134         super(FixedOrderComparatorTest.class.getSimpleName());
135     }
136 
137     /** Shuffles the keys and asserts that the comparator sorts them back to
138      * their original order.
139      */
140     private void assertComparatorYieldsOrder(final String[] orderedObjects, final Comparator<String> comparator) {
141         final String[] keys = orderedObjects.clone();
142 
143         // shuffle until the order changes. It's extremely rare that
144         // this requires more than one shuffle.
145 
146         boolean isInNewOrder = false;
147         final Random rand = new Random();
148         while (keys.length > 1 && !isInNewOrder) {
149             // shuffle:
150             for (int i = keys.length - 1; i > 0; i--) {
151                 final String swap = keys[i];
152                 final int j = rand.nextInt(i + 1);
153                 keys[i] = keys[j];
154                 keys[j] = swap;
155             }
156 
157             // testShuffle
158             for (int i = 0; i < keys.length; i++) {
159                 if (!orderedObjects[i].equals(keys[i])) {
160                     isInNewOrder = true;
161                     break;
162                 }
163             }
164         }
165 
166         // The real test: sort and make sure they come out right.
167 
168         Arrays.sort(keys, comparator);
169 
170         for (int i = 0; i < orderedObjects.length; i++) {
171             assertEquals(orderedObjects[i], keys[i]);
172         }
173     }
174 
175     @Override
176     public List<String> getComparableObjectsOrdered() {
177         return Arrays.asList(topCities);
178     }
179 
180 //    public void testCreate() throws Exception {
181 //        writeExternalFormToDisk((java.io.Serializable) makeObject(), "src/test/resources/data/test/FixedOrderComparator.version4.obj");
182 //    }
183 
184     //
185     // The tests
186     //
187 
188     @Override
189     public String getCompatibilityVersion() {
190         return "4";
191     }
192 
193     @Override
194     public Comparator<String> makeObject() {
195         return new FixedOrderComparator<>(topCities);
196     }
197 
198     /**
199      * Tests addAsEqual method.
200      */
201     @Test
202     public void testAddAsEqual() {
203         final FixedOrderComparator<String> comparator = new FixedOrderComparator<>(topCities);
204         comparator.addAsEqual("New York", "Minneapolis");
205         assertEquals(0, comparator.compare("New York", "Minneapolis"));
206         assertEquals(-1, comparator.compare("Tokyo", "Minneapolis"));
207         assertEquals(1, comparator.compare("Shanghai", "Minneapolis"));
208     }
209 
210     /**
211      * Tests that the array constructor compares items properly.
212      */
213     @Test
214     public void testArrayConstructor() {
215         final String[] keys = topCities.clone();
216         final String[] topCitiesForTest = topCities.clone();
217         final FixedOrderComparator<String> comparator = new FixedOrderComparator<>(topCitiesForTest);
218         assertComparatorYieldsOrder(keys, comparator);
219         // test that changing input after constructor has no effect
220         topCitiesForTest[0] = "Brighton";
221         assertComparatorYieldsOrder(keys, comparator);
222     }
223 
224     /**
225      * Tests that the constructor plus add method compares items properly.
226      */
227     @Test
228     public void testConstructorPlusAdd() {
229         final FixedOrderComparator<String> comparator = new FixedOrderComparator<>();
230         for (final String topCity : topCities) {
231             comparator.add(topCity);
232         }
233         final String[] keys = topCities.clone();
234         assertComparatorYieldsOrder(keys, comparator);
235     }
236 
237     /**
238      * Tests the list constructor.
239      */
240     @Test
241     public void testListConstructor() {
242         final String[] keys = topCities.clone();
243         final List<String> topCitiesForTest = new LinkedList<>(Arrays.asList(topCities));
244         final FixedOrderComparator<String> comparator = new FixedOrderComparator<>(topCitiesForTest);
245         assertComparatorYieldsOrder(keys, comparator);
246         // test that changing input after constructor has no effect
247         topCitiesForTest.set(0, "Brighton");
248         assertComparatorYieldsOrder(keys, comparator);
249     }
250 
251     //
252     // Helper methods
253     //
254 
255     /**
256      * Tests whether or not updates are disabled after a comparison is made.
257      */
258     @Test
259     public void testLock() {
260         final FixedOrderComparator<String> comparator = new FixedOrderComparator<>(topCities);
261         assertFalse(comparator.isLocked());
262         comparator.compare("New York", "Tokyo");
263         assertTrue(comparator.isLocked());
264 
265         assertThrows(UnsupportedOperationException.class, () -> comparator.add("Minneapolis"),
266                 "Should have thrown an UnsupportedOperationException");
267 
268         assertThrows(UnsupportedOperationException.class, () -> comparator.addAsEqual("New York", "Minneapolis"),
269                 "Should have thrown an UnsupportedOperationException");
270     }
271 
272     @Test
273     public void testUnknownObjectBehavior() {
274         FixedOrderComparator<String> comparator = new FixedOrderComparator<>(topCities);
275 
276         final FixedOrderComparator<String> finalComparator = comparator;
277         assertThrows(IllegalArgumentException.class, () -> finalComparator.compare("New York", "Minneapolis"),
278                 "Should have thrown a IllegalArgumentException");
279 
280         assertThrows(IllegalArgumentException.class, () -> finalComparator.compare("Minneapolis", "New York"),
281                 "Should have thrown a IllegalArgumentException");
282 
283         assertEquals(FixedOrderComparator.UnknownObjectBehavior.EXCEPTION, comparator.getUnknownObjectBehavior());
284 
285         comparator = new FixedOrderComparator<>(topCities);
286         comparator.setUnknownObjectBehavior(FixedOrderComparator.UnknownObjectBehavior.BEFORE);
287         assertEquals(FixedOrderComparator.UnknownObjectBehavior.BEFORE, comparator.getUnknownObjectBehavior());
288         LinkedList<String> keys = new LinkedList<>(Arrays.asList(topCities));
289         keys.addFirst("Minneapolis");
290         assertComparatorYieldsOrder(keys.toArray(ArrayUtils.EMPTY_STRING_ARRAY), comparator);
291 
292         assertEquals(-1, comparator.compare("Minneapolis", "New York"));
293         assertEquals( 1, comparator.compare("New York", "Minneapolis"));
294         assertEquals( 0, comparator.compare("Minneapolis", "St Paul"));
295 
296         comparator = new FixedOrderComparator<>(topCities);
297         comparator.setUnknownObjectBehavior(FixedOrderComparator.UnknownObjectBehavior.AFTER);
298         keys = new LinkedList<>(Arrays.asList(topCities));
299         keys.add("Minneapolis");
300         assertComparatorYieldsOrder(keys.toArray(ArrayUtils.EMPTY_STRING_ARRAY), comparator);
301 
302         assertEquals( 1, comparator.compare("Minneapolis", "New York"));
303         assertEquals(-1, comparator.compare("New York", "Minneapolis"));
304         assertEquals( 0, comparator.compare("Minneapolis", "St Paul"));
305     }
306 }