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