• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.primitives;
18 
19 import static com.google.common.truth.Truth.assertThat;
20 import static com.google.common.truth.Truth.assertWithMessage;
21 
22 import com.google.common.annotations.GwtCompatible;
23 import com.google.common.annotations.GwtIncompatible;
24 import com.google.common.annotations.J2ktIncompatible;
25 import com.google.common.collect.testing.Helpers;
26 import com.google.common.testing.NullPointerTester;
27 import com.google.common.testing.SerializableTester;
28 import java.util.Arrays;
29 import java.util.Collection;
30 import java.util.Collections;
31 import java.util.Comparator;
32 import java.util.List;
33 import java.util.Locale;
34 import junit.framework.TestCase;
35 import org.checkerframework.checker.nullness.qual.Nullable;
36 
37 /**
38  * Unit test for {@link Chars}.
39  *
40  * @author Kevin Bourrillion
41  */
42 @GwtCompatible(emulated = true)
43 @ElementTypesAreNonnullByDefault
44 @SuppressWarnings("cast") // redundant casts are intentional and harmless
45 public class CharsTest extends TestCase {
46   private static final char[] EMPTY = {};
47   private static final char[] ARRAY1 = {(char) 1};
48   private static final char[] ARRAY234 = {(char) 2, (char) 3, (char) 4};
49 
50   private static final char LEAST = Character.MIN_VALUE;
51   private static final char GREATEST = Character.MAX_VALUE;
52 
53   private static final char[] VALUES = {LEAST, 'a', '\u00e0', '\udcaa', GREATEST};
54 
testHashCode()55   public void testHashCode() {
56     for (char value : VALUES) {
57       assertThat(Chars.hashCode(value)).isEqualTo(((Character) value).hashCode());
58     }
59   }
60 
testCheckedCast()61   public void testCheckedCast() {
62     for (char value : VALUES) {
63       assertThat(Chars.checkedCast((long) value)).isEqualTo(value);
64     }
65     assertCastFails(GREATEST + 1L);
66     assertCastFails(LEAST - 1L);
67     assertCastFails(Long.MAX_VALUE);
68     assertCastFails(Long.MIN_VALUE);
69   }
70 
testSaturatedCast()71   public void testSaturatedCast() {
72     for (char value : VALUES) {
73       assertThat(Chars.saturatedCast((long) value)).isEqualTo(value);
74     }
75     assertThat(Chars.saturatedCast(GREATEST + 1L)).isEqualTo(GREATEST);
76     assertThat(Chars.saturatedCast(LEAST - 1L)).isEqualTo(LEAST);
77     assertThat(Chars.saturatedCast(Long.MAX_VALUE)).isEqualTo(GREATEST);
78     assertThat(Chars.saturatedCast(Long.MIN_VALUE)).isEqualTo(LEAST);
79   }
80 
assertCastFails(long value)81   private void assertCastFails(long value) {
82     try {
83       Chars.checkedCast(value);
84       fail("Cast to char should have failed: " + value);
85     } catch (IllegalArgumentException ex) {
86       assertWithMessage(value + " not found in exception text: " + ex.getMessage())
87           .that(ex.getMessage().contains(String.valueOf(value)))
88           .isTrue();
89     }
90   }
91 
92   @J2ktIncompatible // TODO(b/285538920): Fix and enable.
testCompare()93   public void testCompare() {
94     for (char x : VALUES) {
95       for (char y : VALUES) {
96         // note: spec requires only that the sign is the same
97         assertWithMessage(x + ", " + y)
98             .that(Chars.compare(x, y))
99             .isEqualTo(Character.valueOf(x).compareTo(y));
100       }
101     }
102   }
103 
testContains()104   public void testContains() {
105     assertThat(Chars.contains(EMPTY, (char) 1)).isFalse();
106     assertThat(Chars.contains(ARRAY1, (char) 2)).isFalse();
107     assertThat(Chars.contains(ARRAY234, (char) 1)).isFalse();
108     assertThat(Chars.contains(new char[] {(char) -1}, (char) -1)).isTrue();
109     assertThat(Chars.contains(ARRAY234, (char) 2)).isTrue();
110     assertThat(Chars.contains(ARRAY234, (char) 3)).isTrue();
111     assertThat(Chars.contains(ARRAY234, (char) 4)).isTrue();
112   }
113 
testIndexOf()114   public void testIndexOf() {
115     assertThat(Chars.indexOf(EMPTY, (char) 1)).isEqualTo(-1);
116     assertThat(Chars.indexOf(ARRAY1, (char) 2)).isEqualTo(-1);
117     assertThat(Chars.indexOf(ARRAY234, (char) 1)).isEqualTo(-1);
118     assertThat(Chars.indexOf(new char[] {(char) -1}, (char) -1)).isEqualTo(0);
119     assertThat(Chars.indexOf(ARRAY234, (char) 2)).isEqualTo(0);
120     assertThat(Chars.indexOf(ARRAY234, (char) 3)).isEqualTo(1);
121     assertThat(Chars.indexOf(ARRAY234, (char) 4)).isEqualTo(2);
122     assertThat(Chars.indexOf(new char[] {(char) 2, (char) 3, (char) 2, (char) 3}, (char) 3))
123         .isEqualTo(1);
124   }
125 
testIndexOf_arrayTarget()126   public void testIndexOf_arrayTarget() {
127     assertThat(Chars.indexOf(EMPTY, EMPTY)).isEqualTo(0);
128     assertThat(Chars.indexOf(ARRAY234, EMPTY)).isEqualTo(0);
129     assertThat(Chars.indexOf(EMPTY, ARRAY234)).isEqualTo(-1);
130     assertThat(Chars.indexOf(ARRAY234, ARRAY1)).isEqualTo(-1);
131     assertThat(Chars.indexOf(ARRAY1, ARRAY234)).isEqualTo(-1);
132     assertThat(Chars.indexOf(ARRAY1, ARRAY1)).isEqualTo(0);
133     assertThat(Chars.indexOf(ARRAY234, ARRAY234)).isEqualTo(0);
134     assertThat(Chars.indexOf(ARRAY234, new char[] {(char) 2, (char) 3})).isEqualTo(0);
135     assertThat(Chars.indexOf(ARRAY234, new char[] {(char) 3, (char) 4})).isEqualTo(1);
136     assertThat(Chars.indexOf(ARRAY234, new char[] {(char) 3})).isEqualTo(1);
137     assertThat(Chars.indexOf(ARRAY234, new char[] {(char) 4})).isEqualTo(2);
138     assertThat(
139             Chars.indexOf(
140                 new char[] {(char) 2, (char) 3, (char) 3, (char) 3, (char) 3},
141                 new char[] {(char) 3}))
142         .isEqualTo(1);
143     assertThat(
144             Chars.indexOf(
145                 new char[] {(char) 2, (char) 3, (char) 2, (char) 3, (char) 4, (char) 2, (char) 3},
146                 new char[] {(char) 2, (char) 3, (char) 4}))
147         .isEqualTo(2);
148     assertThat(
149             Chars.indexOf(
150                 new char[] {(char) 2, (char) 2, (char) 3, (char) 4, (char) 2, (char) 3, (char) 4},
151                 new char[] {(char) 2, (char) 3, (char) 4}))
152         .isEqualTo(1);
153     assertThat(
154             Chars.indexOf(
155                 new char[] {(char) 4, (char) 3, (char) 2},
156                 new char[] {(char) 2, (char) 3, (char) 4}))
157         .isEqualTo(-1);
158   }
159 
testLastIndexOf()160   public void testLastIndexOf() {
161     assertThat(Chars.lastIndexOf(EMPTY, (char) 1)).isEqualTo(-1);
162     assertThat(Chars.lastIndexOf(ARRAY1, (char) 2)).isEqualTo(-1);
163     assertThat(Chars.lastIndexOf(ARRAY234, (char) 1)).isEqualTo(-1);
164     assertThat(Chars.lastIndexOf(new char[] {(char) -1}, (char) -1)).isEqualTo(0);
165     assertThat(Chars.lastIndexOf(ARRAY234, (char) 2)).isEqualTo(0);
166     assertThat(Chars.lastIndexOf(ARRAY234, (char) 3)).isEqualTo(1);
167     assertThat(Chars.lastIndexOf(ARRAY234, (char) 4)).isEqualTo(2);
168     assertThat(Chars.lastIndexOf(new char[] {(char) 2, (char) 3, (char) 2, (char) 3}, (char) 3))
169         .isEqualTo(3);
170   }
171 
testMax_noArgs()172   public void testMax_noArgs() {
173     try {
174       Chars.max();
175       fail();
176     } catch (IllegalArgumentException expected) {
177     }
178   }
179 
testMax()180   public void testMax() {
181     assertThat(Chars.max(LEAST)).isEqualTo(LEAST);
182     assertThat(Chars.max(GREATEST)).isEqualTo(GREATEST);
183     assertThat(Chars.max((char) 8, (char) 6, (char) 7, (char) 5, (char) 3, (char) 0, (char) 9))
184         .isEqualTo((char) 9);
185   }
186 
testMin_noArgs()187   public void testMin_noArgs() {
188     try {
189       Chars.min();
190       fail();
191     } catch (IllegalArgumentException expected) {
192     }
193   }
194 
testMin()195   public void testMin() {
196     assertThat(Chars.min(LEAST)).isEqualTo(LEAST);
197     assertThat(Chars.min(GREATEST)).isEqualTo(GREATEST);
198     assertThat(Chars.min((char) 8, (char) 6, (char) 7, (char) 5, (char) 3, (char) 0, (char) 9))
199         .isEqualTo((char) 0);
200   }
201 
testConstrainToRange()202   public void testConstrainToRange() {
203     assertThat(Chars.constrainToRange((char) 1, (char) 0, (char) 5)).isEqualTo((char) 1);
204     assertThat(Chars.constrainToRange((char) 1, (char) 1, (char) 5)).isEqualTo((char) 1);
205     assertThat(Chars.constrainToRange((char) 1, (char) 3, (char) 5)).isEqualTo((char) 3);
206     assertThat(Chars.constrainToRange((char) 255, (char) 250, (char) 254)).isEqualTo((char) 254);
207     assertThat(Chars.constrainToRange((char) 5, (char) 2, (char) 2)).isEqualTo((char) 2);
208     try {
209       Chars.constrainToRange((char) 1, (char) 3, (char) 2);
210       fail();
211     } catch (IllegalArgumentException expected) {
212     }
213   }
214 
testConcat()215   public void testConcat() {
216     assertThat(Chars.concat()).isEqualTo(EMPTY);
217     assertThat(Chars.concat(EMPTY)).isEqualTo(EMPTY);
218     assertThat(Chars.concat(EMPTY, EMPTY, EMPTY)).isEqualTo(EMPTY);
219     assertThat(Chars.concat(ARRAY1)).isEqualTo(ARRAY1);
220     assertThat(Chars.concat(ARRAY1)).isNotSameInstanceAs(ARRAY1);
221     assertThat(Chars.concat(EMPTY, ARRAY1, EMPTY)).isEqualTo(ARRAY1);
222     assertThat(Chars.concat(ARRAY1, ARRAY1, ARRAY1))
223         .isEqualTo(new char[] {(char) 1, (char) 1, (char) 1});
224     assertThat(Chars.concat(ARRAY1, ARRAY234))
225         .isEqualTo(new char[] {(char) 1, (char) 2, (char) 3, (char) 4});
226   }
227 
228   @J2ktIncompatible
229   @GwtIncompatible // Chars.fromByteArray
testFromByteArray()230   public void testFromByteArray() {
231     assertThat(Chars.fromByteArray(new byte[] {0x23, 0x45, (byte) 0xDC})).isEqualTo('\u2345');
232     assertThat(Chars.fromByteArray(new byte[] {(byte) 0xFE, (byte) 0xDC})).isEqualTo('\uFEDC');
233   }
234 
235   @J2ktIncompatible
236   @GwtIncompatible // Chars.fromByteArray
testFromByteArrayFails()237   public void testFromByteArrayFails() {
238     try {
239       Chars.fromByteArray(new byte[Chars.BYTES - 1]);
240       fail();
241     } catch (IllegalArgumentException expected) {
242     }
243   }
244 
245   @J2ktIncompatible
246   @GwtIncompatible // Chars.fromBytes
testFromBytes()247   public void testFromBytes() {
248     assertThat(Chars.fromBytes((byte) 0x23, (byte) 0x45)).isEqualTo('\u2345');
249     assertThat(Chars.fromBytes((byte) 0xFE, (byte) 0xDC)).isEqualTo('\uFEDC');
250   }
251 
252   @J2ktIncompatible
253   @GwtIncompatible // Chars.fromByteArray, Chars.toByteArray
testByteArrayRoundTrips()254   public void testByteArrayRoundTrips() {
255     char c = 0;
256     for (int hi = 0; hi < 256; hi++) {
257       for (int lo = 0; lo < 256; lo++) {
258         char result = Chars.fromByteArray(new byte[] {(byte) hi, (byte) lo});
259         assertWithMessage(
260                 String.format(
261                     Locale.ROOT,
262                     "hi=%s, lo=%s, expected=%s, result=%s",
263                     hi,
264                     lo,
265                     (int) c,
266                     (int) result))
267             .that(result)
268             .isEqualTo(c);
269 
270         byte[] bytes = Chars.toByteArray(c);
271         assertThat(bytes[0]).isEqualTo((byte) hi);
272         assertThat(bytes[1]).isEqualTo((byte) lo);
273 
274         c++;
275       }
276     }
277     assertThat(c).isEqualTo((char) 0); // sanity check
278   }
279 
280   @J2ktIncompatible
281   @GwtIncompatible // Chars.fromByteArray, Chars.toByteArray
testByteArrayRoundTripsFails()282   public void testByteArrayRoundTripsFails() {
283     try {
284       Chars.fromByteArray(new byte[] {0x11});
285       fail();
286     } catch (IllegalArgumentException expected) {
287     }
288   }
289 
testEnsureCapacity()290   public void testEnsureCapacity() {
291     assertThat(Chars.ensureCapacity(EMPTY, 0, 1)).isSameInstanceAs(EMPTY);
292     assertThat(Chars.ensureCapacity(ARRAY1, 0, 1)).isSameInstanceAs(ARRAY1);
293     assertThat(Chars.ensureCapacity(ARRAY1, 1, 1)).isSameInstanceAs(ARRAY1);
294     assertThat(Chars.ensureCapacity(ARRAY1, 2, 1))
295         .isEqualTo(new char[] {(char) 1, (char) 0, (char) 0});
296   }
297 
testEnsureCapacity_fail()298   public void testEnsureCapacity_fail() {
299     try {
300       Chars.ensureCapacity(ARRAY1, -1, 1);
301       fail();
302     } catch (IllegalArgumentException expected) {
303     }
304     try {
305       // notice that this should even fail when no growth was needed
306       Chars.ensureCapacity(ARRAY1, 1, -1);
307       fail();
308     } catch (IllegalArgumentException expected) {
309     }
310   }
311 
testJoin()312   public void testJoin() {
313     assertThat(Chars.join(",", EMPTY)).isEmpty();
314     assertThat(Chars.join(",", '1')).isEqualTo("1");
315     assertThat(Chars.join(",", '1', '2')).isEqualTo("1,2");
316     assertThat(Chars.join("", '1', '2', '3')).isEqualTo("123");
317   }
318 
testLexicographicalComparator()319   public void testLexicographicalComparator() {
320     List<char[]> ordered =
321         Arrays.asList(
322             new char[] {},
323             new char[] {LEAST},
324             new char[] {LEAST, LEAST},
325             new char[] {LEAST, (char) 1},
326             new char[] {(char) 1},
327             new char[] {(char) 1, LEAST},
328             new char[] {GREATEST, GREATEST - (char) 1},
329             new char[] {GREATEST, GREATEST},
330             new char[] {GREATEST, GREATEST, GREATEST});
331 
332     Comparator<char[]> comparator = Chars.lexicographicalComparator();
333     Helpers.testComparator(comparator, ordered);
334   }
335 
336   @J2ktIncompatible
337   @GwtIncompatible // SerializableTester
testLexicographicalComparatorSerializable()338   public void testLexicographicalComparatorSerializable() {
339     Comparator<char[]> comparator = Chars.lexicographicalComparator();
340     assertThat(SerializableTester.reserialize(comparator)).isSameInstanceAs(comparator);
341   }
342 
testReverse()343   public void testReverse() {
344     testReverse(new char[] {}, new char[] {});
345     testReverse(new char[] {'1'}, new char[] {'1'});
346     testReverse(new char[] {'1', '2'}, new char[] {'2', '1'});
347     testReverse(new char[] {'3', '1', '1'}, new char[] {'1', '1', '3'});
348     testReverse(new char[] {'A', '1', 'B', '2'}, new char[] {'2', 'B', '1', 'A'});
349   }
350 
testReverse(char[] input, char[] expectedOutput)351   private static void testReverse(char[] input, char[] expectedOutput) {
352     input = Arrays.copyOf(input, input.length);
353     Chars.reverse(input);
354     assertThat(input).isEqualTo(expectedOutput);
355   }
356 
testReverse(char[] input, int fromIndex, int toIndex, char[] expectedOutput)357   private static void testReverse(char[] input, int fromIndex, int toIndex, char[] expectedOutput) {
358     input = Arrays.copyOf(input, input.length);
359     Chars.reverse(input, fromIndex, toIndex);
360     assertThat(input).isEqualTo(expectedOutput);
361   }
362 
testReverseIndexed()363   public void testReverseIndexed() {
364     testReverse(new char[] {}, 0, 0, new char[] {});
365     testReverse(new char[] {'1'}, 0, 1, new char[] {'1'});
366     testReverse(new char[] {'1', '2'}, 0, 2, new char[] {'2', '1'});
367     testReverse(new char[] {'3', '1', '1'}, 0, 2, new char[] {'1', '3', '1'});
368     testReverse(new char[] {'3', '1', '1'}, 0, 1, new char[] {'3', '1', '1'});
369     testReverse(new char[] {'A', '1', 'B', '2'}, 1, 3, new char[] {'A', 'B', '1', '2'});
370   }
371 
testRotate(char[] input, int distance, char[] expectedOutput)372   private static void testRotate(char[] input, int distance, char[] expectedOutput) {
373     input = Arrays.copyOf(input, input.length);
374     Chars.rotate(input, distance);
375     assertThat(input).isEqualTo(expectedOutput);
376   }
377 
testRotate( char[] input, int distance, int fromIndex, int toIndex, char[] expectedOutput)378   private static void testRotate(
379       char[] input, int distance, int fromIndex, int toIndex, char[] expectedOutput) {
380     input = Arrays.copyOf(input, input.length);
381     Chars.rotate(input, distance, fromIndex, toIndex);
382     assertThat(input).isEqualTo(expectedOutput);
383   }
384 
testRotate()385   public void testRotate() {
386     testRotate(new char[] {}, -1, new char[] {});
387     testRotate(new char[] {}, 0, new char[] {});
388     testRotate(new char[] {}, 1, new char[] {});
389 
390     testRotate(new char[] {'1'}, -2, new char[] {'1'});
391     testRotate(new char[] {'1'}, -1, new char[] {'1'});
392     testRotate(new char[] {'1'}, 0, new char[] {'1'});
393     testRotate(new char[] {'1'}, 1, new char[] {'1'});
394     testRotate(new char[] {'1'}, 2, new char[] {'1'});
395 
396     testRotate(new char[] {'1', '2'}, -3, new char[] {'2', '1'});
397     testRotate(new char[] {'1', '2'}, -1, new char[] {'2', '1'});
398     testRotate(new char[] {'1', '2'}, -2, new char[] {'1', '2'});
399     testRotate(new char[] {'1', '2'}, 0, new char[] {'1', '2'});
400     testRotate(new char[] {'1', '2'}, 1, new char[] {'2', '1'});
401     testRotate(new char[] {'1', '2'}, 2, new char[] {'1', '2'});
402     testRotate(new char[] {'1', '2'}, 3, new char[] {'2', '1'});
403 
404     testRotate(new char[] {'1', '2', '3'}, -5, new char[] {'3', '1', '2'});
405     testRotate(new char[] {'1', '2', '3'}, -4, new char[] {'2', '3', '1'});
406     testRotate(new char[] {'1', '2', '3'}, -3, new char[] {'1', '2', '3'});
407     testRotate(new char[] {'1', '2', '3'}, -2, new char[] {'3', '1', '2'});
408     testRotate(new char[] {'1', '2', '3'}, -1, new char[] {'2', '3', '1'});
409     testRotate(new char[] {'1', '2', '3'}, 0, new char[] {'1', '2', '3'});
410     testRotate(new char[] {'1', '2', '3'}, 1, new char[] {'3', '1', '2'});
411     testRotate(new char[] {'1', '2', '3'}, 2, new char[] {'2', '3', '1'});
412     testRotate(new char[] {'1', '2', '3'}, 3, new char[] {'1', '2', '3'});
413     testRotate(new char[] {'1', '2', '3'}, 4, new char[] {'3', '1', '2'});
414     testRotate(new char[] {'1', '2', '3'}, 5, new char[] {'2', '3', '1'});
415 
416     testRotate(new char[] {'1', '2', '3', '4'}, -9, new char[] {'2', '3', '4', '1'});
417     testRotate(new char[] {'1', '2', '3', '4'}, -5, new char[] {'2', '3', '4', '1'});
418     testRotate(new char[] {'1', '2', '3', '4'}, -1, new char[] {'2', '3', '4', '1'});
419     testRotate(new char[] {'1', '2', '3', '4'}, 0, new char[] {'1', '2', '3', '4'});
420     testRotate(new char[] {'1', '2', '3', '4'}, 1, new char[] {'4', '1', '2', '3'});
421     testRotate(new char[] {'1', '2', '3', '4'}, 5, new char[] {'4', '1', '2', '3'});
422     testRotate(new char[] {'1', '2', '3', '4'}, 9, new char[] {'4', '1', '2', '3'});
423 
424     testRotate(new char[] {'1', '2', '3', '4', '5'}, -6, new char[] {'2', '3', '4', '5', '1'});
425     testRotate(new char[] {'1', '2', '3', '4', '5'}, -4, new char[] {'5', '1', '2', '3', '4'});
426     testRotate(new char[] {'1', '2', '3', '4', '5'}, -3, new char[] {'4', '5', '1', '2', '3'});
427     testRotate(new char[] {'1', '2', '3', '4', '5'}, -1, new char[] {'2', '3', '4', '5', '1'});
428     testRotate(new char[] {'1', '2', '3', '4', '5'}, 0, new char[] {'1', '2', '3', '4', '5'});
429     testRotate(new char[] {'1', '2', '3', '4', '5'}, 1, new char[] {'5', '1', '2', '3', '4'});
430     testRotate(new char[] {'1', '2', '3', '4', '5'}, 3, new char[] {'3', '4', '5', '1', '2'});
431     testRotate(new char[] {'1', '2', '3', '4', '5'}, 4, new char[] {'2', '3', '4', '5', '1'});
432     testRotate(new char[] {'1', '2', '3', '4', '5'}, 6, new char[] {'5', '1', '2', '3', '4'});
433   }
434 
testRotateIndexed()435   public void testRotateIndexed() {
436     testRotate(new char[] {}, 0, 0, 0, new char[] {});
437 
438     testRotate(new char[] {'1'}, 0, 0, 1, new char[] {'1'});
439     testRotate(new char[] {'1'}, 1, 0, 1, new char[] {'1'});
440     testRotate(new char[] {'1'}, 1, 1, 1, new char[] {'1'});
441 
442     // Rotate the central 5 elements, leaving the ends as-is
443     testRotate(
444         new char[] {'0', '1', '2', '3', '4', '5', '6'},
445         -6,
446         1,
447         6,
448         new char[] {'0', '2', '3', '4', '5', '1', '6'});
449     testRotate(
450         new char[] {'0', '1', '2', '3', '4', '5', '6'},
451         -1,
452         1,
453         6,
454         new char[] {'0', '2', '3', '4', '5', '1', '6'});
455     testRotate(
456         new char[] {'0', '1', '2', '3', '4', '5', '6'},
457         0,
458         1,
459         6,
460         new char[] {'0', '1', '2', '3', '4', '5', '6'});
461     testRotate(
462         new char[] {'0', '1', '2', '3', '4', '5', '6'},
463         5,
464         1,
465         6,
466         new char[] {'0', '1', '2', '3', '4', '5', '6'});
467     testRotate(
468         new char[] {'0', '1', '2', '3', '4', '5', '6'},
469         14,
470         1,
471         6,
472         new char[] {'0', '2', '3', '4', '5', '1', '6'});
473 
474     // Rotate the first three elements
475     testRotate(
476         new char[] {'0', '1', '2', '3', '4', '5', '6'},
477         -2,
478         0,
479         3,
480         new char[] {'2', '0', '1', '3', '4', '5', '6'});
481     testRotate(
482         new char[] {'0', '1', '2', '3', '4', '5', '6'},
483         -1,
484         0,
485         3,
486         new char[] {'1', '2', '0', '3', '4', '5', '6'});
487     testRotate(
488         new char[] {'0', '1', '2', '3', '4', '5', '6'},
489         0,
490         0,
491         3,
492         new char[] {'0', '1', '2', '3', '4', '5', '6'});
493     testRotate(
494         new char[] {'0', '1', '2', '3', '4', '5', '6'},
495         1,
496         0,
497         3,
498         new char[] {'2', '0', '1', '3', '4', '5', '6'});
499     testRotate(
500         new char[] {'0', '1', '2', '3', '4', '5', '6'},
501         2,
502         0,
503         3,
504         new char[] {'1', '2', '0', '3', '4', '5', '6'});
505 
506     // Rotate the last four elements
507     testRotate(
508         new char[] {'0', '1', '2', '3', '4', '5', '6'},
509         -6,
510         3,
511         7,
512         new char[] {'0', '1', '2', '5', '6', '3', '4'});
513     testRotate(
514         new char[] {'0', '1', '2', '3', '4', '5', '6'},
515         -5,
516         3,
517         7,
518         new char[] {'0', '1', '2', '4', '5', '6', '3'});
519     testRotate(
520         new char[] {'0', '1', '2', '3', '4', '5', '6'},
521         -4,
522         3,
523         7,
524         new char[] {'0', '1', '2', '3', '4', '5', '6'});
525     testRotate(
526         new char[] {'0', '1', '2', '3', '4', '5', '6'},
527         -3,
528         3,
529         7,
530         new char[] {'0', '1', '2', '6', '3', '4', '5'});
531     testRotate(
532         new char[] {'0', '1', '2', '3', '4', '5', '6'},
533         -2,
534         3,
535         7,
536         new char[] {'0', '1', '2', '5', '6', '3', '4'});
537     testRotate(
538         new char[] {'0', '1', '2', '3', '4', '5', '6'},
539         -1,
540         3,
541         7,
542         new char[] {'0', '1', '2', '4', '5', '6', '3'});
543     testRotate(
544         new char[] {'0', '1', '2', '3', '4', '5', '6'},
545         0,
546         3,
547         7,
548         new char[] {'0', '1', '2', '3', '4', '5', '6'});
549     testRotate(
550         new char[] {'0', '1', '2', '3', '4', '5', '6'},
551         1,
552         3,
553         7,
554         new char[] {'0', '1', '2', '6', '3', '4', '5'});
555     testRotate(
556         new char[] {'0', '1', '2', '3', '4', '5', '6'},
557         2,
558         3,
559         7,
560         new char[] {'0', '1', '2', '5', '6', '3', '4'});
561     testRotate(
562         new char[] {'0', '1', '2', '3', '4', '5', '6'},
563         3,
564         3,
565         7,
566         new char[] {'0', '1', '2', '4', '5', '6', '3'});
567   }
568 
testSortDescending()569   public void testSortDescending() {
570     testSortDescending(new char[] {}, new char[] {});
571     testSortDescending(new char[] {'1'}, new char[] {'1'});
572     testSortDescending(new char[] {'1', '2'}, new char[] {'2', '1'});
573     testSortDescending(new char[] {'1', '3', '1'}, new char[] {'3', '1', '1'});
574     testSortDescending(new char[] {'A', '1', 'B', '2'}, new char[] {'B', 'A', '2', '1'});
575   }
576 
testSortDescending(char[] input, char[] expectedOutput)577   private static void testSortDescending(char[] input, char[] expectedOutput) {
578     input = Arrays.copyOf(input, input.length);
579     Chars.sortDescending(input);
580     assertThat(input).isEqualTo(expectedOutput);
581   }
582 
testSortDescending( char[] input, int fromIndex, int toIndex, char[] expectedOutput)583   private static void testSortDescending(
584       char[] input, int fromIndex, int toIndex, char[] expectedOutput) {
585     input = Arrays.copyOf(input, input.length);
586     Chars.sortDescending(input, fromIndex, toIndex);
587     assertThat(input).isEqualTo(expectedOutput);
588   }
589 
testSortDescendingIndexed()590   public void testSortDescendingIndexed() {
591     testSortDescending(new char[] {}, 0, 0, new char[] {});
592     testSortDescending(new char[] {'1'}, 0, 1, new char[] {'1'});
593     testSortDescending(new char[] {'1', '2'}, 0, 2, new char[] {'2', '1'});
594     testSortDescending(new char[] {'1', '3', '1'}, 0, 2, new char[] {'3', '1', '1'});
595     testSortDescending(new char[] {'1', '3', '1'}, 0, 1, new char[] {'1', '3', '1'});
596     testSortDescending(new char[] {'A', '1', 'B', '2'}, 1, 3, new char[] {'A', 'B', '1', '2'});
597   }
598 
testToArray()599   public void testToArray() {
600     // need explicit type parameter to avoid javac warning!?
601     List<Character> none = Arrays.<Character>asList();
602     assertThat(Chars.toArray(none)).isEqualTo(EMPTY);
603 
604     List<Character> one = Arrays.asList((char) 1);
605     assertThat(Chars.toArray(one)).isEqualTo(ARRAY1);
606 
607     char[] array = {(char) 0, (char) 1, 'A'};
608 
609     List<Character> three = Arrays.asList((char) 0, (char) 1, 'A');
610     assertThat(Chars.toArray(three)).isEqualTo(array);
611 
612     assertThat(Chars.toArray(Chars.asList(array))).isEqualTo(array);
613   }
614 
testToArray_threadSafe()615   public void testToArray_threadSafe() {
616     for (int delta : new int[] {+1, 0, -1}) {
617       for (int i = 0; i < VALUES.length; i++) {
618         List<Character> list = Chars.asList(VALUES).subList(0, i);
619         Collection<Character> misleadingSize = Helpers.misleadingSizeCollection(delta);
620         misleadingSize.addAll(list);
621         char[] arr = Chars.toArray(misleadingSize);
622         assertThat(arr).hasLength(i);
623         for (int j = 0; j < i; j++) {
624           assertThat(arr[j]).isEqualTo(VALUES[j]);
625         }
626       }
627     }
628   }
629 
testToArray_withNull()630   public void testToArray_withNull() {
631     List<@Nullable Character> list = Arrays.asList((char) 0, (char) 1, null);
632     try {
633       Chars.toArray(list);
634       fail();
635     } catch (NullPointerException expected) {
636     }
637   }
638 
639   @J2ktIncompatible // b/285319375
testAsList_isAView()640   public void testAsList_isAView() {
641     char[] array = {(char) 0, (char) 1};
642     List<Character> list = Chars.asList(array);
643     list.set(0, (char) 2);
644     assertThat(array).isEqualTo(new char[] {(char) 2, (char) 1});
645     array[1] = (char) 3;
646     assertThat(list).containsExactly((char) 2, (char) 3).inOrder();
647   }
648 
testAsList_toArray_roundTrip()649   public void testAsList_toArray_roundTrip() {
650     char[] array = {(char) 0, (char) 1, (char) 2};
651     List<Character> list = Chars.asList(array);
652     char[] newArray = Chars.toArray(list);
653 
654     // Make sure it returned a copy
655     list.set(0, (char) 4);
656     assertThat(newArray).isEqualTo(new char[] {(char) 0, (char) 1, (char) 2});
657     newArray[1] = (char) 5;
658     assertThat((char) list.get(1)).isEqualTo((char) 1);
659   }
660 
661   // This test stems from a real bug found by andrewk
testAsList_subList_toArray_roundTrip()662   public void testAsList_subList_toArray_roundTrip() {
663     char[] array = {(char) 0, (char) 1, (char) 2, (char) 3};
664     List<Character> list = Chars.asList(array);
665     assertThat(Chars.toArray(list.subList(1, 3))).isEqualTo(new char[] {(char) 1, (char) 2});
666     assertThat(Chars.toArray(list.subList(2, 2))).isEqualTo(new char[] {});
667   }
668 
testAsListEmpty()669   public void testAsListEmpty() {
670     assertThat(Chars.asList(EMPTY)).isSameInstanceAs(Collections.emptyList());
671   }
672 
673   @J2ktIncompatible
674   @GwtIncompatible // NullPointerTester
testNulls()675   public void testNulls() {
676     new NullPointerTester().testAllPublicStaticMethods(Chars.class);
677   }
678 }
679