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