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 
30 import junit.framework.TestCase;
31 
32 import java.util.Arrays;
33 import java.util.Collection;
34 import java.util.Collections;
35 import java.util.Comparator;
36 import java.util.List;
37 
38 /**
39  * Unit test for {@link Doubles}.
40  *
41  * @author Kevin Bourrillion
42  */
43 @GwtCompatible(emulated = true)
44 @SuppressWarnings("cast") // redundant casts are intentional and harmless
45 public class DoublesTest extends TestCase {
46   private static final double[] EMPTY = {};
47   private static final double[] ARRAY1 = {(double) 1};
48   private static final double[] ARRAY234
49       = {(double) 2, (double) 3, (double) 4};
50 
51   private static final double LEAST = Double.NEGATIVE_INFINITY;
52   private static final double GREATEST = Double.POSITIVE_INFINITY;
53 
54   private static final double[] NUMBERS = new double[] {
55       LEAST, -Double.MAX_VALUE, -1.0, -0.5, -0.1, -0.0, 0.0, 0.1, 0.5, 1.0,
56       Double.MAX_VALUE, GREATEST, Double.MIN_NORMAL, -Double.MIN_NORMAL,
57       Double.MIN_VALUE, -Double.MIN_VALUE, Integer.MIN_VALUE,
58       Integer.MAX_VALUE, Long.MIN_VALUE, Long.MAX_VALUE
59   };
60 
61   private static final double[] VALUES
62       = Doubles.concat(NUMBERS, new double[] {NaN});
63 
testHashCode()64   public void testHashCode() {
65     for (double value : VALUES) {
66       assertEquals(((Double) value).hashCode(), Doubles.hashCode(value));
67     }
68   }
69 
testIsFinite()70   public void testIsFinite() {
71     for (double value : NUMBERS) {
72       assertEquals(!(Double.isNaN(value) || Double.isInfinite(value)), Doubles.isFinite(value));
73     }
74   }
75 
testCompare()76   public void testCompare() {
77     for (double x : VALUES) {
78       for (double y : VALUES) {
79         // note: spec requires only that the sign is the same
80         assertEquals(x + ", " + y,
81                      Double.valueOf(x).compareTo(y),
82                      Doubles.compare(x, y));
83       }
84     }
85   }
86 
testContains()87   public void testContains() {
88     assertFalse(Doubles.contains(EMPTY, (double) 1));
89     assertFalse(Doubles.contains(ARRAY1, (double) 2));
90     assertFalse(Doubles.contains(ARRAY234, (double) 1));
91     assertTrue(Doubles.contains(new double[] {(double) -1}, (double) -1));
92     assertTrue(Doubles.contains(ARRAY234, (double) 2));
93     assertTrue(Doubles.contains(ARRAY234, (double) 3));
94     assertTrue(Doubles.contains(ARRAY234, (double) 4));
95 
96     for (double value : NUMBERS) {
97       assertTrue("" + value,
98           Doubles.contains(new double[] {5.0, value}, value));
99     }
100     assertFalse(Doubles.contains(new double[] {5.0, NaN}, NaN));
101   }
102 
testIndexOf()103   public void testIndexOf() {
104     assertEquals(-1, Doubles.indexOf(EMPTY, (double) 1));
105     assertEquals(-1, Doubles.indexOf(ARRAY1, (double) 2));
106     assertEquals(-1, Doubles.indexOf(ARRAY234, (double) 1));
107     assertEquals(0, Doubles.indexOf(
108         new double[] {(double) -1}, (double) -1));
109     assertEquals(0, Doubles.indexOf(ARRAY234, (double) 2));
110     assertEquals(1, Doubles.indexOf(ARRAY234, (double) 3));
111     assertEquals(2, Doubles.indexOf(ARRAY234, (double) 4));
112     assertEquals(1, Doubles.indexOf(
113         new double[] { (double) 2, (double) 3, (double) 2, (double) 3 },
114         (double) 3));
115 
116     for (double value : NUMBERS) {
117       assertEquals("" + value,
118           1, Doubles.indexOf(new double[] {5.0, value}, value));
119     }
120     assertEquals(-1, Doubles.indexOf(new double[] {5.0, NaN}, NaN));
121   }
122 
testIndexOf_arrayTarget()123   public void testIndexOf_arrayTarget() {
124     assertEquals(0, Doubles.indexOf(EMPTY, EMPTY));
125     assertEquals(0, Doubles.indexOf(ARRAY234, EMPTY));
126     assertEquals(-1, Doubles.indexOf(EMPTY, ARRAY234));
127     assertEquals(-1, Doubles.indexOf(ARRAY234, ARRAY1));
128     assertEquals(-1, Doubles.indexOf(ARRAY1, ARRAY234));
129     assertEquals(0, Doubles.indexOf(ARRAY1, ARRAY1));
130     assertEquals(0, Doubles.indexOf(ARRAY234, ARRAY234));
131     assertEquals(0, Doubles.indexOf(
132         ARRAY234, new double[] { (double) 2, (double) 3 }));
133     assertEquals(1, Doubles.indexOf(
134         ARRAY234, new double[] { (double) 3, (double) 4 }));
135     assertEquals(1, Doubles.indexOf(ARRAY234, new double[] { (double) 3 }));
136     assertEquals(2, Doubles.indexOf(ARRAY234, new double[] { (double) 4 }));
137     assertEquals(1, Doubles.indexOf(new double[] { (double) 2, (double) 3,
138         (double) 3, (double) 3, (double) 3 },
139         new double[] { (double) 3 }
140     ));
141     assertEquals(2, Doubles.indexOf(
142         new double[] { (double) 2, (double) 3, (double) 2,
143             (double) 3, (double) 4, (double) 2, (double) 3},
144         new double[] { (double) 2, (double) 3, (double) 4}
145     ));
146     assertEquals(1, Doubles.indexOf(
147         new double[] { (double) 2, (double) 2, (double) 3,
148             (double) 4, (double) 2, (double) 3, (double) 4},
149         new double[] { (double) 2, (double) 3, (double) 4}
150     ));
151     assertEquals(-1, Doubles.indexOf(
152         new double[] { (double) 4, (double) 3, (double) 2},
153         new double[] { (double) 2, (double) 3, (double) 4}
154     ));
155 
156     for (double value : NUMBERS) {
157       assertEquals("" + value, 1, Doubles.indexOf(
158           new double[] {5.0, value, value, 5.0}, new double[] {value, value}));
159     }
160     assertEquals(-1, Doubles.indexOf(
161         new double[] {5.0, NaN, NaN, 5.0}, new double[] {NaN, NaN}));
162   }
163 
testLastIndexOf()164   public void testLastIndexOf() {
165     assertEquals(-1, Doubles.lastIndexOf(EMPTY, (double) 1));
166     assertEquals(-1, Doubles.lastIndexOf(ARRAY1, (double) 2));
167     assertEquals(-1, Doubles.lastIndexOf(ARRAY234, (double) 1));
168     assertEquals(0, Doubles.lastIndexOf(
169         new double[] {(double) -1}, (double) -1));
170     assertEquals(0, Doubles.lastIndexOf(ARRAY234, (double) 2));
171     assertEquals(1, Doubles.lastIndexOf(ARRAY234, (double) 3));
172     assertEquals(2, Doubles.lastIndexOf(ARRAY234, (double) 4));
173     assertEquals(3, Doubles.lastIndexOf(
174         new double[] { (double) 2, (double) 3, (double) 2, (double) 3 },
175         (double) 3));
176 
177     for (double value : NUMBERS) {
178       assertEquals("" + value,
179           0, Doubles.lastIndexOf(new double[] {value, 5.0}, value));
180     }
181     assertEquals(-1, Doubles.lastIndexOf(new double[] {NaN, 5.0}, NaN));
182   }
183 
testMax_noArgs()184   public void testMax_noArgs() {
185     try {
186       Doubles.max();
187       fail();
188     } catch (IllegalArgumentException expected) {
189     }
190   }
191 
testMax()192   public void testMax() {
193     assertEquals(LEAST, Doubles.max(LEAST));
194     assertEquals(GREATEST, Doubles.max(GREATEST));
195     assertEquals((double) 9, Doubles.max(
196         (double) 8, (double) 6, (double) 7,
197         (double) 5, (double) 3, (double) 0, (double) 9));
198 
199     assertEquals(0.0, Doubles.max(-0.0, 0.0));
200     assertEquals(0.0, Doubles.max(0.0, -0.0));
201     assertEquals(GREATEST, Doubles.max(NUMBERS));
202     assertTrue(Double.isNaN(Doubles.max(VALUES)));
203   }
204 
testMin_noArgs()205   public void testMin_noArgs() {
206     try {
207       Doubles.min();
208       fail();
209     } catch (IllegalArgumentException expected) {
210     }
211   }
212 
testMin()213   public void testMin() {
214     assertEquals(LEAST, Doubles.min(LEAST));
215     assertEquals(GREATEST, Doubles.min(GREATEST));
216     assertEquals((double) 0, Doubles.min(
217         (double) 8, (double) 6, (double) 7,
218         (double) 5, (double) 3, (double) 0, (double) 9));
219 
220     assertEquals(-0.0, Doubles.min(-0.0, 0.0));
221     assertEquals(-0.0, Doubles.min(0.0, -0.0));
222     assertEquals(LEAST, Doubles.min(NUMBERS));
223     assertTrue(Double.isNaN(Doubles.min(VALUES)));
224   }
225 
testConcat()226   public void testConcat() {
227     assertTrue(Arrays.equals(EMPTY, Doubles.concat()));
228     assertTrue(Arrays.equals(EMPTY, Doubles.concat(EMPTY)));
229     assertTrue(Arrays.equals(EMPTY, Doubles.concat(EMPTY, EMPTY, EMPTY)));
230     assertTrue(Arrays.equals(ARRAY1, Doubles.concat(ARRAY1)));
231     assertNotSame(ARRAY1, Doubles.concat(ARRAY1));
232     assertTrue(Arrays.equals(ARRAY1, Doubles.concat(EMPTY, ARRAY1, EMPTY)));
233     assertTrue(Arrays.equals(
234         new double[] {(double) 1, (double) 1, (double) 1},
235         Doubles.concat(ARRAY1, ARRAY1, ARRAY1)));
236     assertTrue(Arrays.equals(
237         new double[] {(double) 1, (double) 2, (double) 3, (double) 4},
238         Doubles.concat(ARRAY1, ARRAY234)));
239   }
240 
testEnsureCapacity()241   public void testEnsureCapacity() {
242     assertSame(EMPTY, Doubles.ensureCapacity(EMPTY, 0, 1));
243     assertSame(ARRAY1, Doubles.ensureCapacity(ARRAY1, 0, 1));
244     assertSame(ARRAY1, Doubles.ensureCapacity(ARRAY1, 1, 1));
245     assertTrue(Arrays.equals(
246         new double[] {(double) 1, (double) 0, (double) 0},
247         Doubles.ensureCapacity(ARRAY1, 2, 1)));
248   }
249 
testEnsureCapacity_fail()250   public void testEnsureCapacity_fail() {
251     try {
252       Doubles.ensureCapacity(ARRAY1, -1, 1);
253       fail();
254     } catch (IllegalArgumentException expected) {
255     }
256     try {
257       // notice that this should even fail when no growth was needed
258       Doubles.ensureCapacity(ARRAY1, 1, -1);
259       fail();
260     } catch (IllegalArgumentException expected) {
261     }
262   }
263 
264   @GwtIncompatible("Double.toString returns different value in GWT.")
testJoin()265   public void testJoin() {
266     assertEquals("", Doubles.join(",", EMPTY));
267     assertEquals("1.0", Doubles.join(",", ARRAY1));
268     assertEquals("1.0,2.0", Doubles.join(",", (double) 1, (double) 2));
269     assertEquals("1.02.03.0",
270         Doubles.join("", (double) 1, (double) 2, (double) 3));
271   }
272 
testJoinNonTrivialDoubles()273   public void testJoinNonTrivialDoubles() {
274     assertEquals("", Doubles.join(",", EMPTY));
275     assertEquals("1.2", Doubles.join(",", 1.2));
276     assertEquals("1.3,2.4", Doubles.join(",", 1.3, 2.4));
277     assertEquals("1.42.53.6", Doubles.join("", 1.4, 2.5, 3.6));
278   }
279 
testLexicographicalComparator()280   public void testLexicographicalComparator() {
281     List<double[]> ordered = Arrays.asList(
282         new double[] {},
283         new double[] {LEAST},
284         new double[] {LEAST, LEAST},
285         new double[] {LEAST, (double) 1},
286         new double[] {(double) 1},
287         new double[] {(double) 1, LEAST},
288         new double[] {GREATEST, Double.MAX_VALUE},
289         new double[] {GREATEST, GREATEST},
290         new double[] {GREATEST, GREATEST, GREATEST});
291 
292     Comparator<double[]> comparator = Doubles.lexicographicalComparator();
293     Helpers.testComparator(comparator, ordered);
294   }
295 
296   @GwtIncompatible("SerializableTester")
testLexicographicalComparatorSerializable()297   public void testLexicographicalComparatorSerializable() {
298     Comparator<double[]> comparator = Doubles.lexicographicalComparator();
299     assertSame(comparator, SerializableTester.reserialize(comparator));
300   }
301 
302   @GwtIncompatible("SerializableTester")
testStringConverterSerialization()303   public void testStringConverterSerialization() {
304     SerializableTester.reserializeAndAssert(Doubles.stringConverter());
305   }
306 
testToArray()307   public void testToArray() {
308     // need explicit type parameter to avoid javac warning!?
309     List<Double> none = Arrays.<Double>asList();
310     assertTrue(Arrays.equals(EMPTY, Doubles.toArray(none)));
311 
312     List<Double> one = Arrays.asList((double) 1);
313     assertTrue(Arrays.equals(ARRAY1, Doubles.toArray(one)));
314 
315     double[] array = {(double) 0, (double) 1, Math.PI};
316 
317     List<Double> three = Arrays.asList((double) 0, (double) 1, Math.PI);
318     assertTrue(Arrays.equals(array, Doubles.toArray(three)));
319 
320     assertTrue(Arrays.equals(array, Doubles.toArray(Doubles.asList(array))));
321   }
322 
testToArray_threadSafe()323   public void testToArray_threadSafe() {
324     for (int delta : new int[] { +1, 0, -1 }) {
325       for (int i = 0; i < VALUES.length; i++) {
326         List<Double> list = Doubles.asList(VALUES).subList(0, i);
327         Collection<Double> misleadingSize =
328             Helpers.misleadingSizeCollection(delta);
329         misleadingSize.addAll(list);
330         double[] arr = Doubles.toArray(misleadingSize);
331         assertEquals(i, arr.length);
332         for (int j = 0; j < i; j++) {
333           assertEquals(VALUES[j], arr[j]);
334         }
335       }
336     }
337   }
338 
testToArray_withNull()339   public void testToArray_withNull() {
340     List<Double> list = Arrays.asList((double) 0, (double) 1, null);
341     try {
342       Doubles.toArray(list);
343       fail();
344     } catch (NullPointerException expected) {
345     }
346   }
347 
testToArray_withConversion()348   public void testToArray_withConversion() {
349     double[] array = {(double) 0, (double) 1, (double) 2};
350 
351     List<Byte> bytes = Arrays.asList((byte) 0, (byte) 1, (byte) 2);
352     List<Short> shorts = Arrays.asList((short) 0, (short) 1, (short) 2);
353     List<Integer> ints = Arrays.asList(0, 1, 2);
354     List<Float> floats = Arrays.asList((float) 0, (float) 1, (float) 2);
355     List<Long> longs = Arrays.asList((long) 0, (long) 1, (long) 2);
356     List<Double> doubles = Arrays.asList((double) 0, (double) 1, (double) 2);
357 
358     assertTrue(Arrays.equals(array, Doubles.toArray(bytes)));
359     assertTrue(Arrays.equals(array, Doubles.toArray(shorts)));
360     assertTrue(Arrays.equals(array, Doubles.toArray(ints)));
361     assertTrue(Arrays.equals(array, Doubles.toArray(floats)));
362     assertTrue(Arrays.equals(array, Doubles.toArray(longs)));
363     assertTrue(Arrays.equals(array, Doubles.toArray(doubles)));
364   }
365 
testAsList_isAView()366   public void testAsList_isAView() {
367     double[] array = {(double) 0, (double) 1};
368     List<Double> list = Doubles.asList(array);
369     list.set(0, (double) 2);
370     assertTrue(Arrays.equals(new double[] {(double) 2, (double) 1}, array));
371     array[1] = (double) 3;
372     assertThat(list).has().exactly((double) 2, (double) 3).inOrder();
373   }
374 
testAsList_toArray_roundTrip()375   public void testAsList_toArray_roundTrip() {
376     double[] array = { (double) 0, (double) 1, (double) 2 };
377     List<Double> list = Doubles.asList(array);
378     double[] newArray = Doubles.toArray(list);
379 
380     // Make sure it returned a copy
381     list.set(0, (double) 4);
382     assertTrue(Arrays.equals(
383         new double[] { (double) 0, (double) 1, (double) 2 }, newArray));
384     newArray[1] = (double) 5;
385     assertEquals((double) 1, (double) list.get(1));
386   }
387 
388   // This test stems from a real bug found by andrewk
testAsList_subList_toArray_roundTrip()389   public void testAsList_subList_toArray_roundTrip() {
390     double[] array = { (double) 0, (double) 1, (double) 2, (double) 3 };
391     List<Double> list = Doubles.asList(array);
392     assertTrue(Arrays.equals(new double[] { (double) 1, (double) 2 },
393         Doubles.toArray(list.subList(1, 3))));
394     assertTrue(Arrays.equals(new double[] {},
395         Doubles.toArray(list.subList(2, 2))));
396   }
397 
testAsListEmpty()398   public void testAsListEmpty() {
399     assertSame(Collections.emptyList(), Doubles.asList(EMPTY));
400   }
401 
402   /**
403    * A reference implementation for {@code tryParse} that just catches the exception from
404    * {@link Double#valueOf}.
405    */
referenceTryParse(String input)406   private static Double referenceTryParse(String input) {
407     if (input.trim().length() < input.length()) {
408       return null;
409     }
410     try {
411       return Double.valueOf(input);
412     } catch (NumberFormatException e) {
413       return null;
414     }
415   }
416 
417   @GwtIncompatible("Doubles.tryParse")
checkTryParse(String input)418   private static void checkTryParse(String input) {
419     Double expected = referenceTryParse(input);
420     assertEquals(expected, Doubles.tryParse(input));
421     assertEquals(expected != null,
422         Doubles.FLOATING_POINT_PATTERN.matcher(input).matches());
423   }
424 
425   @GwtIncompatible("Doubles.tryParse")
checkTryParse(double expected, String input)426   private static void checkTryParse(double expected, String input) {
427     assertEquals(Double.valueOf(expected), Doubles.tryParse(input));
428     assertTrue(Doubles.FLOATING_POINT_PATTERN.matcher(input).matches());
429   }
430 
431   @GwtIncompatible("Doubles.tryParse")
testTryParseHex()432   public void testTryParseHex() {
433     for (String signChar : ImmutableList.of("", "+", "-")) {
434       for (String hexPrefix : ImmutableList.of("0x", "0X")) {
435         for (String iPart : ImmutableList.of("", "0", "1", "F", "f", "c4", "CE")) {
436           for (String fPart : ImmutableList.of("", ".", ".F", ".52", ".a")) {
437             for (String expMarker : ImmutableList.of("p", "P")) {
438               for (String exponent : ImmutableList.of("0", "-5", "+20", "52")) {
439                 for (String typePart : ImmutableList.of("", "D", "F", "d", "f")) {
440                   checkTryParse(
441                       signChar + hexPrefix + iPart + fPart + expMarker + exponent + typePart);
442                 }
443               }
444             }
445           }
446         }
447       }
448     }
449   }
450 
451   @GwtIncompatible("Doubles.tryParse")
testTryParseAllCodePoints()452   public void testTryParseAllCodePoints() {
453     // Exercise non-ASCII digit test cases and the like.
454     char[] tmp = new char[2];
455     for (int i = Character.MIN_CODE_POINT; i < Character.MAX_CODE_POINT; i++) {
456       Character.toChars(i, tmp, 0);
457       checkTryParse(String.copyValueOf(tmp, 0, Character.charCount(i)));
458     }
459   }
460 
461   @GwtIncompatible("Doubles.tryParse")
testTryParseOfToStringIsOriginal()462   public void testTryParseOfToStringIsOriginal() {
463     for (double d : NUMBERS) {
464       checkTryParse(d, Double.toString(d));
465     }
466   }
467 
468   @GwtIncompatible("Doubles.tryParse")
testTryParseOfToHexStringIsOriginal()469   public void testTryParseOfToHexStringIsOriginal() {
470     for (double d : NUMBERS) {
471       checkTryParse(d, Double.toHexString(d));
472     }
473   }
474 
475   @GwtIncompatible("Doubles.tryParse")
testTryParseNaN()476   public void testTryParseNaN() {
477     checkTryParse("NaN");
478     checkTryParse("+NaN");
479     checkTryParse("-NaN");
480   }
481 
482   @GwtIncompatible("Doubles.tryParse")
testTryParseInfinity()483   public void testTryParseInfinity() {
484     checkTryParse(Double.POSITIVE_INFINITY, "Infinity");
485     checkTryParse(Double.POSITIVE_INFINITY, "+Infinity");
486     checkTryParse(Double.NEGATIVE_INFINITY, "-Infinity");
487   }
488 
489   private static final String[] BAD_TRY_PARSE_INPUTS =
490     { "", "+-", "+-0", " 5", "32 ", " 55 ", "infinity", "POSITIVE_INFINITY", "0x9A", "0x9A.bE-5",
491       ".", ".e5", "NaNd", "InfinityF" };
492 
493   @GwtIncompatible("Doubles.tryParse")
testTryParseFailures()494   public void testTryParseFailures() {
495     for (String badInput : BAD_TRY_PARSE_INPUTS) {
496       assertFalse(Doubles.FLOATING_POINT_PATTERN.matcher(badInput).matches());
497       assertEquals(referenceTryParse(badInput), Doubles.tryParse(badInput));
498       assertNull(Doubles.tryParse(badInput));
499     }
500   }
501 
502   @GwtIncompatible("NullPointerTester")
testNulls()503   public void testNulls() {
504     new NullPointerTester().testAllPublicStaticMethods(Doubles.class);
505   }
506 
testStringConverter_convert()507   public void testStringConverter_convert() {
508     Converter<String, Double> converter = Doubles.stringConverter();
509     assertEquals((Double) 1.0, converter.convert("1.0"));
510     assertEquals((Double) 0.0, converter.convert("0.0"));
511     assertEquals((Double) (-1.0), converter.convert("-1.0"));
512     assertEquals((Double) 1.0, converter.convert("1"));
513     assertEquals((Double) 0.0, converter.convert("0"));
514     assertEquals((Double) (-1.0), converter.convert("-1"));
515     assertEquals((Double) 1e6, converter.convert("1e6"));
516     assertEquals((Double) 1e-6, converter.convert("1e-6"));
517   }
518 
testStringConverter_convertError()519   public void testStringConverter_convertError() {
520     try {
521       Doubles.stringConverter().convert("notanumber");
522       fail();
523     } catch (NumberFormatException expected) {
524     }
525   }
526 
testStringConverter_nullConversions()527   public void testStringConverter_nullConversions() {
528     assertNull(Doubles.stringConverter().convert(null));
529     assertNull(Doubles.stringConverter().reverse().convert(null));
530   }
531 
532   @GwtIncompatible("Double.toString returns different value in GWT.")
testStringConverter_reverse()533   public void testStringConverter_reverse() {
534     Converter<String, Double> converter = Doubles.stringConverter();
535     assertEquals("1.0", converter.reverse().convert(1.0));
536     assertEquals("0.0", converter.reverse().convert(0.0));
537     assertEquals("-1.0", converter.reverse().convert(-1.0));
538     assertEquals("1000000.0", converter.reverse().convert(1e6));
539     assertEquals("1.0E-6", converter.reverse().convert(1e-6));
540   }
541 
542   @GwtIncompatible("NullPointerTester")
testStringConverter_nullPointerTester()543   public void testStringConverter_nullPointerTester() throws Exception {
544     NullPointerTester tester = new NullPointerTester();
545     tester.testAllPublicInstanceMethods(Doubles.stringConverter());
546   }
547 }
548