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              FixedOrderComparator<Integer> comparator1 = new FixedOrderComparator<>(1, 2, 3);
45              FixedOrderComparator<Integer> comparator2 = new FixedOrderComparator<>(2, 3, 4);
46              assertFalse(comparator1.equals(comparator2));
47          }
48  
49          @Test
50          void expectFalseWhenBothComparatorsWithDifferentUnknownObjectBehavior() {
51              FixedOrderComparator<Integer> comparator1 = new FixedOrderComparator<>();
52              comparator1.setUnknownObjectBehavior(FixedOrderComparator.UnknownObjectBehavior.BEFORE);
53              FixedOrderComparator<Integer> comparator2 = new FixedOrderComparator<>();
54              comparator2.setUnknownObjectBehavior(FixedOrderComparator.UnknownObjectBehavior.AFTER);
55              assertFalse(comparator1.equals(comparator2));
56          }
57  
58          @Test
59          void expectFalseWhenFixedOrderComparatorIsComparedWithNull() {
60              FixedOrderComparator<Integer> comparator = new FixedOrderComparator<>();
61              assertFalse(comparator.equals(null));
62          }
63  
64  
65          @Test
66          void expectFalseWhenFixedOrderComparatorIsComparedWithOtherObject() {
67              FixedOrderComparator<Integer> comparator = new FixedOrderComparator<>();
68              assertFalse(comparator.equals(new Object()));
69          }
70  
71          @Test
72          void expectFalseWhenOneComparatorIsLocked() {
73              FixedOrderComparator<Integer> comparator1 = new FixedOrderComparator<>(1, 2, 3);
74              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              FixedOrderComparator<Integer> comparator1 = new FixedOrderComparator<>(1, 2, 3);
82              FixedOrderComparator<Integer> comparator2 = new FixedOrderComparator<>(1, 2, 3, 3);
83              assertFalse(comparator1.equals(comparator2));
84          }
85  
86          @Test
87          void expectTrueWhenBothComparatorsAreLocked() {
88              FixedOrderComparator<Integer> comparator1 = new FixedOrderComparator<>(1, 2, 3);
89              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              FixedOrderComparator<Integer> comparator1 = new FixedOrderComparator<>();
98              FixedOrderComparator<Integer> comparator2 = new FixedOrderComparator<>();
99              assertTrue(comparator1.equals(comparator2));
100         }
101 
102         @Test
103         void expectTrueWhenBothObjectsAreSame() {
104             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,
141                                              final Comparator<String> comparator) {
142         final String[] keys = orderedObjects.clone();
143 
144         // shuffle until the order changes.  It's extremely rare that
145         // this requires more than one shuffle.
146 
147         boolean isInNewOrder = false;
148         final Random rand = new Random();
149         while (keys.length > 1 && !isInNewOrder) {
150             // shuffle:
151             for (int i = keys.length-1; i > 0; i--) {
152                 final String swap = keys[i];
153                 final int j = rand.nextInt(i+1);
154                 keys[i] = keys[j];
155                 keys[j] = swap;
156             }
157 
158             // testShuffle
159             for (int i = 0; i < keys.length; i++) {
160                 if (!orderedObjects[i].equals(keys[i])) {
161                     isInNewOrder = true;
162                     break;
163                 }
164             }
165         }
166 
167         // The real test:  sort and make sure they come out right.
168 
169         Arrays.sort(keys, comparator);
170 
171         for (int i = 0; i < orderedObjects.length; i++) {
172             assertEquals(orderedObjects[i], keys[i]);
173         }
174     }
175 
176     @Override
177     public List<String> getComparableObjectsOrdered() {
178         return Arrays.asList(topCities);
179     }
180 
181 //    public void testCreate() throws Exception {
182 //        writeExternalFormToDisk((java.io.Serializable) makeObject(), "src/test/resources/data/test/FixedOrderComparator.version4.obj");
183 //    }
184 
185     //
186     // The tests
187     //
188 
189     @Override
190     public String getCompatibilityVersion() {
191         return "4";
192     }
193 
194     @Override
195     public Comparator<String> makeObject() {
196         return new FixedOrderComparator<>(topCities);
197     }
198 
199     /**
200      * Tests addAsEqual method.
201      */
202     @Test
203     public void testAddAsEqual() {
204         final FixedOrderComparator<String> comparator = new FixedOrderComparator<>(topCities);
205         comparator.addAsEqual("New York", "Minneapolis");
206         assertEquals(0, comparator.compare("New York", "Minneapolis"));
207         assertEquals(-1, comparator.compare("Tokyo", "Minneapolis"));
208         assertEquals(1, comparator.compare("Shanghai", "Minneapolis"));
209     }
210 
211     /**
212      * Tests that the array constructor compares items properly.
213      */
214     @Test
215     public void testArrayConstructor() {
216         final String[] keys = topCities.clone();
217         final String[] topCitiesForTest = topCities.clone();
218         final FixedOrderComparator<String> comparator = new FixedOrderComparator<>(topCitiesForTest);
219         assertComparatorYieldsOrder(keys, comparator);
220         // test that changing input after constructor has no effect
221         topCitiesForTest[0] = "Brighton";
222         assertComparatorYieldsOrder(keys, comparator);
223     }
224 
225     /**
226      * Tests that the constructor plus add method compares items properly.
227      */
228     @Test
229     public void testConstructorPlusAdd() {
230         final FixedOrderComparator<String> comparator = new FixedOrderComparator<>();
231         for (final String topCity : topCities) {
232             comparator.add(topCity);
233         }
234         final String[] keys = topCities.clone();
235         assertComparatorYieldsOrder(keys, comparator);
236     }
237 
238     /**
239      * Tests the list constructor.
240      */
241     @Test
242     public void testListConstructor() {
243         final String[] keys = topCities.clone();
244         final List<String> topCitiesForTest = new LinkedList<>(Arrays.asList(topCities));
245         final FixedOrderComparator<String> comparator = new FixedOrderComparator<>(topCitiesForTest);
246         assertComparatorYieldsOrder(keys, comparator);
247         // test that changing input after constructor has no effect
248         topCitiesForTest.set(0, "Brighton");
249         assertComparatorYieldsOrder(keys, comparator);
250     }
251 
252     //
253     // Helper methods
254     //
255 
256     /**
257      * Tests whether or not updates are disabled after a comparison is made.
258      */
259     @Test
260     public void testLock() {
261         final FixedOrderComparator<String> comparator = new FixedOrderComparator<>(topCities);
262         assertFalse(comparator.isLocked());
263         comparator.compare("New York", "Tokyo");
264         assertTrue(comparator.isLocked());
265 
266         assertThrows(UnsupportedOperationException.class, () -> comparator.add("Minneapolis"),
267                 "Should have thrown an UnsupportedOperationException");
268 
269         assertThrows(UnsupportedOperationException.class, () -> comparator.addAsEqual("New York", "Minneapolis"),
270                 "Should have thrown an UnsupportedOperationException");
271     }
272 
273     @Test
274     public void testUnknownObjectBehavior() {
275         FixedOrderComparator<String> comparator = new FixedOrderComparator<>(topCities);
276 
277         final FixedOrderComparator<String> finalComparator = comparator;
278         assertThrows(IllegalArgumentException.class, () -> finalComparator.compare("New York", "Minneapolis"),
279                 "Should have thrown a IllegalArgumentException");
280 
281         assertThrows(IllegalArgumentException.class, () -> finalComparator.compare("Minneapolis", "New York"),
282                 "Should have thrown a IllegalArgumentException");
283 
284         assertEquals(FixedOrderComparator.UnknownObjectBehavior.EXCEPTION, comparator.getUnknownObjectBehavior());
285 
286         comparator = new FixedOrderComparator<>(topCities);
287         comparator.setUnknownObjectBehavior(FixedOrderComparator.UnknownObjectBehavior.BEFORE);
288         assertEquals(FixedOrderComparator.UnknownObjectBehavior.BEFORE, comparator.getUnknownObjectBehavior());
289         LinkedList<String> keys = new LinkedList<>(Arrays.asList(topCities));
290         keys.addFirst("Minneapolis");
291         assertComparatorYieldsOrder(keys.toArray(ArrayUtils.EMPTY_STRING_ARRAY), comparator);
292 
293         assertEquals(-1, comparator.compare("Minneapolis", "New York"));
294         assertEquals( 1, comparator.compare("New York", "Minneapolis"));
295         assertEquals( 0, comparator.compare("Minneapolis", "St Paul"));
296 
297         comparator = new FixedOrderComparator<>(topCities);
298         comparator.setUnknownObjectBehavior(FixedOrderComparator.UnknownObjectBehavior.AFTER);
299         keys = new LinkedList<>(Arrays.asList(topCities));
300         keys.add("Minneapolis");
301         assertComparatorYieldsOrder(keys.toArray(ArrayUtils.EMPTY_STRING_ARRAY), comparator);
302 
303         assertEquals( 1, comparator.compare("Minneapolis", "New York"));
304         assertEquals(-1, comparator.compare("New York", "Minneapolis"));
305         assertEquals( 0, comparator.compare("Minneapolis", "St Paul"));
306     }
307 }