• 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 java.lang.Double.NaN;
21 
22 import com.google.common.annotations.GwtCompatible;
23 import com.google.common.annotations.GwtIncompatible;
24 import com.google.common.base.Converter;
25 import com.google.common.collect.ImmutableList;
26 import com.google.common.collect.testing.Helpers;
27 import com.google.common.testing.NullPointerTester;
28 import com.google.common.testing.SerializableTester;
29 import java.util.Arrays;
30 import java.util.Collection;
31 import java.util.Collections;
32 import java.util.Comparator;
33 import java.util.List;
34 import java.util.regex.Pattern;
35 import junit.framework.TestCase;
36 
37 /**
38  * Unit test for {@link Doubles}.
39  *
40  * @author Kevin Bourrillion
41  */
42 @GwtCompatible(emulated = true)
43 @SuppressWarnings("cast") // redundant casts are intentional and harmless
44 public class DoublesTest extends TestCase {
45   private static final double[] EMPTY = {};
46   private static final double[] ARRAY1 = {(double) 1};
47   private static final double[] ARRAY234 = {(double) 2, (double) 3, (double) 4};
48 
49   private static final double LEAST = Double.NEGATIVE_INFINITY;
50   private static final double GREATEST = Double.POSITIVE_INFINITY;
51 
52   private static final double[] NUMBERS =
53       new double[] {
54         LEAST,
55         -Double.MAX_VALUE,
56         -1.0,
57         -0.5,
58         -0.1,
59         -0.0,
60         0.0,
61         0.1,
62         0.5,
63         1.0,
64         Double.MAX_VALUE,
65         GREATEST,
66         Double.MIN_NORMAL,
67         -Double.MIN_NORMAL,
68         Double.MIN_VALUE,
69         -Double.MIN_VALUE,
70         Integer.MIN_VALUE,
71         Integer.MAX_VALUE,
72         Long.MIN_VALUE,
73         Long.MAX_VALUE
74       };
75 
76   private static final double[] VALUES = Doubles.concat(NUMBERS, new double[] {NaN});
77 
testHashCode()78   public void testHashCode() {
79     for (double value : VALUES) {
80       assertEquals(((Double) value).hashCode(), Doubles.hashCode(value));
81     }
82   }
83 
testIsFinite()84   public void testIsFinite() {
85     for (double value : NUMBERS) {
86       assertEquals(!(Double.isNaN(value) || Double.isInfinite(value)), Doubles.isFinite(value));
87     }
88   }
89 
testCompare()90   public void testCompare() {
91     for (double x : VALUES) {
92       for (double y : VALUES) {
93         // note: spec requires only that the sign is the same
94         assertEquals(x + ", " + y, Double.valueOf(x).compareTo(y), Doubles.compare(x, y));
95       }
96     }
97   }
98 
testContains()99   public void testContains() {
100     assertFalse(Doubles.contains(EMPTY, (double) 1));
101     assertFalse(Doubles.contains(ARRAY1, (double) 2));
102     assertFalse(Doubles.contains(ARRAY234, (double) 1));
103     assertTrue(Doubles.contains(new double[] {(double) -1}, (double) -1));
104     assertTrue(Doubles.contains(ARRAY234, (double) 2));
105     assertTrue(Doubles.contains(ARRAY234, (double) 3));
106     assertTrue(Doubles.contains(ARRAY234, (double) 4));
107 
108     for (double value : NUMBERS) {
109       assertTrue("" + value, Doubles.contains(new double[] {5.0, value}, value));
110     }
111     assertFalse(Doubles.contains(new double[] {5.0, NaN}, NaN));
112   }
113 
testIndexOf()114   public void testIndexOf() {
115     assertEquals(-1, Doubles.indexOf(EMPTY, (double) 1));
116     assertEquals(-1, Doubles.indexOf(ARRAY1, (double) 2));
117     assertEquals(-1, Doubles.indexOf(ARRAY234, (double) 1));
118     assertEquals(0, Doubles.indexOf(new double[] {(double) -1}, (double) -1));
119     assertEquals(0, Doubles.indexOf(ARRAY234, (double) 2));
120     assertEquals(1, Doubles.indexOf(ARRAY234, (double) 3));
121     assertEquals(2, Doubles.indexOf(ARRAY234, (double) 4));
122     assertEquals(
123         1,
124         Doubles.indexOf(new double[] {(double) 2, (double) 3, (double) 2, (double) 3}, (double) 3));
125 
126     for (double value : NUMBERS) {
127       assertEquals("" + value, 1, Doubles.indexOf(new double[] {5.0, value}, value));
128     }
129     assertEquals(-1, Doubles.indexOf(new double[] {5.0, NaN}, NaN));
130   }
131 
testIndexOf_arrayTarget()132   public void testIndexOf_arrayTarget() {
133     assertEquals(0, Doubles.indexOf(EMPTY, EMPTY));
134     assertEquals(0, Doubles.indexOf(ARRAY234, EMPTY));
135     assertEquals(-1, Doubles.indexOf(EMPTY, ARRAY234));
136     assertEquals(-1, Doubles.indexOf(ARRAY234, ARRAY1));
137     assertEquals(-1, Doubles.indexOf(ARRAY1, ARRAY234));
138     assertEquals(0, Doubles.indexOf(ARRAY1, ARRAY1));
139     assertEquals(0, Doubles.indexOf(ARRAY234, ARRAY234));
140     assertEquals(0, Doubles.indexOf(ARRAY234, new double[] {(double) 2, (double) 3}));
141     assertEquals(1, Doubles.indexOf(ARRAY234, new double[] {(double) 3, (double) 4}));
142     assertEquals(1, Doubles.indexOf(ARRAY234, new double[] {(double) 3}));
143     assertEquals(2, Doubles.indexOf(ARRAY234, new double[] {(double) 4}));
144     assertEquals(
145         1,
146         Doubles.indexOf(
147             new double[] {(double) 2, (double) 3, (double) 3, (double) 3, (double) 3},
148             new double[] {(double) 3}));
149     assertEquals(
150         2,
151         Doubles.indexOf(
152             new double[] {
153               (double) 2, (double) 3, (double) 2, (double) 3, (double) 4, (double) 2, (double) 3
154             },
155             new double[] {(double) 2, (double) 3, (double) 4}));
156     assertEquals(
157         1,
158         Doubles.indexOf(
159             new double[] {
160               (double) 2, (double) 2, (double) 3, (double) 4, (double) 2, (double) 3, (double) 4
161             },
162             new double[] {(double) 2, (double) 3, (double) 4}));
163     assertEquals(
164         -1,
165         Doubles.indexOf(
166             new double[] {(double) 4, (double) 3, (double) 2},
167             new double[] {(double) 2, (double) 3, (double) 4}));
168 
169     for (double value : NUMBERS) {
170       assertEquals(
171           "" + value,
172           1,
173           Doubles.indexOf(new double[] {5.0, value, value, 5.0}, new double[] {value, value}));
174     }
175     assertEquals(-1, Doubles.indexOf(new double[] {5.0, NaN, NaN, 5.0}, new double[] {NaN, NaN}));
176   }
177 
testLastIndexOf()178   public void testLastIndexOf() {
179     assertEquals(-1, Doubles.lastIndexOf(EMPTY, (double) 1));
180     assertEquals(-1, Doubles.lastIndexOf(ARRAY1, (double) 2));
181     assertEquals(-1, Doubles.lastIndexOf(ARRAY234, (double) 1));
182     assertEquals(0, Doubles.lastIndexOf(new double[] {(double) -1}, (double) -1));
183     assertEquals(0, Doubles.lastIndexOf(ARRAY234, (double) 2));
184     assertEquals(1, Doubles.lastIndexOf(ARRAY234, (double) 3));
185     assertEquals(2, Doubles.lastIndexOf(ARRAY234, (double) 4));
186     assertEquals(
187         3,
188         Doubles.lastIndexOf(
189             new double[] {(double) 2, (double) 3, (double) 2, (double) 3}, (double) 3));
190 
191     for (double value : NUMBERS) {
192       assertEquals("" + value, 0, Doubles.lastIndexOf(new double[] {value, 5.0}, value));
193     }
194     assertEquals(-1, Doubles.lastIndexOf(new double[] {NaN, 5.0}, NaN));
195   }
196 
testMax_noArgs()197   public void testMax_noArgs() {
198     try {
199       Doubles.max();
200       fail();
201     } catch (IllegalArgumentException expected) {
202     }
203   }
204 
testMax()205   public void testMax() {
206     assertEquals(LEAST, Doubles.max(LEAST));
207     assertEquals(GREATEST, Doubles.max(GREATEST));
208     assertEquals(
209         (double) 9,
210         Doubles.max(
211             (double) 8, (double) 6, (double) 7, (double) 5, (double) 3, (double) 0, (double) 9));
212 
213     assertEquals(0.0, Doubles.max(-0.0, 0.0));
214     assertEquals(0.0, Doubles.max(0.0, -0.0));
215     assertEquals(GREATEST, Doubles.max(NUMBERS));
216     assertTrue(Double.isNaN(Doubles.max(VALUES)));
217   }
218 
testMin_noArgs()219   public void testMin_noArgs() {
220     try {
221       Doubles.min();
222       fail();
223     } catch (IllegalArgumentException expected) {
224     }
225   }
226 
testMin()227   public void testMin() {
228     assertEquals(LEAST, Doubles.min(LEAST));
229     assertEquals(GREATEST, Doubles.min(GREATEST));
230     assertEquals(
231         (double) 0,
232         Doubles.min(
233             (double) 8, (double) 6, (double) 7, (double) 5, (double) 3, (double) 0, (double) 9));
234 
235     assertEquals(-0.0, Doubles.min(-0.0, 0.0));
236     assertEquals(-0.0, Doubles.min(0.0, -0.0));
237     assertEquals(LEAST, Doubles.min(NUMBERS));
238     assertTrue(Double.isNaN(Doubles.min(VALUES)));
239   }
240 
testConstrainToRange()241   public void testConstrainToRange() {
242     double tolerance = 1e-10;
243     assertEquals(
244         (double) 1, Doubles.constrainToRange((double) 1, (double) 0, (double) 5), tolerance);
245     assertEquals(
246         (double) 1, Doubles.constrainToRange((double) 1, (double) 1, (double) 5), tolerance);
247     assertEquals(
248         (double) 3, Doubles.constrainToRange((double) 1, (double) 3, (double) 5), tolerance);
249     assertEquals(
250         (double) -1, Doubles.constrainToRange((double) 0, (double) -5, (double) -1), tolerance);
251     assertEquals(
252         (double) 2, Doubles.constrainToRange((double) 5, (double) 2, (double) 2), tolerance);
253     try {
254       Doubles.constrainToRange((double) 1, (double) 3, (double) 2);
255       fail();
256     } catch (IllegalArgumentException expected) {
257     }
258   }
259 
testConcat()260   public void testConcat() {
261     assertTrue(Arrays.equals(EMPTY, Doubles.concat()));
262     assertTrue(Arrays.equals(EMPTY, Doubles.concat(EMPTY)));
263     assertTrue(Arrays.equals(EMPTY, Doubles.concat(EMPTY, EMPTY, EMPTY)));
264     assertTrue(Arrays.equals(ARRAY1, Doubles.concat(ARRAY1)));
265     assertNotSame(ARRAY1, Doubles.concat(ARRAY1));
266     assertTrue(Arrays.equals(ARRAY1, Doubles.concat(EMPTY, ARRAY1, EMPTY)));
267     assertTrue(
268         Arrays.equals(
269             new double[] {(double) 1, (double) 1, (double) 1},
270             Doubles.concat(ARRAY1, ARRAY1, ARRAY1)));
271     assertTrue(
272         Arrays.equals(
273             new double[] {(double) 1, (double) 2, (double) 3, (double) 4},
274             Doubles.concat(ARRAY1, ARRAY234)));
275   }
276 
testEnsureCapacity()277   public void testEnsureCapacity() {
278     assertSame(EMPTY, Doubles.ensureCapacity(EMPTY, 0, 1));
279     assertSame(ARRAY1, Doubles.ensureCapacity(ARRAY1, 0, 1));
280     assertSame(ARRAY1, Doubles.ensureCapacity(ARRAY1, 1, 1));
281     assertTrue(
282         Arrays.equals(
283             new double[] {(double) 1, (double) 0, (double) 0},
284             Doubles.ensureCapacity(ARRAY1, 2, 1)));
285   }
286 
testEnsureCapacity_fail()287   public void testEnsureCapacity_fail() {
288     try {
289       Doubles.ensureCapacity(ARRAY1, -1, 1);
290       fail();
291     } catch (IllegalArgumentException expected) {
292     }
293     try {
294       // notice that this should even fail when no growth was needed
295       Doubles.ensureCapacity(ARRAY1, 1, -1);
296       fail();
297     } catch (IllegalArgumentException expected) {
298     }
299   }
300 
301   @GwtIncompatible // Double.toString returns different value in GWT.
testJoin()302   public void testJoin() {
303     assertEquals("", Doubles.join(",", EMPTY));
304     assertEquals("1.0", Doubles.join(",", ARRAY1));
305     assertEquals("1.0,2.0", Doubles.join(",", (double) 1, (double) 2));
306     assertEquals("1.02.03.0", Doubles.join("", (double) 1, (double) 2, (double) 3));
307   }
308 
testJoinNonTrivialDoubles()309   public void testJoinNonTrivialDoubles() {
310     assertEquals("", Doubles.join(",", EMPTY));
311     assertEquals("1.2", Doubles.join(",", 1.2));
312     assertEquals("1.3,2.4", Doubles.join(",", 1.3, 2.4));
313     assertEquals("1.42.53.6", Doubles.join("", 1.4, 2.5, 3.6));
314   }
315 
testLexicographicalComparator()316   public void testLexicographicalComparator() {
317     List<double[]> ordered =
318         Arrays.asList(
319             new double[] {},
320             new double[] {LEAST},
321             new double[] {LEAST, LEAST},
322             new double[] {LEAST, (double) 1},
323             new double[] {(double) 1},
324             new double[] {(double) 1, LEAST},
325             new double[] {GREATEST, Double.MAX_VALUE},
326             new double[] {GREATEST, GREATEST},
327             new double[] {GREATEST, GREATEST, GREATEST});
328 
329     Comparator<double[]> comparator = Doubles.lexicographicalComparator();
330     Helpers.testComparator(comparator, ordered);
331   }
332 
testReverse()333   public void testReverse() {
334     testReverse(new double[] {}, new double[] {});
335     testReverse(new double[] {1}, new double[] {1});
336     testReverse(new double[] {1, 2}, new double[] {2, 1});
337     testReverse(new double[] {3, 1, 1}, new double[] {1, 1, 3});
338     testReverse(new double[] {-1, 1, -2, 2}, new double[] {2, -2, 1, -1});
339   }
340 
testReverse(double[] input, double[] expectedOutput)341   private static void testReverse(double[] input, double[] expectedOutput) {
342     input = Arrays.copyOf(input, input.length);
343     Doubles.reverse(input);
344     assertTrue(Arrays.equals(expectedOutput, input));
345   }
346 
testReverse( double[] input, int fromIndex, int toIndex, double[] expectedOutput)347   private static void testReverse(
348       double[] input, int fromIndex, int toIndex, double[] expectedOutput) {
349     input = Arrays.copyOf(input, input.length);
350     Doubles.reverse(input, fromIndex, toIndex);
351     assertTrue(Arrays.equals(expectedOutput, input));
352   }
353 
testReverseIndexed()354   public void testReverseIndexed() {
355     testReverse(new double[] {}, 0, 0, new double[] {});
356     testReverse(new double[] {1}, 0, 1, new double[] {1});
357     testReverse(new double[] {1, 2}, 0, 2, new double[] {2, 1});
358     testReverse(new double[] {3, 1, 1}, 0, 2, new double[] {1, 3, 1});
359     testReverse(new double[] {3, 1, 1}, 0, 1, new double[] {3, 1, 1});
360     testReverse(new double[] {-1, 1, -2, 2}, 1, 3, new double[] {-1, -2, 1, 2});
361   }
362 
testSortDescending()363   public void testSortDescending() {
364     testSortDescending(new double[] {}, new double[] {});
365     testSortDescending(new double[] {1}, new double[] {1});
366     testSortDescending(new double[] {1, 2}, new double[] {2, 1});
367     testSortDescending(new double[] {1, 3, 1}, new double[] {3, 1, 1});
368     testSortDescending(new double[] {-1, 1, -2, 2}, new double[] {2, 1, -1, -2});
369     testSortDescending(
370         new double[] {-1, 1, Double.NaN, -2, -0, 0, 2},
371         new double[] {Double.NaN, 2, 1, 0, -0, -1, -2});
372   }
373 
testSortDescending(double[] input, double[] expectedOutput)374   private static void testSortDescending(double[] input, double[] expectedOutput) {
375     input = Arrays.copyOf(input, input.length);
376     Doubles.sortDescending(input);
377     // GWT's Arrays.equals doesn't appear to handle NaN correctly, so test each element individually
378     for (int i = 0; i < input.length; i++) {
379       assertEquals(0, Double.compare(expectedOutput[i], input[i]));
380     }
381   }
382 
testSortDescending( double[] input, int fromIndex, int toIndex, double[] expectedOutput)383   private static void testSortDescending(
384       double[] input, int fromIndex, int toIndex, double[] expectedOutput) {
385     input = Arrays.copyOf(input, input.length);
386     Doubles.sortDescending(input, fromIndex, toIndex);
387     // GWT's Arrays.equals doesn't appear to handle NaN correctly, so test each element individually
388     for (int i = 0; i < input.length; i++) {
389       assertEquals(0, Double.compare(expectedOutput[i], input[i]));
390     }
391   }
392 
testSortDescendingIndexed()393   public void testSortDescendingIndexed() {
394     testSortDescending(new double[] {}, 0, 0, new double[] {});
395     testSortDescending(new double[] {1}, 0, 1, new double[] {1});
396     testSortDescending(new double[] {1, 2}, 0, 2, new double[] {2, 1});
397     testSortDescending(new double[] {1, 3, 1}, 0, 2, new double[] {3, 1, 1});
398     testSortDescending(new double[] {1, 3, 1}, 0, 1, new double[] {1, 3, 1});
399     testSortDescending(new double[] {-1, -2, 1, 2}, 1, 3, new double[] {-1, 1, -2, 2});
400     testSortDescending(
401         new double[] {-1, 1, Double.NaN, -2, 2}, 1, 4, new double[] {-1, Double.NaN, 1, -2, 2});
402   }
403 
404   @GwtIncompatible // SerializableTester
testLexicographicalComparatorSerializable()405   public void testLexicographicalComparatorSerializable() {
406     Comparator<double[]> comparator = Doubles.lexicographicalComparator();
407     assertSame(comparator, SerializableTester.reserialize(comparator));
408   }
409 
410   @GwtIncompatible // SerializableTester
testStringConverterSerialization()411   public void testStringConverterSerialization() {
412     SerializableTester.reserializeAndAssert(Doubles.stringConverter());
413   }
414 
testToArray()415   public void testToArray() {
416     // need explicit type parameter to avoid javac warning!?
417     List<Double> none = Arrays.<Double>asList();
418     assertTrue(Arrays.equals(EMPTY, Doubles.toArray(none)));
419 
420     List<Double> one = Arrays.asList((double) 1);
421     assertTrue(Arrays.equals(ARRAY1, Doubles.toArray(one)));
422 
423     double[] array = {(double) 0, (double) 1, Math.PI};
424 
425     List<Double> three = Arrays.asList((double) 0, (double) 1, Math.PI);
426     assertTrue(Arrays.equals(array, Doubles.toArray(three)));
427 
428     assertTrue(Arrays.equals(array, Doubles.toArray(Doubles.asList(array))));
429   }
430 
testToArray_threadSafe()431   public void testToArray_threadSafe() {
432     for (int delta : new int[] {+1, 0, -1}) {
433       for (int i = 0; i < VALUES.length; i++) {
434         List<Double> list = Doubles.asList(VALUES).subList(0, i);
435         Collection<Double> misleadingSize = Helpers.misleadingSizeCollection(delta);
436         misleadingSize.addAll(list);
437         double[] arr = Doubles.toArray(misleadingSize);
438         assertEquals(i, arr.length);
439         for (int j = 0; j < i; j++) {
440           assertEquals(VALUES[j], arr[j]);
441         }
442       }
443     }
444   }
445 
testToArray_withNull()446   public void testToArray_withNull() {
447     List<Double> list = Arrays.asList((double) 0, (double) 1, null);
448     try {
449       Doubles.toArray(list);
450       fail();
451     } catch (NullPointerException expected) {
452     }
453   }
454 
testToArray_withConversion()455   public void testToArray_withConversion() {
456     double[] array = {(double) 0, (double) 1, (double) 2};
457 
458     List<Byte> bytes = Arrays.asList((byte) 0, (byte) 1, (byte) 2);
459     List<Short> shorts = Arrays.asList((short) 0, (short) 1, (short) 2);
460     List<Integer> ints = Arrays.asList(0, 1, 2);
461     List<Float> floats = Arrays.asList((float) 0, (float) 1, (float) 2);
462     List<Long> longs = Arrays.asList((long) 0, (long) 1, (long) 2);
463     List<Double> doubles = Arrays.asList((double) 0, (double) 1, (double) 2);
464 
465     assertTrue(Arrays.equals(array, Doubles.toArray(bytes)));
466     assertTrue(Arrays.equals(array, Doubles.toArray(shorts)));
467     assertTrue(Arrays.equals(array, Doubles.toArray(ints)));
468     assertTrue(Arrays.equals(array, Doubles.toArray(floats)));
469     assertTrue(Arrays.equals(array, Doubles.toArray(longs)));
470     assertTrue(Arrays.equals(array, Doubles.toArray(doubles)));
471   }
472 
testAsList_isAView()473   public void testAsList_isAView() {
474     double[] array = {(double) 0, (double) 1};
475     List<Double> list = Doubles.asList(array);
476     list.set(0, (double) 2);
477     assertTrue(Arrays.equals(new double[] {(double) 2, (double) 1}, array));
478     array[1] = (double) 3;
479     assertThat(list).containsExactly((double) 2, (double) 3).inOrder();
480   }
481 
testAsList_toArray_roundTrip()482   public void testAsList_toArray_roundTrip() {
483     double[] array = {(double) 0, (double) 1, (double) 2};
484     List<Double> list = Doubles.asList(array);
485     double[] newArray = Doubles.toArray(list);
486 
487     // Make sure it returned a copy
488     list.set(0, (double) 4);
489     assertTrue(Arrays.equals(new double[] {(double) 0, (double) 1, (double) 2}, newArray));
490     newArray[1] = (double) 5;
491     assertEquals((double) 1, (double) list.get(1));
492   }
493 
494   // This test stems from a real bug found by andrewk
testAsList_subList_toArray_roundTrip()495   public void testAsList_subList_toArray_roundTrip() {
496     double[] array = {(double) 0, (double) 1, (double) 2, (double) 3};
497     List<Double> list = Doubles.asList(array);
498     assertTrue(
499         Arrays.equals(new double[] {(double) 1, (double) 2}, Doubles.toArray(list.subList(1, 3))));
500     assertTrue(Arrays.equals(new double[] {}, Doubles.toArray(list.subList(2, 2))));
501   }
502 
testAsListEmpty()503   public void testAsListEmpty() {
504     assertSame(Collections.emptyList(), Doubles.asList(EMPTY));
505   }
506 
507   /**
508    * A reference implementation for {@code tryParse} that just catches the exception from {@link
509    * Double#valueOf}.
510    */
referenceTryParse(String input)511   private static Double referenceTryParse(String input) {
512     if (input.trim().length() < input.length()) {
513       return null;
514     }
515     try {
516       return Double.valueOf(input);
517     } catch (NumberFormatException e) {
518       return null;
519     }
520   }
521 
522   @GwtIncompatible // Doubles.tryParse
checkTryParse(String input)523   private static void checkTryParse(String input) {
524     Double expected = referenceTryParse(input);
525     assertEquals(expected, Doubles.tryParse(input));
526     if (expected != null && !Doubles.FLOATING_POINT_PATTERN.matcher(input).matches()) {
527       // TODO(cpovirk): Use SourceCodeEscapers if it is added to Guava.
528       StringBuilder escapedInput = new StringBuilder();
529       for (char c : input.toCharArray()) {
530         if (c >= 0x20 && c <= 0x7E) {
531           escapedInput.append(c);
532         } else {
533           escapedInput.append(String.format("\\u%04x", (int) c));
534         }
535       }
536       fail("FLOATING_POINT_PATTERN should have matched valid input <" + escapedInput + ">");
537     }
538   }
539 
540   @GwtIncompatible // Doubles.tryParse
checkTryParse(double expected, String input)541   private static void checkTryParse(double expected, String input) {
542     assertEquals(Double.valueOf(expected), Doubles.tryParse(input));
543     assertThat(input)
544         .matches(
545             Pattern.compile(
546                 Doubles.FLOATING_POINT_PATTERN.pattern(), Doubles.FLOATING_POINT_PATTERN.flags()));
547   }
548 
549   @GwtIncompatible // Doubles.tryParse
testTryParseHex()550   public void testTryParseHex() {
551     for (String signChar : ImmutableList.of("", "+", "-")) {
552       for (String hexPrefix : ImmutableList.of("0x", "0X")) {
553         for (String iPart : ImmutableList.of("", "0", "1", "F", "f", "c4", "CE")) {
554           for (String fPart : ImmutableList.of("", ".", ".F", ".52", ".a")) {
555             for (String expMarker : ImmutableList.of("p", "P")) {
556               for (String exponent : ImmutableList.of("0", "-5", "+20", "52")) {
557                 for (String typePart : ImmutableList.of("", "D", "F", "d", "f")) {
558                   checkTryParse(
559                       signChar + hexPrefix + iPart + fPart + expMarker + exponent + typePart);
560                 }
561               }
562             }
563           }
564         }
565       }
566     }
567   }
568 
569   @AndroidIncompatible // slow
570   @GwtIncompatible // Doubles.tryParse
testTryParseAllCodePoints()571   public void testTryParseAllCodePoints() {
572     // Exercise non-ASCII digit test cases and the like.
573     char[] tmp = new char[2];
574     for (int i = Character.MIN_CODE_POINT; i < Character.MAX_CODE_POINT; i++) {
575       Character.toChars(i, tmp, 0);
576       checkTryParse(String.copyValueOf(tmp, 0, Character.charCount(i)));
577     }
578   }
579 
580   @GwtIncompatible // Doubles.tryParse
testTryParseOfToStringIsOriginal()581   public void testTryParseOfToStringIsOriginal() {
582     for (double d : NUMBERS) {
583       checkTryParse(d, Double.toString(d));
584     }
585   }
586 
587   @GwtIncompatible // Doubles.tryParse
testTryParseOfToHexStringIsOriginal()588   public void testTryParseOfToHexStringIsOriginal() {
589     for (double d : NUMBERS) {
590       checkTryParse(d, Double.toHexString(d));
591     }
592   }
593 
594   @GwtIncompatible // Doubles.tryParse
testTryParseNaN()595   public void testTryParseNaN() {
596     checkTryParse("NaN");
597     checkTryParse("+NaN");
598     checkTryParse("-NaN");
599   }
600 
601   @GwtIncompatible // Doubles.tryParse
testTryParseInfinity()602   public void testTryParseInfinity() {
603     checkTryParse(Double.POSITIVE_INFINITY, "Infinity");
604     checkTryParse(Double.POSITIVE_INFINITY, "+Infinity");
605     checkTryParse(Double.NEGATIVE_INFINITY, "-Infinity");
606   }
607 
608   private static final String[] BAD_TRY_PARSE_INPUTS = {
609     "",
610     "+-",
611     "+-0",
612     " 5",
613     "32 ",
614     " 55 ",
615     "infinity",
616     "POSITIVE_INFINITY",
617     "0x9A",
618     "0x9A.bE-5",
619     ".",
620     ".e5",
621     "NaNd",
622     "InfinityF"
623   };
624 
625   @GwtIncompatible // Doubles.tryParse
testTryParseFailures()626   public void testTryParseFailures() {
627     for (String badInput : BAD_TRY_PARSE_INPUTS) {
628       assertThat(badInput)
629           .doesNotMatch(
630               Pattern.compile(
631                   Doubles.FLOATING_POINT_PATTERN.pattern(),
632                   Doubles.FLOATING_POINT_PATTERN.flags()));
633       assertEquals(referenceTryParse(badInput), Doubles.tryParse(badInput));
634       assertNull(Doubles.tryParse(badInput));
635     }
636   }
637 
638   @GwtIncompatible // NullPointerTester
testNulls()639   public void testNulls() {
640     new NullPointerTester().testAllPublicStaticMethods(Doubles.class);
641   }
642 
testStringConverter_convert()643   public void testStringConverter_convert() {
644     Converter<String, Double> converter = Doubles.stringConverter();
645     assertEquals((Double) 1.0, converter.convert("1.0"));
646     assertEquals((Double) 0.0, converter.convert("0.0"));
647     assertEquals((Double) (-1.0), converter.convert("-1.0"));
648     assertEquals((Double) 1.0, converter.convert("1"));
649     assertEquals((Double) 0.0, converter.convert("0"));
650     assertEquals((Double) (-1.0), converter.convert("-1"));
651     assertEquals((Double) 1e6, converter.convert("1e6"));
652     assertEquals((Double) 1e-6, converter.convert("1e-6"));
653   }
654 
testStringConverter_convertError()655   public void testStringConverter_convertError() {
656     try {
657       Doubles.stringConverter().convert("notanumber");
658       fail();
659     } catch (NumberFormatException expected) {
660     }
661   }
662 
testStringConverter_nullConversions()663   public void testStringConverter_nullConversions() {
664     assertNull(Doubles.stringConverter().convert(null));
665     assertNull(Doubles.stringConverter().reverse().convert(null));
666   }
667 
668   @GwtIncompatible // Double.toString returns different value in GWT.
testStringConverter_reverse()669   public void testStringConverter_reverse() {
670     Converter<String, Double> converter = Doubles.stringConverter();
671     assertEquals("1.0", converter.reverse().convert(1.0));
672     assertEquals("0.0", converter.reverse().convert(0.0));
673     assertEquals("-1.0", converter.reverse().convert(-1.0));
674     assertEquals("1000000.0", converter.reverse().convert(1e6));
675     assertEquals("1.0E-6", converter.reverse().convert(1e-6));
676   }
677 
678   @GwtIncompatible // NullPointerTester
testStringConverter_nullPointerTester()679   public void testStringConverter_nullPointerTester() throws Exception {
680     NullPointerTester tester = new NullPointerTester();
681     tester.testAllPublicInstanceMethods(Doubles.stringConverter());
682   }
683 
684   @GwtIncompatible
testTryParse_withNullNoGwt()685   public void testTryParse_withNullNoGwt() {
686     assertNull(Doubles.tryParse("null"));
687     try {
688       Doubles.tryParse(null);
689       fail("Expected NPE");
690     } catch (NullPointerException expected) {
691     }
692   }
693 }
694