View Javadoc
1   /*
2    * Copyright (C) 2008 The Guava Authors
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    * http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  
17  package com.google.common.collect;
18  
19  import static com.google.common.collect.BoundType.CLOSED;
20  import static com.google.common.collect.BoundType.OPEN;
21  import static com.google.common.collect.DiscreteDomain.integers;
22  import static com.google.common.testing.SerializableTester.reserializeAndAssert;
23  import static java.util.Arrays.asList;
24  
25  import com.google.common.annotations.GwtCompatible;
26  import com.google.common.base.Predicate;
27  import com.google.common.collect.testing.Helpers;
28  import com.google.common.testing.EqualsTester;
29  
30  import junit.framework.TestCase;
31  
32  import java.util.Arrays;
33  import java.util.Collections;
34  import java.util.List;
35  import java.util.NoSuchElementException;
36  
37  /**
38   * Unit test for {@link Range}.
39   *
40   * @author Kevin Bourrillion
41   */
42  @GwtCompatible
43  public class RangeTest extends TestCase {
44    public void testOpen() {
45      Range<Integer> range = Range.open(4, 8);
46      checkContains(range);
47      assertTrue(range.hasLowerBound());
48      assertEquals(4, (int) range.lowerEndpoint());
49      assertEquals(OPEN, range.lowerBoundType());
50      assertTrue(range.hasUpperBound());
51      assertEquals(8, (int) range.upperEndpoint());
52      assertEquals(OPEN, range.upperBoundType());
53      assertFalse(range.isEmpty());
54      assertEquals("(4\u20258)", range.toString());
55      reserializeAndAssert(range);
56    }
57  
58    public void testOpen_invalid() {
59      try {
60        Range.open(4, 3);
61        fail();
62      } catch (IllegalArgumentException expected) {
63      }
64      try {
65        Range.open(3, 3);
66        fail();
67      } catch (IllegalArgumentException expected) {
68      }
69    }
70  
71    public void testClosed() {
72      Range<Integer> range = Range.closed(5, 7);
73      checkContains(range);
74      assertTrue(range.hasLowerBound());
75      assertEquals(5, (int) range.lowerEndpoint());
76      assertEquals(CLOSED, range.lowerBoundType());
77      assertTrue(range.hasUpperBound());
78      assertEquals(7, (int) range.upperEndpoint());
79      assertEquals(CLOSED, range.upperBoundType());
80      assertFalse(range.isEmpty());
81      assertEquals("[5\u20257]", range.toString());
82      reserializeAndAssert(range);
83    }
84  
85    public void testClosed_invalid() {
86      try {
87        Range.closed(4, 3);
88        fail();
89      } catch (IllegalArgumentException expected) {
90      }
91    }
92  
93    public void testOpenClosed() {
94      Range<Integer> range = Range.openClosed(4, 7);
95      checkContains(range);
96      assertTrue(range.hasLowerBound());
97      assertEquals(4, (int) range.lowerEndpoint());
98      assertEquals(OPEN, range.lowerBoundType());
99      assertTrue(range.hasUpperBound());
100     assertEquals(7, (int) range.upperEndpoint());
101     assertEquals(CLOSED, range.upperBoundType());
102     assertFalse(range.isEmpty());
103     assertEquals("(4\u20257]", range.toString());
104     reserializeAndAssert(range);
105   }
106 
107   public void testClosedOpen() {
108     Range<Integer> range = Range.closedOpen(5, 8);
109     checkContains(range);
110     assertTrue(range.hasLowerBound());
111     assertEquals(5, (int) range.lowerEndpoint());
112     assertEquals(CLOSED, range.lowerBoundType());
113     assertTrue(range.hasUpperBound());
114     assertEquals(8, (int) range.upperEndpoint());
115     assertEquals(OPEN, range.upperBoundType());
116     assertFalse(range.isEmpty());
117     assertEquals("[5\u20258)", range.toString());
118     reserializeAndAssert(range);
119   }
120 
121   public void testIsConnected() {
122     assertTrue(Range.closed(3, 5).isConnected(Range.open(5, 6)));
123     assertTrue(Range.closed(3, 5).isConnected(Range.openClosed(5, 5)));
124     assertTrue(Range.open(3, 5).isConnected(Range.closed(5, 6)));
125     assertTrue(Range.closed(3, 7).isConnected(Range.open(6, 8)));
126     assertTrue(Range.open(3, 7).isConnected(Range.closed(5, 6)));
127     assertFalse(Range.closed(3, 5).isConnected(Range.closed(7, 8)));
128     assertFalse(Range.closed(3, 5).isConnected(Range.closedOpen(7, 7)));
129   }
130 
131   private static void checkContains(Range<Integer> range) {
132     assertFalse(range.contains(4));
133     assertTrue(range.contains(5));
134     assertTrue(range.contains(7));
135     assertFalse(range.contains(8));
136   }
137 
138   public void testSingleton() {
139     Range<Integer> range = Range.closed(4, 4);
140     assertFalse(range.contains(3));
141     assertTrue(range.contains(4));
142     assertFalse(range.contains(5));
143     assertTrue(range.hasLowerBound());
144     assertEquals(4, (int) range.lowerEndpoint());
145     assertEquals(CLOSED, range.lowerBoundType());
146     assertTrue(range.hasUpperBound());
147     assertEquals(4, (int) range.upperEndpoint());
148     assertEquals(CLOSED, range.upperBoundType());
149     assertFalse(range.isEmpty());
150     assertEquals("[4\u20254]", range.toString());
151     reserializeAndAssert(range);
152   }
153 
154   public void testEmpty1() {
155     Range<Integer> range = Range.closedOpen(4, 4);
156     assertFalse(range.contains(3));
157     assertFalse(range.contains(4));
158     assertFalse(range.contains(5));
159     assertTrue(range.hasLowerBound());
160     assertEquals(4, (int) range.lowerEndpoint());
161     assertEquals(CLOSED, range.lowerBoundType());
162     assertTrue(range.hasUpperBound());
163     assertEquals(4, (int) range.upperEndpoint());
164     assertEquals(OPEN, range.upperBoundType());
165     assertTrue(range.isEmpty());
166     assertEquals("[4\u20254)", range.toString());
167     reserializeAndAssert(range);
168   }
169 
170   public void testEmpty2() {
171     Range<Integer> range = Range.openClosed(4, 4);
172     assertFalse(range.contains(3));
173     assertFalse(range.contains(4));
174     assertFalse(range.contains(5));
175     assertTrue(range.hasLowerBound());
176     assertEquals(4, (int) range.lowerEndpoint());
177     assertEquals(OPEN, range.lowerBoundType());
178     assertTrue(range.hasUpperBound());
179     assertEquals(4, (int) range.upperEndpoint());
180     assertEquals(CLOSED, range.upperBoundType());
181     assertTrue(range.isEmpty());
182     assertEquals("(4\u20254]", range.toString());
183     reserializeAndAssert(range);
184   }
185 
186   public void testLessThan() {
187     Range<Integer> range = Range.lessThan(5);
188     assertTrue(range.contains(Integer.MIN_VALUE));
189     assertTrue(range.contains(4));
190     assertFalse(range.contains(5));
191     assertUnboundedBelow(range);
192     assertTrue(range.hasUpperBound());
193     assertEquals(5, (int) range.upperEndpoint());
194     assertEquals(OPEN, range.upperBoundType());
195     assertFalse(range.isEmpty());
196     assertEquals("(-\u221e\u20255)", range.toString());
197     reserializeAndAssert(range);
198   }
199 
200   public void testGreaterThan() {
201     Range<Integer> range = Range.greaterThan(5);
202     assertFalse(range.contains(5));
203     assertTrue(range.contains(6));
204     assertTrue(range.contains(Integer.MAX_VALUE));
205     assertTrue(range.hasLowerBound());
206     assertEquals(5, (int) range.lowerEndpoint());
207     assertEquals(OPEN, range.lowerBoundType());
208     assertUnboundedAbove(range);
209     assertFalse(range.isEmpty());
210     assertEquals("(5\u2025+\u221e)", range.toString());
211     reserializeAndAssert(range);
212   }
213 
214   public void testAtLeast() {
215     Range<Integer> range = Range.atLeast(6);
216     assertFalse(range.contains(5));
217     assertTrue(range.contains(6));
218     assertTrue(range.contains(Integer.MAX_VALUE));
219     assertTrue(range.hasLowerBound());
220     assertEquals(6, (int) range.lowerEndpoint());
221     assertEquals(CLOSED, range.lowerBoundType());
222     assertUnboundedAbove(range);
223     assertFalse(range.isEmpty());
224     assertEquals("[6\u2025+\u221e)", range.toString());
225     reserializeAndAssert(range);
226   }
227 
228   public void testAtMost() {
229     Range<Integer> range = Range.atMost(4);
230     assertTrue(range.contains(Integer.MIN_VALUE));
231     assertTrue(range.contains(4));
232     assertFalse(range.contains(5));
233     assertUnboundedBelow(range);
234     assertTrue(range.hasUpperBound());
235     assertEquals(4, (int) range.upperEndpoint());
236     assertEquals(CLOSED, range.upperBoundType());
237     assertFalse(range.isEmpty());
238     assertEquals("(-\u221e\u20254]", range.toString());
239     reserializeAndAssert(range);
240   }
241 
242   public void testAll() {
243     Range<Integer> range = Range.all();
244     assertTrue(range.contains(Integer.MIN_VALUE));
245     assertTrue(range.contains(Integer.MAX_VALUE));
246     assertUnboundedBelow(range);
247     assertUnboundedAbove(range);
248     assertFalse(range.isEmpty());
249     assertEquals("(-\u221e\u2025+\u221e)", range.toString());
250     assertSame(range, reserializeAndAssert(range));
251     assertSame(range, Range.all());
252   }
253 
254   private static void assertUnboundedBelow(Range<Integer> range) {
255     assertFalse(range.hasLowerBound());
256     try {
257       range.lowerEndpoint();
258       fail();
259     } catch (IllegalStateException expected) {
260     }
261     try {
262       range.lowerBoundType();
263       fail();
264     } catch (IllegalStateException expected) {
265     }
266   }
267 
268   private static void assertUnboundedAbove(Range<Integer> range) {
269     assertFalse(range.hasUpperBound());
270     try {
271       range.upperEndpoint();
272       fail();
273     } catch (IllegalStateException expected) {
274     }
275     try {
276       range.upperBoundType();
277       fail();
278     } catch (IllegalStateException expected) {
279     }
280   }
281 
282   public void testOrderingCuts() {
283     Cut<Integer> a = Range.lessThan(0).lowerBound;
284     Cut<Integer> b = Range.atLeast(0).lowerBound;
285     Cut<Integer> c = Range.greaterThan(0).lowerBound;
286     Cut<Integer> d = Range.atLeast(1).lowerBound;
287     Cut<Integer> e = Range.greaterThan(1).lowerBound;
288     Cut<Integer> f = Range.greaterThan(1).upperBound;
289 
290     Helpers.testCompareToAndEquals(ImmutableList.of(a, b, c, d, e, f));
291   }
292 
293   public void testContainsAll() {
294     Range<Integer> range = Range.closed(3, 5);
295     assertTrue(range.containsAll(asList(3, 3, 4, 5)));
296     assertFalse(range.containsAll(asList(3, 3, 4, 5, 6)));
297 
298     // We happen to know that natural-order sorted sets use a different code
299     // path, so we test that separately
300     assertTrue(range.containsAll(ImmutableSortedSet.of(3, 3, 4, 5)));
301     assertTrue(range.containsAll(ImmutableSortedSet.of(3)));
302     assertTrue(range.containsAll(ImmutableSortedSet.<Integer>of()));
303     assertFalse(range.containsAll(ImmutableSortedSet.of(3, 3, 4, 5, 6)));
304 
305     assertTrue(Range.openClosed(3, 3).containsAll(
306         Collections.<Integer>emptySet()));
307   }
308 
309   public void testEncloses_open() {
310     Range<Integer> range = Range.open(2, 5);
311     assertTrue(range.encloses(range));
312     assertTrue(range.encloses(Range.open(2, 4)));
313     assertTrue(range.encloses(Range.open(3, 5)));
314     assertTrue(range.encloses(Range.closed(3, 4)));
315 
316     assertFalse(range.encloses(Range.openClosed(2, 5)));
317     assertFalse(range.encloses(Range.closedOpen(2, 5)));
318     assertFalse(range.encloses(Range.closed(1, 4)));
319     assertFalse(range.encloses(Range.closed(3, 6)));
320     assertFalse(range.encloses(Range.greaterThan(3)));
321     assertFalse(range.encloses(Range.lessThan(3)));
322     assertFalse(range.encloses(Range.atLeast(3)));
323     assertFalse(range.encloses(Range.atMost(3)));
324     assertFalse(range.encloses(Range.<Integer>all()));
325   }
326 
327   public void testEncloses_closed() {
328     Range<Integer> range = Range.closed(2, 5);
329     assertTrue(range.encloses(range));
330     assertTrue(range.encloses(Range.open(2, 5)));
331     assertTrue(range.encloses(Range.openClosed(2, 5)));
332     assertTrue(range.encloses(Range.closedOpen(2, 5)));
333     assertTrue(range.encloses(Range.closed(3, 5)));
334     assertTrue(range.encloses(Range.closed(2, 4)));
335 
336     assertFalse(range.encloses(Range.open(1, 6)));
337     assertFalse(range.encloses(Range.greaterThan(3)));
338     assertFalse(range.encloses(Range.lessThan(3)));
339     assertFalse(range.encloses(Range.atLeast(3)));
340     assertFalse(range.encloses(Range.atMost(3)));
341     assertFalse(range.encloses(Range.<Integer>all()));
342   }
343 
344   public void testIntersection_empty() {
345     Range<Integer> range = Range.closedOpen(3, 3);
346     assertEquals(range, range.intersection(range));
347 
348     try {
349       range.intersection(Range.open(3, 5));
350       fail();
351     } catch (IllegalArgumentException expected) {
352     }
353     try {
354       range.intersection(Range.closed(0, 2));
355       fail();
356     } catch (IllegalArgumentException expected) {
357     }
358   }
359 
360   public void testIntersection_deFactoEmpty() {
361     Range<Integer> range = Range.open(3, 4);
362     assertEquals(range, range.intersection(range));
363 
364     assertEquals(Range.openClosed(3, 3),
365         range.intersection(Range.atMost(3)));
366     assertEquals(Range.closedOpen(4, 4),
367         range.intersection(Range.atLeast(4)));
368 
369     try {
370       range.intersection(Range.lessThan(3));
371       fail();
372     } catch (IllegalArgumentException expected) {
373     }
374     try {
375       range.intersection(Range.greaterThan(4));
376       fail();
377     } catch (IllegalArgumentException expected) {
378     }
379 
380     range = Range.closed(3, 4);
381     assertEquals(Range.openClosed(4, 4),
382         range.intersection(Range.greaterThan(4)));
383   }
384 
385   public void testIntersection_singleton() {
386     Range<Integer> range = Range.closed(3, 3);
387     assertEquals(range, range.intersection(range));
388 
389     assertEquals(range, range.intersection(Range.atMost(4)));
390     assertEquals(range, range.intersection(Range.atMost(3)));
391     assertEquals(range, range.intersection(Range.atLeast(3)));
392     assertEquals(range, range.intersection(Range.atLeast(2)));
393 
394     assertEquals(Range.closedOpen(3, 3),
395         range.intersection(Range.lessThan(3)));
396     assertEquals(Range.openClosed(3, 3),
397         range.intersection(Range.greaterThan(3)));
398 
399     try {
400       range.intersection(Range.atLeast(4));
401       fail();
402     } catch (IllegalArgumentException expected) {
403     }
404     try {
405       range.intersection(Range.atMost(2));
406       fail();
407     } catch (IllegalArgumentException expected) {
408     }
409   }
410 
411   public void testIntersection_general() {
412     Range<Integer> range = Range.closed(4, 8);
413 
414     // separate below
415     try {
416       range.intersection(Range.closed(0, 2));
417       fail();
418     } catch (IllegalArgumentException expected) {
419     }
420 
421     // adjacent below
422     assertEquals(Range.closedOpen(4, 4),
423         range.intersection(Range.closedOpen(2, 4)));
424 
425     // overlap below
426     assertEquals(Range.closed(4, 6), range.intersection(Range.closed(2, 6)));
427 
428     // enclosed with same start
429     assertEquals(Range.closed(4, 6), range.intersection(Range.closed(4, 6)));
430 
431     // enclosed, interior
432     assertEquals(Range.closed(5, 7), range.intersection(Range.closed(5, 7)));
433 
434     // enclosed with same end
435     assertEquals(Range.closed(6, 8), range.intersection(Range.closed(6, 8)));
436 
437     // equal
438     assertEquals(range, range.intersection(range));
439 
440     // enclosing with same start
441     assertEquals(range, range.intersection(Range.closed(4, 10)));
442 
443     // enclosing with same end
444     assertEquals(range, range.intersection(Range.closed(2, 8)));
445 
446     // enclosing, exterior
447     assertEquals(range, range.intersection(Range.closed(2, 10)));
448 
449     // overlap above
450     assertEquals(Range.closed(6, 8), range.intersection(Range.closed(6, 10)));
451 
452     // adjacent above
453     assertEquals(Range.openClosed(8, 8),
454         range.intersection(Range.openClosed(8, 10)));
455 
456     // separate above
457     try {
458       range.intersection(Range.closed(10, 12));
459       fail();
460     } catch (IllegalArgumentException expected) {
461     }
462   }
463 
464   public void testSpan_general() {
465     Range<Integer> range = Range.closed(4, 8);
466 
467     // separate below
468     assertEquals(Range.closed(0, 8), range.span(Range.closed(0, 2)));
469     assertEquals(Range.atMost(8), range.span(Range.atMost(2)));
470 
471     // adjacent below
472     assertEquals(Range.closed(2, 8), range.span(Range.closedOpen(2, 4)));
473     assertEquals(Range.atMost(8), range.span(Range.lessThan(4)));
474 
475     // overlap below
476     assertEquals(Range.closed(2, 8), range.span(Range.closed(2, 6)));
477     assertEquals(Range.atMost(8), range.span(Range.atMost(6)));
478 
479     // enclosed with same start
480     assertEquals(range, range.span(Range.closed(4, 6)));
481 
482     // enclosed, interior
483     assertEquals(range, range.span(Range.closed(5, 7)));
484 
485     // enclosed with same end
486     assertEquals(range, range.span(Range.closed(6, 8)));
487 
488     // equal
489     assertEquals(range, range.span(range));
490 
491     // enclosing with same start
492     assertEquals(Range.closed(4, 10), range.span(Range.closed(4, 10)));
493     assertEquals(Range.atLeast(4), range.span(Range.atLeast(4)));
494 
495     // enclosing with same end
496     assertEquals(Range.closed(2, 8), range.span(Range.closed(2, 8)));
497     assertEquals(Range.atMost(8), range.span(Range.atMost(8)));
498 
499     // enclosing, exterior
500     assertEquals(Range.closed(2, 10), range.span(Range.closed(2, 10)));
501     assertEquals(Range.<Integer>all(), range.span(Range.<Integer>all()));
502 
503     // overlap above
504     assertEquals(Range.closed(4, 10), range.span(Range.closed(6, 10)));
505     assertEquals(Range.atLeast(4), range.span(Range.atLeast(6)));
506 
507     // adjacent above
508     assertEquals(Range.closed(4, 10), range.span(Range.openClosed(8, 10)));
509     assertEquals(Range.atLeast(4), range.span(Range.greaterThan(8)));
510 
511     // separate above
512     assertEquals(Range.closed(4, 12), range.span(Range.closed(10, 12)));
513     assertEquals(Range.atLeast(4), range.span(Range.atLeast(10)));
514   }
515 
516   public void testApply() {
517     Predicate<Integer> predicate = Range.closed(2, 3);
518     assertFalse(predicate.apply(1));
519     assertTrue(predicate.apply(2));
520     assertTrue(predicate.apply(3));
521     assertFalse(predicate.apply(4));
522   }
523 
524   public void testEquals() {
525     new EqualsTester()
526         .addEqualityGroup(Range.open(1, 5),
527             Range.range(1, OPEN, 5, OPEN))
528         .addEqualityGroup(Range.greaterThan(2), Range.greaterThan(2))
529         .addEqualityGroup(Range.all(), Range.all())
530         .addEqualityGroup("Phil")
531         .testEquals();
532   }
533 
534   public void testLegacyComparable() {
535     Range<LegacyComparable> range
536         = Range.closed(LegacyComparable.X, LegacyComparable.Y);
537   }
538 
539   static final DiscreteDomain<Integer> UNBOUNDED_DOMAIN =
540       new DiscreteDomain<Integer>() {
541         @Override public Integer next(Integer value) {
542           return integers().next(value);
543         }
544 
545         @Override public Integer previous(Integer value) {
546           return integers().previous(value);
547         }
548 
549         @Override public long distance(Integer start, Integer end) {
550           return integers().distance(start, end);
551         }
552       };
553 
554   public void testCanonical() {
555     assertEquals(Range.closedOpen(1, 5),
556         Range.closed(1, 4).canonical(integers()));
557     assertEquals(Range.closedOpen(1, 5),
558         Range.open(0, 5).canonical(integers()));
559     assertEquals(Range.closedOpen(1, 5),
560         Range.closedOpen(1, 5).canonical(integers()));
561     assertEquals(Range.closedOpen(1, 5),
562         Range.openClosed(0, 4).canonical(integers()));
563 
564     assertEquals(Range.closedOpen(Integer.MIN_VALUE, 0),
565         Range.closedOpen(Integer.MIN_VALUE, 0).canonical(integers()));
566 
567     assertEquals(Range.closedOpen(Integer.MIN_VALUE, 0),
568         Range.lessThan(0).canonical(integers()));
569     assertEquals(Range.closedOpen(Integer.MIN_VALUE, 1),
570         Range.atMost(0).canonical(integers()));
571     assertEquals(Range.atLeast(0), Range.atLeast(0).canonical(integers()));
572     assertEquals(Range.atLeast(1), Range.greaterThan(0).canonical(integers()));
573 
574     assertEquals(Range.atLeast(Integer.MIN_VALUE), Range.<Integer>all().canonical(integers()));
575   }
576 
577   public void testCanonical_unboundedDomain() {
578     assertEquals(Range.lessThan(0), Range.lessThan(0).canonical(UNBOUNDED_DOMAIN));
579     assertEquals(Range.lessThan(1), Range.atMost(0).canonical(UNBOUNDED_DOMAIN));
580     assertEquals(Range.atLeast(0), Range.atLeast(0).canonical(UNBOUNDED_DOMAIN));
581     assertEquals(Range.atLeast(1), Range.greaterThan(0).canonical(UNBOUNDED_DOMAIN));
582 
583     assertEquals(Range.all(), Range.<Integer>all().canonical(UNBOUNDED_DOMAIN));
584   }
585 
586   public void testEncloseAll() {
587     assertEquals(Range.closed(0, 0), Range.encloseAll(Arrays.asList(0)));
588     assertEquals(Range.closed(-3, 5), Range.encloseAll(Arrays.asList(5, -3)));
589     assertEquals(Range.closed(-3, 5), Range.encloseAll(Arrays.asList(1, 2, 2, 2, 5, -3, 0, -1)));
590   }
591 
592   public void testEncloseAll_empty() {
593     try {
594       Range.encloseAll(ImmutableSet.<Integer>of());
595       fail();
596     } catch (NoSuchElementException expected) {}
597   }
598 
599   public void testEncloseAll_nullValue() {
600     List<Integer> nullFirst = Lists.newArrayList(null, 0);
601     try {
602       Range.encloseAll(nullFirst);
603       fail();
604     } catch (NullPointerException expected) {}
605     List<Integer> nullNotFirst = Lists.newArrayList(0, null);
606     try {
607       Range.encloseAll(nullNotFirst);
608       fail();
609     } catch (NullPointerException expected) {}
610   }
611 
612   public void testEquivalentFactories() {
613     new EqualsTester()
614         .addEqualityGroup(Range.all())
615         .addEqualityGroup(
616             Range.atLeast(1),
617             Range.downTo(1, CLOSED))
618         .addEqualityGroup(
619             Range.greaterThan(1),
620             Range.downTo(1, OPEN))
621         .addEqualityGroup(
622             Range.atMost(7),
623             Range.upTo(7, CLOSED))
624         .addEqualityGroup(
625             Range.lessThan(7),
626             Range.upTo(7, OPEN))
627         .addEqualityGroup(
628             Range.open(1, 7),
629             Range.range(1, OPEN, 7, OPEN))
630         .addEqualityGroup(
631             Range.openClosed(1, 7),
632             Range.range(1, OPEN, 7, CLOSED))
633         .addEqualityGroup(
634             Range.closed(1, 7),
635             Range.range(1, CLOSED, 7, CLOSED))
636         .addEqualityGroup(
637             Range.closedOpen(1, 7),
638             Range.range(1, CLOSED, 7, OPEN))
639         .testEquals();
640   }
641 }