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