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    *      https://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  
18  package org.apache.commons.lang3;
19  
20  import static org.apache.commons.lang3.LangAssertions.assertIllegalArgumentException;
21  import static org.apache.commons.lang3.LangAssertions.assertNullPointerException;
22  import static org.junit.jupiter.api.Assertions.assertEquals;
23  import static org.junit.jupiter.api.Assertions.assertFalse;
24  import static org.junit.jupiter.api.Assertions.assertNotEquals;
25  import static org.junit.jupiter.api.Assertions.assertNotNull;
26  import static org.junit.jupiter.api.Assertions.assertSame;
27  import static org.junit.jupiter.api.Assertions.assertTrue;
28  
29  import java.util.Comparator;
30  
31  import org.junit.jupiter.api.BeforeEach;
32  import org.junit.jupiter.api.Test;
33  
34  /**
35   * Tests {@link Range}.
36   */
37  @SuppressWarnings("boxing")
38  class RangeTest extends AbstractLangTest {
39  
40      abstract static class AbstractComparable implements Comparable<AbstractComparable> {
41          @Override
42          public int compareTo(final AbstractComparable o) {
43              return 0;
44          }
45      }
46  
47      static final class DerivedComparableA extends AbstractComparable {
48          // empty
49      }
50  
51      static final class DerivedComparableB extends AbstractComparable {
52          // empty
53      }
54  
55      private Range<Byte> byteRange;
56      private Range<Byte> byteRange2;
57      private Range<Byte> byteRange3;
58      private Range<Double> doubleRange;
59      private Range<Float> floatRange;
60      private Range<Integer> intRange;
61      private Range<Long> longRange;
62  
63      @BeforeEach
64      public void setUp() {
65          byteRange = Range.of((byte) 0, (byte) 5);
66          byteRange2 = Range.of((byte) 0, (byte) 5);
67          byteRange3 = Range.of((byte) 0, (byte) 10);
68          intRange = Range.of(10, 20);
69          longRange = Range.of(10L, 20L);
70          floatRange = Range.of((float) 10, (float) 20);
71          doubleRange = Range.of((double) 10, (double) 20);
72      }
73  
74      @Test
75      void testBetweenWithCompare() {
76          // all integers are equal
77          final Comparator<Integer> c = (o1, o2) -> 0;
78          final Comparator<String> lengthComp = Comparator.comparingInt(String::length);
79          Range<Integer> rb = Range.between(-10, 20);
80          assertFalse(rb.contains(null), "should not contain null");
81          assertTrue(rb.contains(10), "should contain 10");
82          assertTrue(rb.contains(-10), "should contain -10");
83          assertFalse(rb.contains(21), "should not contain 21");
84          assertFalse(rb.contains(-11), "should not contain -11");
85          rb = Range.between(-10, 20, c);
86          assertFalse(rb.contains(null), "should not contain null");
87          assertTrue(rb.contains(10), "should contain 10");
88          assertTrue(rb.contains(-10), "should contain -10");
89          assertTrue(rb.contains(21), "should contain 21");
90          assertTrue(rb.contains(-11), "should contain -11");
91          Range<String> rbstr = Range.between("house", "i");
92          assertFalse(rbstr.contains(null), "should not contain null");
93          assertTrue(rbstr.contains("house"), "should contain house");
94          assertTrue(rbstr.contains("i"), "should contain i");
95          assertFalse(rbstr.contains("hose"), "should not contain hose");
96          assertFalse(rbstr.contains("ice"), "should not contain ice");
97          rbstr = Range.between("house", "i", lengthComp);
98          assertFalse(rbstr.contains(null), "should not contain null");
99          assertTrue(rbstr.contains("house"), "should contain house");
100         assertTrue(rbstr.contains("i"), "should contain i");
101         assertFalse(rbstr.contains("houses"), "should not contain houses");
102         assertFalse(rbstr.contains(""), "should not contain ''");
103         assertNullPointerException(() -> Range.between(null, null, lengthComp));
104     }
105 
106     @SuppressWarnings({"rawtypes", "unchecked"})
107     @Test
108     void testComparableConstructors() {
109         final Comparable c = other -> 1;
110         final Range r1 = Range.is(c);
111         final Range r2 = Range.between(c, c);
112         assertTrue(r1.isNaturalOrdering());
113         assertTrue(r2.isNaturalOrdering());
114     }
115 
116     @Test
117     void testConstructorSignatureWithAbstractComparableClasses() {
118         final DerivedComparableA derivedComparableA = new DerivedComparableA();
119         final DerivedComparableB derivedComparableB = new DerivedComparableB();
120         final Range<AbstractComparable> mixed = Range.between(derivedComparableA, derivedComparableB, null);
121         assertTrue(mixed.contains(derivedComparableA));
122         final Range<AbstractComparable> same = Range.between(derivedComparableA, derivedComparableA, null);
123         assertTrue(same.contains(derivedComparableA));
124         final Range<DerivedComparableA> rangeA = Range.between(derivedComparableA, derivedComparableA, null);
125         assertTrue(rangeA.contains(derivedComparableA));
126         final Range<DerivedComparableB> rangeB = Range.is(derivedComparableB, null);
127         assertTrue(rangeB.contains(derivedComparableB));
128     }
129 
130     @Test
131     void testContains() {
132         assertFalse(intRange.contains(null));
133         assertFalse(intRange.contains(5));
134         assertTrue(intRange.contains(10));
135         assertTrue(intRange.contains(15));
136         assertTrue(intRange.contains(20));
137         assertFalse(intRange.contains(25));
138     }
139 
140     @Test
141     void testContainsRange() {
142         // null handling
143         assertFalse(intRange.containsRange(null));
144         // easy inside range
145         assertTrue(intRange.containsRange(Range.between(12, 18)));
146         // outside range on each side
147         assertFalse(intRange.containsRange(Range.between(32, 45)));
148         assertFalse(intRange.containsRange(Range.between(2, 8)));
149         // equals range
150         assertTrue(intRange.containsRange(Range.between(10, 20)));
151         // overlaps
152         assertFalse(intRange.containsRange(Range.between(9, 14)));
153         assertFalse(intRange.containsRange(Range.between(16, 21)));
154         // touches lower boundary
155         assertTrue(intRange.containsRange(Range.between(10, 19)));
156         assertFalse(intRange.containsRange(Range.between(10, 21)));
157         // touches upper boundary
158         assertTrue(intRange.containsRange(Range.between(11, 20)));
159         assertFalse(intRange.containsRange(Range.between(9, 20)));
160         // negative
161         assertFalse(intRange.containsRange(Range.between(-11, -18)));
162     }
163 
164     @Test
165     void testElementCompareTo() {
166         assertNullPointerException(() -> intRange.elementCompareTo(null));
167         assertEquals(-1, intRange.elementCompareTo(5));
168         assertEquals(0, intRange.elementCompareTo(10));
169         assertEquals(0, intRange.elementCompareTo(15));
170         assertEquals(0, intRange.elementCompareTo(20));
171         assertEquals(1, intRange.elementCompareTo(25));
172     }
173 
174     @Test
175     void testEqualsObject() {
176         assertEquals(byteRange, byteRange);
177         assertEquals(byteRange, byteRange2);
178         assertEquals(byteRange2, byteRange2);
179         assertEquals(byteRange, byteRange);
180         assertEquals(byteRange2, byteRange2);
181         assertEquals(byteRange3, byteRange3);
182         assertNotEquals(byteRange2, byteRange3);
183         assertNotEquals(null, byteRange2);
184         assertNotEquals("Ni!", byteRange2);
185     }
186 
187     @Test
188     void testFit() {
189         assertEquals(intRange.getMinimum(), intRange.fit(Integer.MIN_VALUE));
190         assertEquals(intRange.getMinimum(), intRange.fit(intRange.getMinimum()));
191         assertEquals(intRange.getMaximum(), intRange.fit(Integer.MAX_VALUE));
192         assertEquals(intRange.getMaximum(), intRange.fit(intRange.getMaximum()));
193         assertEquals(15, intRange.fit(15));
194     }
195 
196     @Test
197     void testFitNull() {
198         assertNullPointerException(() -> intRange.fit(null));
199     }
200 
201     @Test
202     void testGetMaximum() {
203         assertEquals(20, (int) intRange.getMaximum());
204         assertEquals(20L, (long) longRange.getMaximum());
205         assertEquals(20f, floatRange.getMaximum(), 0.00001f);
206         assertEquals(20d, doubleRange.getMaximum(), 0.00001d);
207     }
208 
209     @Test
210     void testGetMinimum() {
211         assertEquals(10, (int) intRange.getMinimum());
212         assertEquals(10L, (long) longRange.getMinimum());
213         assertEquals(10f, floatRange.getMinimum(), 0.00001f);
214         assertEquals(10d, doubleRange.getMinimum(), 0.00001d);
215     }
216 
217     @Test
218     void testHashCode() {
219         assertEquals(byteRange.hashCode(), byteRange2.hashCode());
220         assertNotEquals(byteRange.hashCode(), byteRange3.hashCode());
221         assertEquals(intRange.hashCode(), intRange.hashCode());
222         assertTrue(intRange.hashCode() != 0);
223     }
224 
225     @Test
226     void testIntersectionWith() {
227         assertSame(intRange, intRange.intersectionWith(intRange));
228         assertSame(byteRange, byteRange.intersectionWith(byteRange));
229         assertSame(longRange, longRange.intersectionWith(longRange));
230         assertSame(floatRange, floatRange.intersectionWith(floatRange));
231         assertSame(doubleRange, doubleRange.intersectionWith(doubleRange));
232         assertEquals(Range.between(10, 15), intRange.intersectionWith(Range.between(5, 15)));
233     }
234 
235     @Test
236     void testIntersectionWithNonOverlapping() {
237         assertIllegalArgumentException(() -> intRange.intersectionWith(Range.between(0, 9)));
238     }
239 
240     @Test
241     void testIntersectionWithNull() {
242         assertIllegalArgumentException(() -> intRange.intersectionWith(null));
243     }
244 
245     @Test
246     void testIsAfter() {
247         assertFalse(intRange.isAfter(null));
248         assertTrue(intRange.isAfter(5));
249         assertFalse(intRange.isAfter(10));
250         assertFalse(intRange.isAfter(15));
251         assertFalse(intRange.isAfter(20));
252         assertFalse(intRange.isAfter(25));
253     }
254 
255     @Test
256     void testIsAfterRange() {
257         assertFalse(intRange.isAfterRange(null));
258         assertTrue(intRange.isAfterRange(Range.between(5, 9)));
259         assertFalse(intRange.isAfterRange(Range.between(5, 10)));
260         assertFalse(intRange.isAfterRange(Range.between(5, 20)));
261         assertFalse(intRange.isAfterRange(Range.between(5, 25)));
262         assertFalse(intRange.isAfterRange(Range.between(15, 25)));
263         assertFalse(intRange.isAfterRange(Range.between(21, 25)));
264         assertFalse(intRange.isAfterRange(Range.between(10, 20)));
265     }
266 
267     @Test
268     void testIsBefore() {
269         assertFalse(intRange.isBefore(null));
270         assertFalse(intRange.isBefore(5));
271         assertFalse(intRange.isBefore(10));
272         assertFalse(intRange.isBefore(15));
273         assertFalse(intRange.isBefore(20));
274         assertTrue(intRange.isBefore(25));
275     }
276 
277     @Test
278     void testIsBeforeRange() {
279         assertFalse(intRange.isBeforeRange(null));
280         assertFalse(intRange.isBeforeRange(Range.between(5, 9)));
281         assertFalse(intRange.isBeforeRange(Range.between(5, 10)));
282         assertFalse(intRange.isBeforeRange(Range.between(5, 20)));
283         assertFalse(intRange.isBeforeRange(Range.between(5, 25)));
284         assertFalse(intRange.isBeforeRange(Range.between(15, 25)));
285         assertTrue(intRange.isBeforeRange(Range.between(21, 25)));
286         assertFalse(intRange.isBeforeRange(Range.between(10, 20)));
287     }
288 
289     @Test
290     void testIsEndedBy() {
291         assertFalse(intRange.isEndedBy(null));
292         assertFalse(intRange.isEndedBy(5));
293         assertFalse(intRange.isEndedBy(10));
294         assertFalse(intRange.isEndedBy(15));
295         assertTrue(intRange.isEndedBy(20));
296         assertFalse(intRange.isEndedBy(25));
297     }
298 
299     @Test
300     void testIsOverlappedBy() {
301         // null handling
302         assertFalse(intRange.isOverlappedBy(null));
303         // easy inside range
304         assertTrue(intRange.isOverlappedBy(Range.between(12, 18)));
305         // outside range on each side
306         assertFalse(intRange.isOverlappedBy(Range.between(32, 45)));
307         assertFalse(intRange.isOverlappedBy(Range.between(2, 8)));
308         // equals range
309         assertTrue(intRange.isOverlappedBy(Range.between(10, 20)));
310         // overlaps
311         assertTrue(intRange.isOverlappedBy(Range.between(9, 14)));
312         assertTrue(intRange.isOverlappedBy(Range.between(16, 21)));
313         // touches lower boundary
314         assertTrue(intRange.isOverlappedBy(Range.between(10, 19)));
315         assertTrue(intRange.isOverlappedBy(Range.between(10, 21)));
316         // touches upper boundary
317         assertTrue(intRange.isOverlappedBy(Range.between(11, 20)));
318         assertTrue(intRange.isOverlappedBy(Range.between(9, 20)));
319         // negative
320         assertFalse(intRange.isOverlappedBy(Range.between(-11, -18)));
321         // outside range whole range
322         assertTrue(intRange.isOverlappedBy(Range.between(9, 21)));
323     }
324 
325     @Test
326     void testIsStartedBy() {
327         assertFalse(intRange.isStartedBy(null));
328         assertFalse(intRange.isStartedBy(5));
329         assertTrue(intRange.isStartedBy(10));
330         assertFalse(intRange.isStartedBy(15));
331         assertFalse(intRange.isStartedBy(20));
332         assertFalse(intRange.isStartedBy(25));
333     }
334 
335     @Test
336     void testIsWithCompare() {
337         // all integers are equal
338         final Comparator<Integer> c = (o1, o2) -> 0;
339         Range<Integer> ri = Range.is(10);
340         assertFalse(ri.contains(null), "should not contain null");
341         assertTrue(ri.contains(10), "should contain 10");
342         assertFalse(ri.contains(11), "should not contain 11");
343         ri = Range.is(10, c);
344         assertFalse(ri.contains(null), "should not contain null");
345         assertTrue(ri.contains(10), "should contain 10");
346         assertTrue(ri.contains(11), "should contain 11");
347     }
348 
349     @Test
350     void testOfWithCompare() {
351         // all integers are equal
352         final Comparator<Integer> c = (o1, o2) -> 0;
353         final Comparator<String> lengthComp = Comparator.comparingInt(String::length);
354         Range<Integer> rb = Range.of(-10, 20);
355         assertFalse(rb.contains(null), "should not contain null");
356         assertTrue(rb.contains(10), "should contain 10");
357         assertTrue(rb.contains(-10), "should contain -10");
358         assertFalse(rb.contains(21), "should not contain 21");
359         assertFalse(rb.contains(-11), "should not contain -11");
360         rb = Range.of(-10, 20, c);
361         assertFalse(rb.contains(null), "should not contain null");
362         assertTrue(rb.contains(10), "should contain 10");
363         assertTrue(rb.contains(-10), "should contain -10");
364         assertTrue(rb.contains(21), "should contain 21");
365         assertTrue(rb.contains(-11), "should contain -11");
366         Range<String> rbstr = Range.of("house", "i");
367         assertFalse(rbstr.contains(null), "should not contain null");
368         assertTrue(rbstr.contains("house"), "should contain house");
369         assertTrue(rbstr.contains("i"), "should contain i");
370         assertFalse(rbstr.contains("hose"), "should not contain hose");
371         assertFalse(rbstr.contains("ice"), "should not contain ice");
372         rbstr = Range.of("house", "i", lengthComp);
373         assertFalse(rbstr.contains(null), "should not contain null");
374         assertTrue(rbstr.contains("house"), "should contain house");
375         assertTrue(rbstr.contains("i"), "should contain i");
376         assertFalse(rbstr.contains("houses"), "should not contain houses");
377         assertFalse(rbstr.contains(""), "should not contain ''");
378         assertNullPointerException(() -> Range.of(null, null, lengthComp));
379     }
380 
381     @Test
382     void testRangeOfChars() {
383         final Range<Character> chars = Range.between('a', 'z');
384         assertTrue(chars.contains('b'));
385         assertFalse(chars.contains('B'));
386     }
387 
388     @Test
389     void testSerializing() {
390         SerializationUtils.clone(intRange);
391     }
392 
393     @Test
394     void testToString() {
395         assertNotNull(byteRange.toString());
396 
397         final String str = intRange.toString();
398         assertEquals("[10..20]", str);
399         assertEquals("[-20..-10]", Range.between(-20, -10).toString());
400     }
401 
402     @Test
403     void testToStringFormat() {
404         final String str = intRange.toString("From %1$s to %2$s");
405         assertEquals("From 10 to 20", str);
406     }
407 }