1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.commons.lang3;
20
21 import static org.apache.commons.lang3.LangAssertions.assertNullPointerException;
22 import static org.junit.jupiter.api.Assertions.assertEquals;
23 import static org.junit.jupiter.api.Assertions.assertFalse;
24 import static org.junit.jupiter.api.Assertions.assertNotEquals;
25 import static org.junit.jupiter.api.Assertions.assertNotNull;
26 import static org.junit.jupiter.api.Assertions.assertThrows;
27 import static org.junit.jupiter.api.Assertions.assertTrue;
28
29 import java.lang.reflect.Modifier;
30 import java.util.Iterator;
31 import java.util.NoSuchElementException;
32
33 import org.junit.jupiter.api.Test;
34
35
36
37
38 class CharRangeTest extends AbstractLangTest {
39
40 @Test
41 void testClass() {
42
43 assertFalse(Modifier.isPublic(CharRange.class.getModifiers()));
44 assertTrue(Modifier.isFinal(CharRange.class.getModifiers()));
45 }
46
47 @Test
48 void testConstructorAccessors_is() {
49 final CharRange rangea = CharRange.is('a');
50 assertEquals('a', rangea.getStart());
51 assertEquals('a', rangea.getEnd());
52 assertFalse(rangea.isNegated());
53 assertEquals("a", rangea.toString());
54 }
55
56 @Test
57 void testConstructorAccessors_isIn_Normal() {
58 final CharRange rangea = CharRange.isIn('a', 'e');
59 assertEquals('a', rangea.getStart());
60 assertEquals('e', rangea.getEnd());
61 assertFalse(rangea.isNegated());
62 assertEquals("a-e", rangea.toString());
63 }
64
65 @Test
66 void testConstructorAccessors_isIn_Reversed() {
67 final CharRange rangea = CharRange.isIn('e', 'a');
68 assertEquals('a', rangea.getStart());
69 assertEquals('e', rangea.getEnd());
70 assertFalse(rangea.isNegated());
71 assertEquals("a-e", rangea.toString());
72 }
73
74 @Test
75 void testConstructorAccessors_isIn_Same() {
76 final CharRange rangea = CharRange.isIn('a', 'a');
77 assertEquals('a', rangea.getStart());
78 assertEquals('a', rangea.getEnd());
79 assertFalse(rangea.isNegated());
80 assertEquals("a", rangea.toString());
81 }
82
83 @Test
84 void testConstructorAccessors_isNot() {
85 final CharRange rangea = CharRange.isNot('a');
86 assertEquals('a', rangea.getStart());
87 assertEquals('a', rangea.getEnd());
88 assertTrue(rangea.isNegated());
89 assertEquals("^a", rangea.toString());
90 }
91
92 @Test
93 void testConstructorAccessors_isNotIn_Normal() {
94 final CharRange rangea = CharRange.isNotIn('a', 'e');
95 assertEquals('a', rangea.getStart());
96 assertEquals('e', rangea.getEnd());
97 assertTrue(rangea.isNegated());
98 assertEquals("^a-e", rangea.toString());
99 }
100
101 @Test
102 void testConstructorAccessors_isNotIn_Reversed() {
103 final CharRange rangea = CharRange.isNotIn('e', 'a');
104 assertEquals('a', rangea.getStart());
105 assertEquals('e', rangea.getEnd());
106 assertTrue(rangea.isNegated());
107 assertEquals("^a-e", rangea.toString());
108 }
109
110 @Test
111 void testConstructorAccessors_isNotIn_Same() {
112 final CharRange rangea = CharRange.isNotIn('a', 'a');
113 assertEquals('a', rangea.getStart());
114 assertEquals('a', rangea.getEnd());
115 assertTrue(rangea.isNegated());
116 assertEquals("^a", rangea.toString());
117 }
118
119 @Test
120 void testContains_Char() {
121 CharRange range = CharRange.is('c');
122 assertFalse(range.contains('b'));
123 assertTrue(range.contains('c'));
124 assertFalse(range.contains('d'));
125 assertFalse(range.contains('e'));
126
127 range = CharRange.isIn('c', 'd');
128 assertFalse(range.contains('b'));
129 assertTrue(range.contains('c'));
130 assertTrue(range.contains('d'));
131 assertFalse(range.contains('e'));
132
133 range = CharRange.isIn('d', 'c');
134 assertFalse(range.contains('b'));
135 assertTrue(range.contains('c'));
136 assertTrue(range.contains('d'));
137 assertFalse(range.contains('e'));
138
139 range = CharRange.isNotIn('c', 'd');
140 assertTrue(range.contains('b'));
141 assertFalse(range.contains('c'));
142 assertFalse(range.contains('d'));
143 assertTrue(range.contains('e'));
144 assertTrue(range.contains((char) 0));
145 assertTrue(range.contains(Character.MAX_VALUE));
146 }
147
148 @Test
149 void testContains_Charrange() {
150 final CharRange a = CharRange.is('a');
151 final CharRange b = CharRange.is('b');
152 final CharRange c = CharRange.is('c');
153 final CharRange c2 = CharRange.is('c');
154 final CharRange d = CharRange.is('d');
155 final CharRange e = CharRange.is('e');
156 final CharRange cd = CharRange.isIn('c', 'd');
157 final CharRange bd = CharRange.isIn('b', 'd');
158 final CharRange bc = CharRange.isIn('b', 'c');
159 final CharRange ab = CharRange.isIn('a', 'b');
160 final CharRange de = CharRange.isIn('d', 'e');
161 final CharRange ef = CharRange.isIn('e', 'f');
162 final CharRange ae = CharRange.isIn('a', 'e');
163
164
165 assertFalse(c.contains(b));
166 assertTrue(c.contains(c));
167 assertTrue(c.contains(c2));
168 assertFalse(c.contains(d));
169
170 assertFalse(c.contains(cd));
171 assertFalse(c.contains(bd));
172 assertFalse(c.contains(bc));
173 assertFalse(c.contains(ab));
174 assertFalse(c.contains(de));
175
176 assertTrue(cd.contains(c));
177 assertTrue(bd.contains(c));
178 assertTrue(bc.contains(c));
179 assertFalse(ab.contains(c));
180 assertFalse(de.contains(c));
181
182 assertTrue(ae.contains(b));
183 assertTrue(ae.contains(ab));
184 assertTrue(ae.contains(bc));
185 assertTrue(ae.contains(cd));
186 assertTrue(ae.contains(de));
187
188 final CharRange notb = CharRange.isNot('b');
189 final CharRange notc = CharRange.isNot('c');
190 final CharRange notd = CharRange.isNot('d');
191 final CharRange notab = CharRange.isNotIn('a', 'b');
192 final CharRange notbc = CharRange.isNotIn('b', 'c');
193 final CharRange notbd = CharRange.isNotIn('b', 'd');
194 final CharRange notcd = CharRange.isNotIn('c', 'd');
195 final CharRange notde = CharRange.isNotIn('d', 'e');
196 final CharRange notae = CharRange.isNotIn('a', 'e');
197 final CharRange all = CharRange.isIn((char) 0, Character.MAX_VALUE);
198 final CharRange allbutfirst = CharRange.isIn((char) 1, Character.MAX_VALUE);
199
200
201 assertFalse(c.contains(notc));
202 assertFalse(c.contains(notbd));
203 assertTrue(all.contains(notc));
204 assertTrue(all.contains(notbd));
205 assertFalse(allbutfirst.contains(notc));
206 assertFalse(allbutfirst.contains(notbd));
207
208
209 assertTrue(notc.contains(a));
210 assertTrue(notc.contains(b));
211 assertFalse(notc.contains(c));
212 assertTrue(notc.contains(d));
213 assertTrue(notc.contains(e));
214
215 assertTrue(notc.contains(ab));
216 assertFalse(notc.contains(bc));
217 assertFalse(notc.contains(bd));
218 assertFalse(notc.contains(cd));
219 assertTrue(notc.contains(de));
220 assertFalse(notc.contains(ae));
221 assertFalse(notc.contains(all));
222 assertFalse(notc.contains(allbutfirst));
223
224 assertTrue(notbd.contains(a));
225 assertFalse(notbd.contains(b));
226 assertFalse(notbd.contains(c));
227 assertFalse(notbd.contains(d));
228 assertTrue(notbd.contains(e));
229
230 assertTrue(notcd.contains(ab));
231 assertFalse(notcd.contains(bc));
232 assertFalse(notcd.contains(bd));
233 assertFalse(notcd.contains(cd));
234 assertFalse(notcd.contains(de));
235 assertFalse(notcd.contains(ae));
236 assertTrue(notcd.contains(ef));
237 assertFalse(notcd.contains(all));
238 assertFalse(notcd.contains(allbutfirst));
239
240
241 assertFalse(notc.contains(notb));
242 assertTrue(notc.contains(notc));
243 assertFalse(notc.contains(notd));
244
245 assertFalse(notc.contains(notab));
246 assertTrue(notc.contains(notbc));
247 assertTrue(notc.contains(notbd));
248 assertTrue(notc.contains(notcd));
249 assertFalse(notc.contains(notde));
250
251 assertFalse(notbd.contains(notb));
252 assertFalse(notbd.contains(notc));
253 assertFalse(notbd.contains(notd));
254
255 assertFalse(notbd.contains(notab));
256 assertFalse(notbd.contains(notbc));
257 assertTrue(notbd.contains(notbd));
258 assertFalse(notbd.contains(notcd));
259 assertFalse(notbd.contains(notde));
260 assertTrue(notbd.contains(notae));
261 }
262
263 @Test
264 void testContains_Charrange_negatedArgumentTouchingBounds() {
265
266
267 final CharRange emptySet = CharRange.isNotIn((char) 0, Character.MAX_VALUE);
268 assertTrue(CharRange.is('x').contains(emptySet));
269 assertTrue(CharRange.isIn((char) 0, Character.MAX_VALUE).contains(emptySet));
270
271
272 final CharRange fromA = CharRange.isNotIn((char) 0, (char) ('a' - 1));
273 assertTrue(CharRange.isIn('a', Character.MAX_VALUE).contains(fromA));
274 assertTrue(CharRange.isIn('Z', Character.MAX_VALUE).contains(fromA));
275 assertFalse(CharRange.isIn('b', Character.MAX_VALUE).contains(fromA));
276 assertFalse(CharRange.isIn('a', 'z').contains(fromA));
277
278
279 final CharRange upToA = CharRange.isNotIn('b', Character.MAX_VALUE);
280 assertTrue(CharRange.isIn((char) 0, 'a').contains(upToA));
281 assertTrue(CharRange.isIn((char) 0, 'b').contains(upToA));
282 assertFalse(CharRange.isIn((char) 1, 'a').contains(upToA));
283 assertFalse(CharRange.isIn((char) 0, 'Z').contains(upToA));
284
285
286 assertFalse(CharRange.is('c').contains(CharRange.isNot('c')));
287 assertTrue(CharRange.isIn((char) 0, Character.MAX_VALUE).contains(CharRange.isNot('c')));
288 }
289
290 @Test
291 void testContainsNullArg() {
292 final CharRange range = CharRange.is('a');
293 final NullPointerException e = assertNullPointerException(() -> range.contains(null));
294 assertEquals("range", e.getMessage());
295 }
296
297 @Test
298 void testEmptySet() {
299
300 final CharRange emptySet = CharRange.isNotIn(Character.MIN_VALUE, Character.MAX_VALUE);
301 assertTrue(emptySet.isNegated());
302 assertEquals(Character.MIN_VALUE, emptySet.getStart());
303 assertEquals(Character.MAX_VALUE, emptySet.getEnd());
304
305 assertEquals(emptySet, CharRange.isNotIn(Character.MAX_VALUE, Character.MIN_VALUE));
306 assertEquals(emptySet.hashCode(), CharRange.isNotIn(Character.MAX_VALUE, Character.MIN_VALUE).hashCode());
307
308
309 assertFalse(emptySet.contains(Character.MIN_VALUE));
310 assertFalse(emptySet.contains('a'));
311 assertFalse(emptySet.contains('x'));
312 assertFalse(emptySet.contains('z'));
313 assertFalse(emptySet.contains(Character.MAX_VALUE));
314
315
316 assertTrue(CharRange.is('a').contains(emptySet));
317 assertTrue(CharRange.is('x').contains(emptySet));
318 assertTrue(CharRange.isIn('a', 'z').contains(emptySet));
319 assertTrue(CharRange.isIn(Character.MIN_VALUE, Character.MAX_VALUE).contains(emptySet));
320 assertTrue(CharRange.isNot('a').contains(emptySet));
321 assertTrue(CharRange.isNotIn('a', 'z').contains(emptySet));
322 assertTrue(CharRange.isNotIn(Character.MIN_VALUE, 'z').contains(emptySet));
323 assertTrue(CharRange.isNotIn('a', Character.MAX_VALUE).contains(emptySet));
324
325
326 final Iterator<Character> emptySetIt = emptySet.iterator();
327 assertNotNull(emptySetIt);
328 assertFalse(emptySetIt.hasNext());
329 assertThrows(NoSuchElementException.class, emptySetIt::next);
330
331
332 final CharRange fromB = CharRange.isNotIn(Character.MIN_VALUE, 'a');
333 final CharRange upToA = CharRange.isNotIn('a', Character.MAX_VALUE);
334 assertTrue(fromB.contains(Character.MAX_VALUE));
335 assertTrue(upToA.contains(Character.MIN_VALUE));
336
337 assertFalse(CharRange.is('a').contains(fromB));
338 assertFalse(CharRange.is('b').contains(upToA));
339 assertFalse(upToA.contains(fromB));
340 }
341
342 @Test
343 void testEquals_Object() {
344 final CharRange rangea = CharRange.is('a');
345 final CharRange rangeae = CharRange.isIn('a', 'e');
346 final CharRange rangenotbf = CharRange.isIn('b', 'f');
347
348 assertNotEquals(null, rangea);
349
350 assertEquals(rangea, rangea);
351 assertEquals(rangea, CharRange.is('a'));
352 assertEquals(rangeae, rangeae);
353 assertEquals(rangeae, CharRange.isIn('a', 'e'));
354 assertEquals(rangenotbf, rangenotbf);
355 assertEquals(rangenotbf, CharRange.isIn('b', 'f'));
356
357 assertNotEquals(rangea, rangeae);
358 assertNotEquals(rangea, rangenotbf);
359 assertNotEquals(rangeae, rangea);
360 assertNotEquals(rangeae, rangenotbf);
361 assertNotEquals(rangenotbf, rangea);
362 assertNotEquals(rangenotbf, rangeae);
363 }
364
365 @Test
366 void testHashCode() {
367 final CharRange rangea = CharRange.is('a');
368 final CharRange rangeae = CharRange.isIn('a', 'e');
369 final CharRange rangenotbf = CharRange.isIn('b', 'f');
370
371 assertEquals(rangea.hashCode(), rangea.hashCode());
372 assertEquals(rangea.hashCode(), CharRange.is('a').hashCode());
373 assertEquals(rangeae.hashCode(), rangeae.hashCode());
374 assertEquals(rangeae.hashCode(), CharRange.isIn('a', 'e').hashCode());
375 assertEquals(rangenotbf.hashCode(), rangenotbf.hashCode());
376 assertEquals(rangenotbf.hashCode(), CharRange.isIn('b', 'f').hashCode());
377
378 assertNotEquals(rangea.hashCode(), rangeae.hashCode());
379 assertNotEquals(rangea.hashCode(), rangenotbf.hashCode());
380 assertNotEquals(rangeae.hashCode(), rangea.hashCode());
381 assertNotEquals(rangeae.hashCode(), rangenotbf.hashCode());
382 assertNotEquals(rangenotbf.hashCode(), rangea.hashCode());
383 assertNotEquals(rangenotbf.hashCode(), rangeae.hashCode());
384 }
385
386
387
388
389 @Test
390 void testHashCodeLang1802() {
391
392 final CharRange range1 = CharRange.is('a');
393 final CharRange range2 = CharRange.is('b');
394 final CharRange range3 = CharRange.isIn('a', 'z');
395 final CharRange range4 = CharRange.isIn('b', 'z');
396 final CharRange range5 = CharRange.isNot('a');
397 final CharRange range6 = CharRange.isNotIn('a', 'z');
398 final CharRange range7 = CharRange.isNotIn('b', 'z');
399 final CharRange range8 = CharRange.isIn((char) 1, (char) 2);
400 final CharRange range9 = CharRange.isNotIn((char) 1, (char) 2);
401
402 final CharRange a1 = CharRange.isNotIn((char) 1, (char) 2);
403 final CharRange a2 = CharRange.isIn((char) 2, (char) 2);
404 assertNotEquals(a1, a2, "Different ranges should not be equal");
405 assertNotEquals(a1.hashCode(), a2.hashCode(), "Different ranges should have different hash codes");
406 final CharRange b1 = CharRange.isIn((char) 5, (char) 5);
407 final CharRange b2 = CharRange.isNotIn((char) 4, (char) 5);
408 assertNotEquals(b1, b2, "Different ranges should not be equal");
409 assertNotEquals(b1.hashCode(), b2.hashCode(), "Different ranges should have different hash codes");
410
411 final CharRange normal = CharRange.isIn('x', 'y');
412 final CharRange negated = CharRange.isNotIn('x', 'y');
413 assertNotEquals(normal, negated, "Negated and normal ranges should not be equal");
414 assertNotEquals(normal.hashCode(), negated.hashCode(), "Negated and normal ranges should have different hash codes");
415
416 assertNotEquals(range1.hashCode(), range2.hashCode(), "is('a') vs is('b')");
417 assertNotEquals(range1.hashCode(), range3.hashCode(), "is('a') vs isIn('a', 'z')");
418 assertNotEquals(range3.hashCode(), range4.hashCode(), "isIn('a', 'z') vs isIn('b', 'z')");
419 assertNotEquals(range1.hashCode(), range5.hashCode(), "is('a') vs isNot('a')");
420 assertNotEquals(range3.hashCode(), range6.hashCode(), "isIn('a', 'z') vs isNotIn('a', 'z')");
421 assertNotEquals(range6.hashCode(), range7.hashCode(), "isNotIn('a', 'z') vs isNotIn('b', 'z')");
422 assertNotEquals(range8.hashCode(), range9.hashCode(), "isIn(1, 2) vs isNotIn(1, 2)");
423
424 final CharRange sameAsRange1 = CharRange.is('a');
425 assertEquals(range1, sameAsRange1, "Equal ranges should be equal");
426 assertEquals(range1.hashCode(), sameAsRange1.hashCode(), "Equal ranges should have equal hash codes");
427 }
428
429 @Test
430 void testIsEmpty() {
431
432 assertTrue(CharRange.isNotIn(Character.MIN_VALUE, Character.MAX_VALUE).isEmpty());
433
434 assertTrue(CharRange.isNotIn(Character.MAX_VALUE, Character.MIN_VALUE).isEmpty());
435
436
437 assertFalse(CharRange.isNotIn(Character.MIN_VALUE, 'a').isEmpty());
438 assertFalse(CharRange.isNotIn('a', Character.MAX_VALUE).isEmpty());
439 assertFalse(CharRange.isNot('a').isEmpty());
440 assertFalse(CharRange.isNotIn('a', 'z').isEmpty());
441
442
443 assertFalse(CharRange.is('a').isEmpty());
444 assertFalse(CharRange.isIn('a', 'z').isEmpty());
445 assertFalse(CharRange.isIn(Character.MIN_VALUE, Character.MAX_VALUE).isEmpty());
446 }
447
448 @Test
449 void testIterator() {
450 final CharRange a = CharRange.is('a');
451 final CharRange ad = CharRange.isIn('a', 'd');
452 final CharRange nota = CharRange.isNot('a');
453 final CharRange emptySet = CharRange.isNotIn((char) 0, Character.MAX_VALUE);
454 final CharRange notFirst = CharRange.isNotIn((char) 1, Character.MAX_VALUE);
455 final CharRange notLast = CharRange.isNotIn((char) 0, (char) (Character.MAX_VALUE - 1));
456
457 final Iterator<Character> aIt = a.iterator();
458 assertNotNull(aIt);
459 assertTrue(aIt.hasNext());
460 assertEquals(Character.valueOf('a'), aIt.next());
461 assertFalse(aIt.hasNext());
462
463 final Iterator<Character> adIt = ad.iterator();
464 assertNotNull(adIt);
465 assertTrue(adIt.hasNext());
466 assertEquals(Character.valueOf('a'), adIt.next());
467 assertEquals(Character.valueOf('b'), adIt.next());
468 assertEquals(Character.valueOf('c'), adIt.next());
469 assertEquals(Character.valueOf('d'), adIt.next());
470 assertFalse(adIt.hasNext());
471
472 final Iterator<Character> notaIt = nota.iterator();
473 assertNotNull(notaIt);
474 assertTrue(notaIt.hasNext());
475 while (notaIt.hasNext()) {
476 final Character c = notaIt.next();
477 assertNotEquals('a', c.charValue());
478 }
479
480 final Iterator<Character> emptySetIt = emptySet.iterator();
481 assertNotNull(emptySetIt);
482 assertFalse(emptySetIt.hasNext());
483 assertThrows(NoSuchElementException.class, emptySetIt::next);
484
485 final Iterator<Character> notFirstIt = notFirst.iterator();
486 assertNotNull(notFirstIt);
487 assertTrue(notFirstIt.hasNext());
488 assertEquals(Character.valueOf((char) 0), notFirstIt.next());
489 assertFalse(notFirstIt.hasNext());
490 assertThrows(NoSuchElementException.class, notFirstIt::next);
491
492 final Iterator<Character> notLastIt = notLast.iterator();
493 assertNotNull(notLastIt);
494 assertTrue(notLastIt.hasNext());
495 assertEquals(Character.valueOf(Character.MAX_VALUE), notLastIt.next());
496 assertFalse(notLastIt.hasNext());
497 assertThrows(NoSuchElementException.class, notLastIt::next);
498 }
499
500 @Test
501 void testIteratorRemove() {
502 final CharRange a = CharRange.is('a');
503 final Iterator<Character> aIt = a.iterator();
504 assertThrows(UnsupportedOperationException.class, aIt::remove);
505 }
506
507 @Test
508 void testSerialization() {
509 CharRange range = CharRange.is('a');
510 assertEquals(range, SerializationUtils.clone(range));
511 range = CharRange.isIn('a', 'e');
512 assertEquals(range, SerializationUtils.clone(range));
513 range = CharRange.isNotIn('a', 'e');
514 assertEquals(range, SerializationUtils.clone(range));
515 }
516 }