1 /* 2 * Copyright (C) 2011 The Guava Authors 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 5 * in compliance with the License. You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software distributed under the 10 * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 11 * express or implied. See the License for the specific language governing permissions and 12 * limitations under the License. 13 */ 14 15 package com.google.common.primitives; 16 17 import static com.google.common.truth.Truth.assertThat; 18 19 import com.google.common.annotations.GwtCompatible; 20 import com.google.common.annotations.GwtIncompatible; 21 import com.google.common.annotations.J2ktIncompatible; 22 import com.google.common.collect.testing.Helpers; 23 import com.google.common.testing.NullPointerTester; 24 import java.util.Arrays; 25 import java.util.Comparator; 26 import java.util.List; 27 import java.util.Random; 28 import junit.framework.TestCase; 29 30 /** 31 * Tests for UnsignedInts 32 * 33 * @author Louis Wasserman 34 */ 35 @GwtCompatible(emulated = true) 36 public class UnsignedIntsTest extends TestCase { 37 private static final long[] UNSIGNED_INTS = { 38 0L, 39 1L, 40 2L, 41 3L, 42 0x12345678L, 43 0x5a4316b8L, 44 0x6cf78a4bL, 45 0xff1a618bL, 46 0xfffffffdL, 47 0xfffffffeL, 48 0xffffffffL 49 }; 50 51 private static final int LEAST = (int) 0L; 52 private static final int GREATEST = (int) 0xffffffffL; 53 testCheckedCast()54 public void testCheckedCast() { 55 for (long value : UNSIGNED_INTS) { 56 assertThat(UnsignedInts.toLong(UnsignedInts.checkedCast(value))).isEqualTo(value); 57 } 58 assertCastFails(1L << 32); 59 assertCastFails(-1L); 60 assertCastFails(Long.MAX_VALUE); 61 assertCastFails(Long.MIN_VALUE); 62 } 63 assertCastFails(long value)64 private static void assertCastFails(long value) { 65 try { 66 UnsignedInts.checkedCast(value); 67 fail("Cast to int should have failed: " + value); 68 } catch (IllegalArgumentException ex) { 69 assertThat(ex).hasMessageThat().contains(String.valueOf(value)); 70 } 71 } 72 testSaturatedCast()73 public void testSaturatedCast() { 74 for (long value : UNSIGNED_INTS) { 75 assertThat(UnsignedInts.toLong(UnsignedInts.saturatedCast(value))).isEqualTo(value); 76 } 77 assertThat(UnsignedInts.saturatedCast(1L << 32)).isEqualTo(GREATEST); 78 assertThat(UnsignedInts.saturatedCast(-1L)).isEqualTo(LEAST); 79 assertThat(UnsignedInts.saturatedCast(Long.MAX_VALUE)).isEqualTo(GREATEST); 80 assertThat(UnsignedInts.saturatedCast(Long.MIN_VALUE)).isEqualTo(LEAST); 81 } 82 testToLong()83 public void testToLong() { 84 for (long a : UNSIGNED_INTS) { 85 assertThat(UnsignedInts.toLong((int) a)).isEqualTo(a); 86 } 87 } 88 testCompare()89 public void testCompare() { 90 for (long a : UNSIGNED_INTS) { 91 for (long b : UNSIGNED_INTS) { 92 int cmpAsLongs = Longs.compare(a, b); 93 int cmpAsUInt = UnsignedInts.compare((int) a, (int) b); 94 assertThat(Integer.signum(cmpAsUInt)).isEqualTo(Integer.signum(cmpAsLongs)); 95 } 96 } 97 } 98 testMax_noArgs()99 public void testMax_noArgs() { 100 try { 101 UnsignedInts.max(); 102 fail(); 103 } catch (IllegalArgumentException expected) { 104 } 105 } 106 testMax()107 public void testMax() { 108 assertThat(UnsignedInts.max(LEAST)).isEqualTo(LEAST); 109 assertThat(UnsignedInts.max(GREATEST)).isEqualTo(GREATEST); 110 assertThat( 111 UnsignedInts.max( 112 (int) 8L, 113 (int) 6L, 114 (int) 7L, 115 (int) 0x12345678L, 116 (int) 0x5a4316b8L, 117 (int) 0xff1a618bL, 118 (int) 0L)) 119 .isEqualTo((int) 0xff1a618bL); 120 } 121 testMin_noArgs()122 public void testMin_noArgs() { 123 try { 124 UnsignedInts.min(); 125 fail(); 126 } catch (IllegalArgumentException expected) { 127 } 128 } 129 testMin()130 public void testMin() { 131 assertThat(UnsignedInts.min(LEAST)).isEqualTo(LEAST); 132 assertThat(UnsignedInts.min(GREATEST)).isEqualTo(GREATEST); 133 assertThat( 134 UnsignedInts.min( 135 (int) 8L, 136 (int) 6L, 137 (int) 7L, 138 (int) 0x12345678L, 139 (int) 0x5a4316b8L, 140 (int) 0xff1a618bL, 141 (int) 0L)) 142 .isEqualTo((int) 0L); 143 } 144 testLexicographicalComparator()145 public void testLexicographicalComparator() { 146 List<int[]> ordered = 147 Arrays.asList( 148 new int[] {}, 149 new int[] {LEAST}, 150 new int[] {LEAST, LEAST}, 151 new int[] {LEAST, (int) 1L}, 152 new int[] {(int) 1L}, 153 new int[] {(int) 1L, LEAST}, 154 new int[] {GREATEST, (GREATEST - (int) 1L)}, 155 new int[] {GREATEST, GREATEST}, 156 new int[] {GREATEST, GREATEST, GREATEST}); 157 158 Comparator<int[]> comparator = UnsignedInts.lexicographicalComparator(); 159 Helpers.testComparator(comparator, ordered); 160 } 161 testSort()162 public void testSort() { 163 testSort(new int[] {}, new int[] {}); 164 testSort(new int[] {2}, new int[] {2}); 165 testSort(new int[] {2, 1, 0}, new int[] {0, 1, 2}); 166 testSort(new int[] {2, GREATEST, 1, LEAST}, new int[] {LEAST, 1, 2, GREATEST}); 167 } 168 testSort(int[] input, int[] expected)169 static void testSort(int[] input, int[] expected) { 170 input = Arrays.copyOf(input, input.length); 171 UnsignedInts.sort(input); 172 assertThat(input).isEqualTo(expected); 173 } 174 testSort(int[] input, int from, int to, int[] expected)175 static void testSort(int[] input, int from, int to, int[] expected) { 176 input = Arrays.copyOf(input, input.length); 177 UnsignedInts.sort(input, from, to); 178 assertThat(input).isEqualTo(expected); 179 } 180 testSortIndexed()181 public void testSortIndexed() { 182 testSort(new int[] {}, 0, 0, new int[] {}); 183 testSort(new int[] {2}, 0, 1, new int[] {2}); 184 testSort(new int[] {2, 1, 0}, 0, 2, new int[] {1, 2, 0}); 185 testSort(new int[] {2, GREATEST, 1, LEAST}, 1, 4, new int[] {2, LEAST, 1, GREATEST}); 186 } 187 testSortDescending()188 public void testSortDescending() { 189 testSortDescending(new int[] {}, new int[] {}); 190 testSortDescending(new int[] {1}, new int[] {1}); 191 testSortDescending(new int[] {1, 2}, new int[] {2, 1}); 192 testSortDescending(new int[] {1, 3, 1}, new int[] {3, 1, 1}); 193 testSortDescending( 194 new int[] {GREATEST - 1, 1, GREATEST - 2, 2}, new int[] {GREATEST - 1, GREATEST - 2, 2, 1}); 195 } 196 testSortDescending(int[] input, int[] expectedOutput)197 private static void testSortDescending(int[] input, int[] expectedOutput) { 198 input = Arrays.copyOf(input, input.length); 199 UnsignedInts.sortDescending(input); 200 assertThat(input).isEqualTo(expectedOutput); 201 } 202 testSortDescending( int[] input, int fromIndex, int toIndex, int[] expectedOutput)203 private static void testSortDescending( 204 int[] input, int fromIndex, int toIndex, int[] expectedOutput) { 205 input = Arrays.copyOf(input, input.length); 206 UnsignedInts.sortDescending(input, fromIndex, toIndex); 207 assertThat(input).isEqualTo(expectedOutput); 208 } 209 testSortDescendingIndexed()210 public void testSortDescendingIndexed() { 211 testSortDescending(new int[] {}, 0, 0, new int[] {}); 212 testSortDescending(new int[] {1}, 0, 1, new int[] {1}); 213 testSortDescending(new int[] {1, 2}, 0, 2, new int[] {2, 1}); 214 testSortDescending(new int[] {1, 3, 1}, 0, 2, new int[] {3, 1, 1}); 215 testSortDescending(new int[] {1, 3, 1}, 0, 1, new int[] {1, 3, 1}); 216 testSortDescending( 217 new int[] {GREATEST - 1, 1, GREATEST - 2, 2}, 218 1, 219 3, 220 new int[] {GREATEST - 1, GREATEST - 2, 1, 2}); 221 } 222 testDivide()223 public void testDivide() { 224 for (long a : UNSIGNED_INTS) { 225 for (long b : UNSIGNED_INTS) { 226 try { 227 assertThat(UnsignedInts.divide((int) a, (int) b)).isEqualTo((int) (a / b)); 228 assertThat(b).isNotEqualTo(0); 229 } catch (ArithmeticException e) { 230 assertThat(b).isEqualTo(0); 231 } 232 } 233 } 234 } 235 testRemainder()236 public void testRemainder() { 237 for (long a : UNSIGNED_INTS) { 238 for (long b : UNSIGNED_INTS) { 239 try { 240 assertThat(UnsignedInts.remainder((int) a, (int) b)).isEqualTo((int) (a % b)); 241 assertThat(b).isNotEqualTo(0); 242 } catch (ArithmeticException e) { 243 assertThat(b).isEqualTo(0); 244 } 245 } 246 } 247 } 248 249 @J2ktIncompatible 250 @GwtIncompatible // Too slow in GWT (~3min fully optimized) testDivideRemainderEuclideanProperty()251 public void testDivideRemainderEuclideanProperty() { 252 // Use a seed so that the test is deterministic: 253 Random r = new Random(0L); 254 for (int i = 0; i < 1000000; i++) { 255 int dividend = r.nextInt(); 256 int divisor = r.nextInt(); 257 // Test that the Euclidean property is preserved: 258 assertThat( 259 dividend 260 - (divisor * UnsignedInts.divide(dividend, divisor) 261 + UnsignedInts.remainder(dividend, divisor))) 262 .isEqualTo(0); 263 } 264 } 265 testParseInt()266 public void testParseInt() { 267 for (long a : UNSIGNED_INTS) { 268 assertThat(UnsignedInts.parseUnsignedInt(Long.toString(a))).isEqualTo((int) a); 269 } 270 } 271 testParseIntFail()272 public void testParseIntFail() { 273 try { 274 UnsignedInts.parseUnsignedInt(Long.toString(1L << 32)); 275 fail("Expected NumberFormatException"); 276 } catch (NumberFormatException expected) { 277 } 278 } 279 testParseIntWithRadix()280 public void testParseIntWithRadix() { 281 for (long a : UNSIGNED_INTS) { 282 for (int radix = Character.MIN_RADIX; radix <= Character.MAX_RADIX; radix++) { 283 assertThat(UnsignedInts.parseUnsignedInt(Long.toString(a, radix), radix)) 284 .isEqualTo((int) a); 285 } 286 } 287 } 288 testParseIntWithRadixLimits()289 public void testParseIntWithRadixLimits() { 290 // loops through all legal radix values. 291 for (int radix = Character.MIN_RADIX; radix <= Character.MAX_RADIX; radix++) { 292 // tests can successfully parse a number string with this radix. 293 String maxAsString = Long.toString((1L << 32) - 1, radix); 294 assertThat(UnsignedInts.parseUnsignedInt(maxAsString, radix)).isEqualTo(-1); 295 296 try { 297 // tests that we get exception where an overflow would occur. 298 long overflow = 1L << 32; 299 String overflowAsString = Long.toString(overflow, radix); 300 UnsignedInts.parseUnsignedInt(overflowAsString, radix); 301 fail(); 302 } catch (NumberFormatException expected) { 303 } 304 } 305 } 306 307 @J2ktIncompatible // TODO(b/285538920): Exception mismatch testParseIntThrowsExceptionForInvalidRadix()308 public void testParseIntThrowsExceptionForInvalidRadix() { 309 // Valid radix values are Character.MIN_RADIX to Character.MAX_RADIX, 310 // inclusive. 311 try { 312 UnsignedInts.parseUnsignedInt("0", Character.MIN_RADIX - 1); 313 fail(); 314 } catch (NumberFormatException expected) { 315 } 316 317 try { 318 UnsignedInts.parseUnsignedInt("0", Character.MAX_RADIX + 1); 319 fail(); 320 } catch (NumberFormatException expected) { 321 } 322 323 // The radix is used as an array index, so try a negative value. 324 try { 325 UnsignedInts.parseUnsignedInt("0", -1); 326 fail(); 327 } catch (NumberFormatException expected) { 328 } 329 } 330 testDecodeInt()331 public void testDecodeInt() { 332 assertThat(UnsignedInts.decode("0xffffffff")).isEqualTo(0xffffffff); 333 assertThat(UnsignedInts.decode("01234567")).isEqualTo(01234567); // octal 334 assertThat(UnsignedInts.decode("#12345678")).isEqualTo(0x12345678); 335 assertThat(UnsignedInts.decode("76543210")).isEqualTo(76543210); 336 assertThat(UnsignedInts.decode("0x13579135")).isEqualTo(0x13579135); 337 assertThat(UnsignedInts.decode("0X13579135")).isEqualTo(0x13579135); 338 assertThat(UnsignedInts.decode("0")).isEqualTo(0); 339 } 340 testDecodeIntFails()341 public void testDecodeIntFails() { 342 try { 343 // One more than maximum value 344 UnsignedInts.decode("0xfffffffff"); 345 fail(); 346 } catch (NumberFormatException expected) { 347 } 348 349 try { 350 UnsignedInts.decode("-5"); 351 fail(); 352 } catch (NumberFormatException expected) { 353 } 354 355 try { 356 UnsignedInts.decode("-0x5"); 357 fail(); 358 } catch (NumberFormatException expected) { 359 } 360 361 try { 362 UnsignedInts.decode("-05"); 363 fail(); 364 } catch (NumberFormatException expected) { 365 } 366 } 367 testToString()368 public void testToString() { 369 int[] bases = {2, 5, 7, 8, 10, 16}; 370 for (long a : UNSIGNED_INTS) { 371 for (int base : bases) { 372 assertThat(Long.toString(a, base)).isEqualTo(UnsignedInts.toString((int) a, base)); 373 } 374 } 375 } 376 testJoin()377 public void testJoin() { 378 assertThat(join()).isEmpty(); 379 assertThat(join(1)).isEqualTo("1"); 380 assertThat(join(1, 2)).isEqualTo("1,2"); 381 assertThat(join(-1, Integer.MIN_VALUE)).isEqualTo("4294967295,2147483648"); 382 383 assertThat(UnsignedInts.join("", 1, 2, 3)).isEqualTo("123"); 384 } 385 join(int... values)386 private static String join(int... values) { 387 return UnsignedInts.join(",", values); 388 } 389 390 @J2ktIncompatible 391 @GwtIncompatible // NullPointerTester testNulls()392 public void testNulls() { 393 new NullPointerTester().testAllPublicStaticMethods(UnsignedInts.class); 394 } 395 } 396