001/*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements.  See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License.  You may obtain a copy of the License at
008 *
009 *      http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017package org.apache.commons.functor.range;
018
019import static org.junit.Assert.assertEquals;
020import static org.junit.Assert.assertFalse;
021import static org.junit.Assert.assertTrue;
022import static org.junit.Assert.fail;
023
024import java.util.ArrayList;
025import java.util.Arrays;
026import java.util.Collection;
027import java.util.Collections;
028import java.util.List;
029
030import org.apache.commons.functor.BaseFunctorTest;
031import org.apache.commons.functor.Function;
032import org.apache.commons.functor.generator.Generator;
033import org.apache.commons.functor.generator.loop.IteratorToGeneratorAdapter;
034import org.junit.After;
035import org.junit.Before;
036import org.junit.Test;
037
038/**
039 * @version $Revision: 1515264 $ $Date: 2013-08-18 23:51:41 -0300 (Sun, 18 Aug 2013) $
040 */
041public class TestIntegerRange extends BaseFunctorTest {
042
043    // Attributes
044    // ------------------------------------------------------------------------
045    private IntegerRange ascIntRange = null;
046    private IntegerRange descIntRange = null;
047    private Collection<Integer> expectedAsc = null;
048    private Collection<Integer> expectedDesc = null;
049
050    // Test set up
051    // ------------------------------------------------------------------------
052    @Before
053    public void setUp() {
054        ascIntRange = Ranges.integerRange(0, 10);
055        descIntRange = Ranges.integerRange(10, 0);
056        expectedAsc = Arrays.asList(0, 1, 2, 3, 4, 5, 6, 7, 8, 9);
057        expectedDesc = Arrays.asList(10, 9, 8, 7, 6, 5, 4, 3, 2, 1);
058    }
059
060    @After
061    public void tearDown() {
062        ascIntRange = null;
063        descIntRange = null;
064    }
065    
066    @Override
067    protected Object makeFunctor() throws Exception {
068        return Ranges.integerRange(10, 20);
069    }
070
071    // Generator tests
072    // ------------------------------------------------------------------------
073
074    @Test
075    public void testGenerateListExample() {
076        // generates a collection of Integers from 0 (inclusive) to 10 (exclusive)
077        {
078            List<? super Integer> list = (List<? super Integer>) (
079                IteratorToGeneratorAdapter.adapt(Ranges.integerRange(0,10)).to(new ArrayList<Integer>()));
080            for (int i=0;i<10;i++) {
081                assertEquals(Integer.valueOf(i),list.get(i));
082            }
083        }
084
085        // generates a collection of Integers from 10 (inclusive) to 0 (exclusive)
086        {
087            List<? super Integer> list = (List<? super Integer>) (
088                IteratorToGeneratorAdapter.adapt(Ranges.integerRange(10,0)).to(new ArrayList<Integer>()));
089            for (int i=10;i>0;i--) {
090                assertEquals(Integer.valueOf(i),list.get(10-i));
091            }
092        }
093    }
094
095    @Test
096    public void testStepChecking() {
097        {
098            Ranges.integerRange(2, 2, 0); // step of 0 is ok when range is empty
099        }
100        {
101            Ranges.integerRange(2, 2, 1); // positive step is ok when range is empty
102        }
103        {
104            Ranges.integerRange(2, 2, -1); // negative step is ok when range is empty
105        }
106        {
107            Ranges.integerRange(0, 1, 10); // big steps are ok
108        }
109        {
110            Ranges.integerRange(1, 0, -10); // big steps are ok
111        }
112        try {
113            Ranges.integerRange(0, 1, 0);
114            fail("Expected IllegalArgumentException");
115        } catch(IllegalArgumentException e) {
116            // expected
117        }
118        try {
119            Ranges.integerRange(0, 1, -1);
120            fail("Expected IllegalArgumentException");
121        } catch(IllegalArgumentException e) {
122            // expected
123        }
124        try {
125            Ranges.integerRange(0, -1, 1);
126            fail("Expected IllegalArgumentException");
127        } catch(IllegalArgumentException e) {
128            // expected
129        }
130    }
131
132    @Test
133    public void testObjectConstructor() {
134        IntegerRange range = Ranges.integerRange(Integer.valueOf(0), Integer.valueOf(5));
135        assertEquals("[0, 1, 2, 3, 4]", IteratorToGeneratorAdapter.adapt(range).toCollection().toString());
136        range = Ranges.integerRange(Integer.valueOf(0), Integer.valueOf(5), Integer.valueOf(1));
137        assertEquals("[0, 1, 2, 3, 4]", IteratorToGeneratorAdapter.adapt(range).toCollection().toString());
138    }
139
140
141    @Test
142    public void testReverseStep() {
143        IntegerRange range = Ranges.integerRange(10, 0, -2);
144        assertEquals("[10, 8, 6, 4, 2]", IteratorToGeneratorAdapter.adapt(range).toCollection().toString());
145    }
146
147    @Test
148    public void testStep() {
149        IntegerRange range = Ranges.integerRange(0, 10, 2);
150        assertEquals("[0, 2, 4, 6, 8]", IteratorToGeneratorAdapter.adapt(range).toCollection().toString());
151    }
152
153    @Test
154    public void testForwardRange() {
155        IntegerRange range = Ranges.integerRange(0, 5);
156        assertEquals("[0, 1, 2, 3, 4]", IteratorToGeneratorAdapter.adapt(range).toCollection().toString());
157    }
158
159    @Test
160    public void testReverseRange() {
161        IntegerRange range = Ranges.integerRange(5, 0);
162        assertEquals("[5, 4, 3, 2, 1]", IteratorToGeneratorAdapter.adapt(range).toCollection().toString());
163    }
164
165    @Test
166    public void testEdgeCase() {
167        IntegerRange range = Ranges.integerRange(Integer.MAX_VALUE - 3, Integer.MAX_VALUE);
168        assertEquals("[2147483644, 2147483645, 2147483646]", IteratorToGeneratorAdapter.adapt(range).toCollection().toString());
169    }
170
171    @Test
172    public void testBoundaries() {
173        IntegerRange range = Ranges.integerRange(0, 10);
174        assertEquals(new Endpoint<Comparable<?>>(0, BoundType.CLOSED),
175                     range.getLeftEndpoint());
176        assertEquals(new Endpoint<Comparable<?>>(10, BoundType.OPEN),
177                     range.getRightEndpoint());
178    }
179
180    @Test
181    public void testClosedClosedAscending() {
182        // [-5, 5], 3 = -5, -2, 1, 4
183        IntegerRange range = Ranges.integerRange(-5, BoundType.CLOSED, 5,
184                                              BoundType.CLOSED, 3);
185        // [-5, 5], 3 = -5, -2, 1, 4
186        List<Integer> expected = Arrays.asList(-5, -2, 1, 4);
187        Collection<Integer> elements = IteratorToGeneratorAdapter.adapt(range).toCollection();
188        assertEquals(expected, elements);
189    }
190
191    @Test
192    public void testOpenClosedAscending() {
193        // (-5, 5], 3 = -2, 1, 4
194        IntegerRange range = Ranges.integerRange(-5, BoundType.OPEN, 5,
195                                              BoundType.CLOSED, 3);
196        // (-5, 5], 3 = -2, 1, 4
197        List<Integer> expected = Arrays.asList(-2, 1, 4);
198        Collection<Integer> elements = IteratorToGeneratorAdapter.adapt(range).toCollection();
199        assertEquals(expected, elements);
200    }
201
202    @Test
203    public void testClosedOpenAscending() {
204        // [-5, 5), 3 = -5, -2, 1, 4
205        IntegerRange range = Ranges.integerRange(-5, BoundType.CLOSED, 5,
206                                              BoundType.OPEN, 3);
207        // (-5, 5], 3 = -5, -2, 1, 4
208        List<Integer> expected = Arrays.asList(-5, -2, 1, 4);
209        Collection<Integer> elements = IteratorToGeneratorAdapter.adapt(range).toCollection();
210        assertEquals(expected, elements);
211    }
212
213    @Test
214    public void testOpenOpenAscending() {
215        // (-5, 5), 3 = -2, 1, 4
216        IntegerRange range = Ranges.integerRange(-5, BoundType.OPEN, 5,
217                                              BoundType.OPEN, 3);
218        // (-5, 5), 3 = -2, 1, 4
219        List<Integer> expected = Arrays.asList(-2, 1, 4);
220        Collection<Integer> elements = IteratorToGeneratorAdapter.adapt(range).toCollection();
221        assertEquals(expected, elements);
222    }
223
224    @Test
225    public void testSingleStepAscending() {
226        // (-2, 2], 1 = -1, 0, 1, 2
227        IntegerRange range = Ranges.integerRange(-2, BoundType.OPEN, 2,
228                                              BoundType.CLOSED, 1);
229        // (-2, 2], 1 = -1, 0, 1, 2
230        List<Integer> expected = Arrays.asList(-1, 0, 1, 2);
231        Collection<Integer> elements = IteratorToGeneratorAdapter.adapt(range).toCollection();
232        assertEquals(expected, elements);
233    }
234
235    @Test
236    public void testClosedClosedDescending() {
237        // [5, -5], -3 = 5, 2, -1, -4
238        IntegerRange range = Ranges.integerRange(5, BoundType.CLOSED, -5,
239                                              BoundType.CLOSED, -3);
240        // [5, -5], -3 = 5, 2, -1, -4
241        List<Integer> expected = Arrays.asList(5, 2, -1, -4);
242        Collection<Integer> elements = IteratorToGeneratorAdapter.adapt(range).toCollection();
243        assertEquals(expected, elements);
244    }
245
246    @Test
247    public void testOpenClosedDescending() {
248        // (5, -5], -3 = 2, -1, -4
249        IntegerRange range = Ranges.integerRange(5, BoundType.OPEN, -5,
250                                              BoundType.CLOSED, -3);
251        // (5, -5], -3 = 2, -1, -4
252        List<Integer> expected = Arrays.asList(2, -1, -4);
253        Collection<Integer> elements = IteratorToGeneratorAdapter.adapt(range).toCollection();
254        assertEquals(expected, elements);
255    }
256
257    @Test
258    public void testClosedOpenDescending() {
259        // [5, -5), -3 = 5, 2, -1, -4
260        IntegerRange range = Ranges.integerRange(5, BoundType.CLOSED, -5,
261                                              BoundType.OPEN, -3);
262        // [5, -5), -3 = 5, 2, -1, -4
263        List<Integer> expected = Arrays.asList(5, 2, -1, -4);
264        Collection<Integer> elements = IteratorToGeneratorAdapter.adapt(range).toCollection();
265        assertEquals(expected, elements);
266    }
267
268    @Test
269    public void testOpenOpenDescending() {
270        // (5, -5), -3 = 2, -1, -4
271        IntegerRange range = Ranges.integerRange(5, BoundType.OPEN, -5,
272                                              BoundType.OPEN, -3);
273        // (5, -5), -3 = 2, -1, -4
274        List<Integer> expected = Arrays.asList(2, -1, -4);
275        Collection<Integer> elements = IteratorToGeneratorAdapter.adapt(range).toCollection();
276        assertEquals(expected, elements);
277    }
278
279    @Test
280    public void testSingleStepDescending() {
281        // [2, -2), -1 = 2, 1, 0, -1
282        IntegerRange range = Ranges.integerRange(2, BoundType.CLOSED, -2,
283                                              BoundType.OPEN, -1);
284        // [2, -2), -1 = 2, 1, 0, -1
285        List<Integer> expected = Arrays.asList(2, 1, 0, -1);
286        Collection<Integer> elements = IteratorToGeneratorAdapter.adapt(range).toCollection();
287        assertEquals(expected, elements);
288    }
289
290    @Test
291    public void testAscending() {
292        final List<Integer> list = new ArrayList<Integer>();
293        for (int i : ascIntRange) {
294            list.add(i);
295        }
296        assertTrue(expectedAsc.containsAll(list));
297    }
298
299    @Test
300    public void testDescending() {
301        final List<Integer> list = new ArrayList<Integer>();
302        for (int i : descIntRange) {
303            list.add(i);
304        }
305        assertTrue(expectedDesc.containsAll(list));
306    }
307
308    @Test
309    public void testToCollection() {
310        Collection<Integer> ascCol = IteratorToGeneratorAdapter.adapt(ascIntRange).toCollection();
311        assertEquals("Different collections", expectedAsc, ascCol);
312        Collection<Integer> descCol = IteratorToGeneratorAdapter.adapt(descIntRange).toCollection();
313        assertEquals("Different collections", expectedDesc, descCol);
314    }
315
316    @Test
317    public void testTransformedGenerator() {
318        int expected = 45;
319        int total = IteratorToGeneratorAdapter.adapt(ascIntRange)
320            .to(new Function<Generator<? extends Integer>, Integer>() {
321
322                public Integer evaluate(Generator<? extends Integer> obj) {
323                    int total = 0;
324                    for (Object element : obj.toCollection()) {
325                        total += (Integer) element;
326                    }
327                    return total;
328                }
329            });
330        assertEquals(expected, total);
331        expected = 55;
332        total = IteratorToGeneratorAdapter.adapt(descIntRange)
333            .to(new Function<Generator<? extends Integer>, Integer>() {
334
335                public Integer evaluate(Generator<? extends Integer> obj) {
336                    int total = 0;
337                    for (Object element : obj.toCollection()) {
338                        total += (Integer) element;
339                    }
340                    return total;
341                }
342            });
343        assertEquals(expected, total);
344    }
345
346    // Range tests
347    // ---------------------------------------------------------------
348
349    // A base range with all integers between -6 and 6
350    private final List<Integer> fullRange = Collections.unmodifiableList(Arrays
351        .asList(-6, -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6));
352
353    @Test
354    public void testEmptyRanges() {
355        IntegerRange empty1 = Ranges.integerRange(-2, BoundType.OPEN, -1,
356                                               BoundType.OPEN, 2);
357        assertTrue("The range was expected to be empty.", empty1.isEmpty());
358        IntegerRange empty2 = Ranges.integerRange(2, BoundType.OPEN, 0,
359                                               BoundType.OPEN, -2);
360        assertTrue("The range was expected to be empty.", empty2.isEmpty());
361        IntegerRange empty3 = Ranges.integerRange(0, BoundType.OPEN, 1,
362                                               BoundType.CLOSED, 2);
363        assertTrue("The range was expected to be empty.", empty3.isEmpty());
364        IntegerRange empty4 = Ranges.integerRange(-3, BoundType.OPEN, -3,
365                                               BoundType.OPEN, 1);
366        assertTrue("The range was expected to be empty.", empty4.isEmpty());
367        IntegerRange empty5 = Ranges.integerRange(-3, BoundType.CLOSED, -3,
368                                               BoundType.OPEN, 1);
369        assertTrue("The range was expected to be empty.", empty5.isEmpty());
370        IntegerRange empty6 = Ranges.integerRange(1, BoundType.OPEN, 0,
371                                               BoundType.CLOSED, -2);
372        assertTrue("The range was expected to be empty.", empty6.isEmpty());
373        IntegerRange notEmpty1 = Ranges.integerRange(-3, BoundType.CLOSED, -3,
374                                                  BoundType.CLOSED, 1);
375        assertFalse("The range was not expected to be empty.",
376                    notEmpty1.isEmpty());
377        IntegerRange notEmpty2 = Ranges.integerRange(-3, BoundType.OPEN, -2,
378                                                  BoundType.CLOSED, 1);
379        assertFalse("The range was not expected to be empty.",
380                    notEmpty2.isEmpty());
381        IntegerRange notEmpty3 = Ranges.integerRange(2, BoundType.OPEN, 1,
382                                                  BoundType.CLOSED, -1);
383        assertFalse("The range was not expected to be empty.",
384                    notEmpty3.isEmpty());
385        IntegerRange notEmpty4 = Ranges.integerRange(2, BoundType.CLOSED, 1,
386                                                  BoundType.OPEN, -1);
387        assertFalse("The range was not expected to be empty.",
388                    notEmpty4.isEmpty());
389        IntegerRange notEmpty5 = Ranges.integerRange(1, BoundType.CLOSED, 2,
390                                                  BoundType.OPEN, 1);
391        assertFalse("The range was not expected to be empty.",
392                    notEmpty5.isEmpty());
393    }
394
395    @Test
396    public void testClosedClosedAscendingContains() {
397        // [-5, 5], 3 = -5, -2, 1, 4
398        IntegerRange range = Ranges.integerRange(-5, BoundType.CLOSED, 5,
399                                              BoundType.CLOSED, 3);
400        // [-5, 5], 3 = -5, -2, 1, 4
401        List<Integer> arr = Arrays.asList(-5, -2, 1, 4);
402        for (Integer element : arr) {
403            assertTrue("Expected element [" + element +
404                               "] is missing in range [" + range + "]",
405                       range.contains(element));
406        }
407        List<Integer> elementsNotPresent = new ArrayList<Integer>(fullRange);
408        elementsNotPresent.removeAll(arr);
409        for (Integer element : elementsNotPresent) {
410            assertFalse("Unexpected element [" + element +
411                                "] is present in range [" + range + "]",
412                        range.contains(element));
413        }
414    }
415
416    @Test
417    public void testOpenClosedAscendingContains() {
418        // (-5, 5], 3 = -2, 1, 4
419        IntegerRange range = Ranges.integerRange(-5, BoundType.OPEN, 5,
420                                              BoundType.CLOSED, 3);
421        // (-5, 5], 3 = -2, 1, 4
422        List<Integer> arr = Arrays.asList(-2, 1, 4);
423        for (Integer element : arr) {
424            assertTrue("Expected element [" + element +
425                               "] is missing in range [" + range + "]",
426                       range.contains(element));
427        }
428        List<Integer> elementsNotPresent = new ArrayList<Integer>(fullRange);
429        elementsNotPresent.removeAll(arr);
430        for (Integer element : elementsNotPresent) {
431            assertFalse("Unexpected element [" + element +
432                                "] is present in range [" + range + "]",
433                        range.contains(element));
434        }
435    }
436
437    @Test
438    public void testClosedOpenAscendingContains() {
439        // [-5, 5), 3 = -5, -2, 1, 4
440        IntegerRange range = Ranges.integerRange(-5, BoundType.CLOSED, 5,
441                                              BoundType.OPEN, 3);
442        // (-5, 5], 3 = -5, -2, 1, 4
443        List<Integer> arr = Arrays.asList(-5, -2, 1, 4);
444        for (Integer element : arr) {
445            assertTrue("Expected element [" + element +
446                               "] is missing in range [" + range + "]",
447                       range.contains(element));
448        }
449        List<Integer> elementsNotPresent = new ArrayList<Integer>(fullRange);
450        elementsNotPresent.removeAll(arr);
451        for (Integer element : elementsNotPresent) {
452            assertFalse("Unexpected element [" + element +
453                                "] is present in range [" + range + "]",
454                        range.contains(element));
455        }
456    }
457
458    @Test
459    public void testOpenOpenAscendingContains() {
460        // (-5, 5), 3 = -2, 1, 4
461        IntegerRange range = Ranges.integerRange(-5, BoundType.OPEN, 5,
462                                              BoundType.OPEN, 3);
463        // (-5, 5), 3 = -2, 1, 4
464        List<Integer> arr = Arrays.asList(-2, 1, 4);
465        for (Integer element : arr) {
466            assertTrue("Expected element [" + element +
467                               "] is missing in range [" + range + "]",
468                       range.contains(element));
469        }
470        List<Integer> elementsNotPresent = new ArrayList<Integer>(fullRange);
471        elementsNotPresent.removeAll(arr);
472        for (Integer element : elementsNotPresent) {
473            assertFalse("Unexpected element [" + element +
474                                "] is present in range [" + range + "]",
475                        range.contains(element));
476        }
477    }
478
479    @Test
480    public void testContainsSingleStepAscending() {
481        // (-2, 2], 1 = -1, 0, 1, 2
482        IntegerRange ascendingRange = Ranges.integerRange(-2, BoundType.OPEN, 2,
483                                                       BoundType.CLOSED, 1);
484        // (-2, 2], 1 = -1, 0, 1, 2
485        List<Integer> arr = Arrays.asList(-1, 0, 1, 2);
486        for (Integer element : arr) {
487            assertTrue("Expected element [" + element +
488                               "] is missing in range [" + ascendingRange + "]",
489                       ascendingRange.contains(element));
490        }
491        List<Integer> elementsNotPresent = new ArrayList<Integer>(fullRange);
492        elementsNotPresent.removeAll(arr);
493        for (Integer element : elementsNotPresent) {
494            assertFalse("Unexpected element [" + element +
495                                "] is present in range [" + ascendingRange +
496                                "]",
497                        ascendingRange.contains(element));
498        }
499    }
500
501    @Test
502    public void testClosedClosedDescendingContains() {
503        // [5, -5], -3 = 5, 2, -1, -4
504        IntegerRange range = Ranges.integerRange(5, BoundType.CLOSED, -5,
505                                              BoundType.CLOSED, -3);
506        // [5, -5], -3 = 5, 2, -1, -4
507        List<Integer> arr = Arrays.asList(5, 2, -1, -4);
508        for (Integer element : arr) {
509            assertTrue("Expected element [" + element +
510                               "] is missing in range [" + range + "]",
511                       range.contains(element));
512        }
513        List<Integer> elementsNotPresent = new ArrayList<Integer>(fullRange);
514        elementsNotPresent.removeAll(arr);
515        for (Integer element : elementsNotPresent) {
516            assertFalse("Unexpected element [" + element +
517                                "] is present in range [" + range + "]",
518                        range.contains(element));
519        }
520    }
521
522    @Test
523    public void testOpenClosedDescendingContains() {
524        // (5, -5], -3 = 2, -1, -4
525        IntegerRange range = Ranges.integerRange(5, BoundType.OPEN, -5,
526                                              BoundType.CLOSED, -3);
527        // (5, -5], -3 = 2, -1, -4
528        List<Integer> arr = Arrays.asList(2, -1, -4);
529        for (Integer element : arr) {
530            assertTrue("Expected element [" + element +
531                               "] is missing in range [" + range + "]",
532                       range.contains(element));
533        }
534        List<Integer> elementsNotPresent = new ArrayList<Integer>(fullRange);
535        elementsNotPresent.removeAll(arr);
536        for (Integer element : elementsNotPresent) {
537            assertFalse("Unexpected element [" + element +
538                                "] is present in range [" + range + "]",
539                        range.contains(element));
540        }
541    }
542
543    @Test
544    public void testClosedOpenDescendingContains() {
545        // [5, -5), -3 = 5, 2, -1, -4
546        IntegerRange range = Ranges.integerRange(5, BoundType.CLOSED, -5,
547                                              BoundType.OPEN, -3);
548        // [5, -5), -3 = 5, 2, -1, -4
549        List<Integer> arr = Arrays.asList(5, 2, -1, -4);
550        for (Integer element : arr) {
551            assertTrue("Expected element [" + element +
552                               "] is missing in range [" + range + "]",
553                       range.contains(element));
554        }
555        List<Integer> elementsNotPresent = new ArrayList<Integer>(fullRange);
556        elementsNotPresent.removeAll(arr);
557        for (Integer element : elementsNotPresent) {
558            assertFalse("Unexpected element [" + element +
559                                "] is present in range [" + range + "]",
560                        range.contains(element));
561        }
562    }
563
564    @Test
565    public void testOpenOpenDescendingContains() {
566        // (5, -5), -3 = 2, -1, -4
567        IntegerRange range = Ranges.integerRange(5, BoundType.OPEN, -5,
568                                              BoundType.OPEN, -3);
569        // (5, -5), -3 = 2, -1, -4
570        List<Integer> arr = Arrays.asList(2, -1, -4);
571        for (Integer element : arr) {
572            assertTrue("Expected element [" + element +
573                               "] is missing in range [" + range + "]",
574                       range.contains(element));
575        }
576        List<Integer> elementsNotPresent = new ArrayList<Integer>(fullRange);
577        elementsNotPresent.removeAll(arr);
578        for (Integer element : elementsNotPresent) {
579            assertFalse("Unexpected element [" + element +
580                                "] is present in range [" + range + "]",
581                        range.contains(element));
582        }
583    }
584
585    @Test
586    public void testContainsSingleStepDescending() {
587        // [2, -2), -1 = 2, 1, 0, -1
588        IntegerRange descendingRange = Ranges.integerRange(2, BoundType.CLOSED,
589                                                        -2, BoundType.OPEN, -1);
590        // [2, -2), -1 = 2, 1, 0, -1
591        List<Integer> arr = Arrays.asList(2, 1, 0, -1);
592        for (Integer element : arr) {
593            assertTrue("Expected element [" + element +
594                               "] is missing in range [" + descendingRange +
595                               "]",
596                       descendingRange.contains(element));
597        }
598        List<Integer> elementsNotPresent = new ArrayList<Integer>(fullRange);
599        elementsNotPresent.removeAll(arr);
600        for (Integer element : elementsNotPresent) {
601            assertFalse("Unexpected element [" + element +
602                                "] is present in range [" + descendingRange +
603                                "]",
604                        descendingRange.contains(element));
605        }
606    }
607
608    @Test
609    public void testContainsNullOrEmpty() {
610        IntegerRange range = Ranges.integerRange(-2, BoundType.OPEN, 2,
611                                              BoundType.CLOSED, 1);
612        assertFalse(range.contains(null));
613    }
614
615    @SuppressWarnings("unchecked")
616    @Test
617    public void testContainsAll() {
618        // (-2, 2], 1 = -1, 0, 1, 2
619        IntegerRange range = Ranges.integerRange(-2, BoundType.OPEN, 2,
620                                              BoundType.CLOSED, 1);
621        List<Integer> list = Arrays.asList(-1, 0, 1, 2);
622        assertTrue("Range [" + range +
623                   "] was expected to contain all elements from list [" + list +
624                   "]", range.containsAll(list));
625        List<Integer> listWithExtraElements = Arrays.asList(2, -1, 0, 1, 2, 3);
626        assertFalse("Range [" + range + "] has more elements than expected",
627                    range.containsAll(listWithExtraElements));
628        assertFalse(range.containsAll(null));
629        assertFalse(range.containsAll(Collections.EMPTY_LIST));
630    }
631
632    @Test
633    public void testEquals()
634        throws Exception {
635        // equals basic properties
636        IntegerRange range = Ranges.integerRange(-2, BoundType.CLOSED, 2,
637                                              BoundType.OPEN, 1);
638        assertEquals("equals must be reflexive", range, range);
639        assertEquals("hashCode must be reflexive", range.hashCode(),
640                     range.hashCode());
641        assertTrue(!range.equals(null)); // should be able to compare to null
642
643        Object range2 = Ranges.integerRange(-2, BoundType.CLOSED, 2,
644                                         BoundType.OPEN, 1);
645        if (range.equals(range2)) {
646            assertEquals("equals implies hash equals", range.hashCode(),
647                         range2.hashCode());
648            assertEquals("equals must be symmetric", range2, range);
649        } else {
650            assertTrue("equals must be symmetric", !range2.equals(range));
651        }
652
653        // Changing attributes
654        Object range3 = Ranges.integerRange(-1, BoundType.CLOSED, 2,
655                                         BoundType.OPEN, 1);
656        assertFalse("Invalid equals after changing attributes",
657                    range.equals(range3));
658
659        Object range4 = Ranges.integerRange(-2, BoundType.OPEN, 2, BoundType.OPEN,
660                                         1);
661        assertFalse("Invalid equals after changing attributes",
662                    range.equals(range4));
663
664        Object range5 = Ranges.integerRange(-2, BoundType.CLOSED, 1,
665                                         BoundType.OPEN, 1);
666        assertFalse("Invalid equals after changing attributes",
667                    range.equals(range5));
668
669        Object range6 = Ranges.integerRange(-2, BoundType.CLOSED, 2,
670                                         BoundType.CLOSED, 1);
671        assertFalse("Invalid equals after changing attributes",
672                    range.equals(range6));
673
674        Object range7 = Ranges.integerRange(-2, BoundType.CLOSED, 2,
675                                         BoundType.OPEN, 2);
676        assertFalse("Invalid equals after changing attributes",
677                    range.equals(range7));
678
679        // Using different constructors
680        IntegerRange range8 = Ranges.integerRange(Long.valueOf(-2),
681                                                  Long.valueOf(2), Long.valueOf(1));
682        assertEquals("Invalid equals using different constructor", range,
683                     range8);
684
685        IntegerRange range9 = Ranges.integerRange(Long.valueOf(-2),
686                                                  Long.valueOf(2));
687        assertEquals("Invalid equals using different constructor", range,
688                     range9);
689
690        Endpoint<Integer> leftEndpoint = new Endpoint<Integer>(-2,
691                                                               BoundType.CLOSED);
692        Endpoint<Integer> rightEndpoint = new Endpoint<Integer>(2,
693                                                                BoundType.OPEN);
694        IntegerRange range10 = Ranges.integerRange(leftEndpoint, rightEndpoint, 1);
695        assertEquals("Invalid equals using different constructor", range,
696                     range10);
697    }
698
699    @Test
700    public void testToString() {
701        IntegerRange range = Ranges.integerRange(-2, BoundType.OPEN, 2,
702                                              BoundType.CLOSED, 1);
703        assertEquals("Wrong string value", "IntegerRange<(-2, 2], 1>",
704                     range.toString());
705    }
706
707    @Test
708    public void testConstructorUsingSameEndpoint() {
709        Endpoint<Integer> uniqueEndpoint = new Endpoint<Integer>(
710                                                                 10,
711                                                                 BoundType.CLOSED);
712        try {
713            Ranges.integerRange(uniqueEndpoint, uniqueEndpoint, 1);
714        } catch (IllegalArgumentException e) {
715            fail("Not expected to get here");
716        }
717    }
718
719    @Test
720    public void testInvalidRange() {
721        try {
722            Ranges.integerRange(10, BoundType.OPEN, -5, BoundType.CLOSED, 10);
723            fail("Not expected to get here");
724        } catch (IllegalArgumentException e) {
725            // Do nothing
726        }
727        Endpoint<Integer> leftEndpoint = new Endpoint<Integer>(10,
728                                                               BoundType.CLOSED);
729        Endpoint<Integer> rightEndpoint = new Endpoint<Integer>(-5,
730                                                                BoundType.OPEN);
731        try {
732            Ranges.integerRange(leftEndpoint, rightEndpoint, 1);
733            fail("Not expected to get here");
734        } catch (IllegalArgumentException e) {
735            // Do nothing
736        }
737    }
738
739    @Test
740    public void testDefaultStep() {
741        assertEquals("Invalid default step", Integer.valueOf(-1),
742                     IntegerRange.DEFAULT_STEP.evaluate(10, 1));
743        assertEquals("Invalid default step", Integer.valueOf(1),
744                     IntegerRange.DEFAULT_STEP.evaluate(1, 10));
745    }
746
747}