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