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