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 import static java.math.BigInteger.ONE; 19 20 import com.google.common.annotations.GwtCompatible; 21 import com.google.common.annotations.GwtIncompatible; 22 import com.google.common.annotations.J2ktIncompatible; 23 import com.google.common.collect.testing.Helpers; 24 import com.google.common.testing.NullPointerTester; 25 import java.math.BigInteger; 26 import java.util.Arrays; 27 import java.util.Comparator; 28 import java.util.List; 29 import java.util.Random; 30 import junit.framework.TestCase; 31 32 /** 33 * Tests for UnsignedLongs 34 * 35 * @author Brian Milch 36 * @author Louis Wasserman 37 */ 38 @GwtCompatible(emulated = true) 39 public class UnsignedLongsTest extends TestCase { 40 private static final long LEAST = 0L; 41 private static final long GREATEST = 0xffffffffffffffffL; 42 testCompare()43 public void testCompare() { 44 // max value 45 assertThat(UnsignedLongs.compare(0, 0xffffffffffffffffL)).isLessThan(0); 46 assertThat(UnsignedLongs.compare(0xffffffffffffffffL, 0)).isGreaterThan(0); 47 48 // both with high bit set 49 assertThat(UnsignedLongs.compare(0xff1a618b7f65ea12L, 0xffffffffffffffffL)).isLessThan(0); 50 assertThat(UnsignedLongs.compare(0xffffffffffffffffL, 0xff1a618b7f65ea12L)).isGreaterThan(0); 51 52 // one with high bit set 53 assertThat(UnsignedLongs.compare(0x5a4316b8c153ac4dL, 0xff1a618b7f65ea12L)).isLessThan(0); 54 assertThat(UnsignedLongs.compare(0xff1a618b7f65ea12L, 0x5a4316b8c153ac4dL)).isGreaterThan(0); 55 56 // neither with high bit set 57 assertThat(UnsignedLongs.compare(0x5a4316b8c153ac4dL, 0x6cf78a4b139a4e2aL)).isLessThan(0); 58 assertThat(UnsignedLongs.compare(0x6cf78a4b139a4e2aL, 0x5a4316b8c153ac4dL)).isGreaterThan(0); 59 60 // same value 61 assertThat(UnsignedLongs.compare(0xff1a618b7f65ea12L, 0xff1a618b7f65ea12L)).isEqualTo(0); 62 } 63 testMax_noArgs()64 public void testMax_noArgs() { 65 try { 66 UnsignedLongs.max(); 67 fail(); 68 } catch (IllegalArgumentException expected) { 69 } 70 } 71 testMax()72 public void testMax() { 73 assertThat(UnsignedLongs.max(LEAST)).isEqualTo(LEAST); 74 assertThat(UnsignedLongs.max(GREATEST)).isEqualTo(GREATEST); 75 assertThat( 76 UnsignedLongs.max( 77 0x5a4316b8c153ac4dL, 8L, 100L, 0L, 0x6cf78a4b139a4e2aL, 0xff1a618b7f65ea12L)) 78 .isEqualTo(0xff1a618b7f65ea12L); 79 } 80 testMin_noArgs()81 public void testMin_noArgs() { 82 try { 83 UnsignedLongs.min(); 84 fail(); 85 } catch (IllegalArgumentException expected) { 86 } 87 } 88 testMin()89 public void testMin() { 90 assertThat(UnsignedLongs.min(LEAST)).isEqualTo(LEAST); 91 assertThat(UnsignedLongs.min(GREATEST)).isEqualTo(GREATEST); 92 assertThat( 93 UnsignedLongs.min( 94 0x5a4316b8c153ac4dL, 8L, 100L, 0L, 0x6cf78a4b139a4e2aL, 0xff1a618b7f65ea12L)) 95 .isEqualTo(0L); 96 } 97 testLexicographicalComparator()98 public void testLexicographicalComparator() { 99 List<long[]> ordered = 100 Arrays.asList( 101 new long[] {}, 102 new long[] {LEAST}, 103 new long[] {LEAST, LEAST}, 104 new long[] {LEAST, (long) 1}, 105 new long[] {(long) 1}, 106 new long[] {(long) 1, LEAST}, 107 new long[] {GREATEST, GREATEST - (long) 1}, 108 new long[] {GREATEST, GREATEST}, 109 new long[] {GREATEST, GREATEST, GREATEST}); 110 111 Comparator<long[]> comparator = UnsignedLongs.lexicographicalComparator(); 112 Helpers.testComparator(comparator, ordered); 113 } 114 testSort()115 public void testSort() { 116 testSort(new long[] {}, new long[] {}); 117 testSort(new long[] {2}, new long[] {2}); 118 testSort(new long[] {2, 1, 0}, new long[] {0, 1, 2}); 119 testSort(new long[] {2, GREATEST, 1, LEAST}, new long[] {LEAST, 1, 2, GREATEST}); 120 } 121 testSort(long[] input, long[] expected)122 static void testSort(long[] input, long[] expected) { 123 input = Arrays.copyOf(input, input.length); 124 UnsignedLongs.sort(input); 125 assertThat(input).isEqualTo(expected); 126 } 127 testSort(long[] input, int from, int to, long[] expected)128 static void testSort(long[] input, int from, int to, long[] expected) { 129 input = Arrays.copyOf(input, input.length); 130 UnsignedLongs.sort(input, from, to); 131 assertThat(input).isEqualTo(expected); 132 } 133 testSortIndexed()134 public void testSortIndexed() { 135 testSort(new long[] {}, 0, 0, new long[] {}); 136 testSort(new long[] {2}, 0, 1, new long[] {2}); 137 testSort(new long[] {2, 1, 0}, 0, 2, new long[] {1, 2, 0}); 138 testSort(new long[] {2, GREATEST, 1, LEAST}, 1, 4, new long[] {2, LEAST, 1, GREATEST}); 139 } 140 testSortDescending()141 public void testSortDescending() { 142 testSortDescending(new long[] {}, new long[] {}); 143 testSortDescending(new long[] {1}, new long[] {1}); 144 testSortDescending(new long[] {1, 2}, new long[] {2, 1}); 145 testSortDescending(new long[] {1, 3, 1}, new long[] {3, 1, 1}); 146 testSortDescending( 147 new long[] {GREATEST - 1, 1, GREATEST - 2, 2}, 148 new long[] {GREATEST - 1, GREATEST - 2, 2, 1}); 149 } 150 testSortDescending(long[] input, long[] expectedOutput)151 private static void testSortDescending(long[] input, long[] expectedOutput) { 152 input = Arrays.copyOf(input, input.length); 153 UnsignedLongs.sortDescending(input); 154 assertThat(input).isEqualTo(expectedOutput); 155 } 156 testSortDescending( long[] input, int fromIndex, int toIndex, long[] expectedOutput)157 private static void testSortDescending( 158 long[] input, int fromIndex, int toIndex, long[] expectedOutput) { 159 input = Arrays.copyOf(input, input.length); 160 UnsignedLongs.sortDescending(input, fromIndex, toIndex); 161 assertThat(input).isEqualTo(expectedOutput); 162 } 163 testSortDescendingIndexed()164 public void testSortDescendingIndexed() { 165 testSortDescending(new long[] {}, 0, 0, new long[] {}); 166 testSortDescending(new long[] {1}, 0, 1, new long[] {1}); 167 testSortDescending(new long[] {1, 2}, 0, 2, new long[] {2, 1}); 168 testSortDescending(new long[] {1, 3, 1}, 0, 2, new long[] {3, 1, 1}); 169 testSortDescending(new long[] {1, 3, 1}, 0, 1, new long[] {1, 3, 1}); 170 testSortDescending( 171 new long[] {GREATEST - 1, 1, GREATEST - 2, 2}, 172 1, 173 3, 174 new long[] {GREATEST - 1, GREATEST - 2, 1, 2}); 175 } 176 testDivide()177 public void testDivide() { 178 assertThat(UnsignedLongs.divide(14, 5)).isEqualTo(2); 179 assertThat(UnsignedLongs.divide(0, 50)).isEqualTo(0); 180 assertThat(UnsignedLongs.divide(0xfffffffffffffffeL, 0xfffffffffffffffdL)).isEqualTo(1); 181 assertThat(UnsignedLongs.divide(0xfffffffffffffffdL, 0xfffffffffffffffeL)).isEqualTo(0); 182 assertThat(UnsignedLongs.divide(0xfffffffffffffffeL, 65535)).isEqualTo(281479271743488L); 183 assertThat(UnsignedLongs.divide(0xfffffffffffffffeL, 2)).isEqualTo(0x7fffffffffffffffL); 184 assertThat(UnsignedLongs.divide(0xfffffffffffffffeL, 5)).isEqualTo(3689348814741910322L); 185 } 186 testRemainder()187 public void testRemainder() { 188 assertThat(UnsignedLongs.remainder(14, 5)).isEqualTo(4); 189 assertThat(UnsignedLongs.remainder(0, 50)).isEqualTo(0); 190 assertThat(UnsignedLongs.remainder(0xfffffffffffffffeL, 0xfffffffffffffffdL)).isEqualTo(1); 191 assertThat(UnsignedLongs.remainder(0xfffffffffffffffdL, 0xfffffffffffffffeL)) 192 .isEqualTo(0xfffffffffffffffdL); 193 assertThat(UnsignedLongs.remainder(0xfffffffffffffffeL, 65535)).isEqualTo(65534L); 194 assertThat(UnsignedLongs.remainder(0xfffffffffffffffeL, 2)).isEqualTo(0); 195 assertThat(UnsignedLongs.remainder(0xfffffffffffffffeL, 5)).isEqualTo(4); 196 } 197 198 @J2ktIncompatible 199 @GwtIncompatible // Too slow in GWT (~3min fully optimized) testDivideRemainderEuclideanProperty()200 public void testDivideRemainderEuclideanProperty() { 201 // Use a seed so that the test is deterministic: 202 Random r = new Random(0L); 203 for (int i = 0; i < 1000000; i++) { 204 long dividend = r.nextLong(); 205 long divisor = r.nextLong(); 206 // Test that the Euclidean property is preserved: 207 assertThat( 208 dividend 209 - (divisor * UnsignedLongs.divide(dividend, divisor) 210 + UnsignedLongs.remainder(dividend, divisor))) 211 .isEqualTo(0); 212 } 213 } 214 testParseLong()215 public void testParseLong() { 216 assertThat(UnsignedLongs.parseUnsignedLong("18446744073709551615")) 217 .isEqualTo(0xffffffffffffffffL); 218 assertThat(UnsignedLongs.parseUnsignedLong("9223372036854775807")) 219 .isEqualTo(0x7fffffffffffffffL); 220 assertThat(UnsignedLongs.parseUnsignedLong("18382112080831834642")) 221 .isEqualTo(0xff1a618b7f65ea12L); 222 assertThat(UnsignedLongs.parseUnsignedLong("6504067269626408013")) 223 .isEqualTo(0x5a4316b8c153ac4dL); 224 assertThat(UnsignedLongs.parseUnsignedLong("7851896530399809066")) 225 .isEqualTo(0x6cf78a4b139a4e2aL); 226 } 227 testParseLongEmptyString()228 public void testParseLongEmptyString() { 229 try { 230 UnsignedLongs.parseUnsignedLong(""); 231 fail("NumberFormatException should have been raised."); 232 } catch (NumberFormatException expected) { 233 } 234 } 235 testParseLongFails()236 public void testParseLongFails() { 237 try { 238 // One more than maximum value 239 UnsignedLongs.parseUnsignedLong("18446744073709551616"); 240 fail(); 241 } catch (NumberFormatException expected) { 242 } 243 } 244 testDecodeLong()245 public void testDecodeLong() { 246 assertThat(UnsignedLongs.decode("0xffffffffffffffff")).isEqualTo(0xffffffffffffffffL); 247 assertThat(UnsignedLongs.decode("01234567")).isEqualTo(01234567); // octal 248 assertThat(UnsignedLongs.decode("#1234567890abcdef")).isEqualTo(0x1234567890abcdefL); 249 assertThat(UnsignedLongs.decode("987654321012345678")).isEqualTo(987654321012345678L); 250 assertThat(UnsignedLongs.decode("0x135791357913579")).isEqualTo(0x135791357913579L); 251 assertThat(UnsignedLongs.decode("0X135791357913579")).isEqualTo(0x135791357913579L); 252 assertThat(UnsignedLongs.decode("0")).isEqualTo(0L); 253 } 254 testDecodeLongFails()255 public void testDecodeLongFails() { 256 try { 257 // One more than maximum value 258 UnsignedLongs.decode("0xfffffffffffffffff"); 259 fail(); 260 } catch (NumberFormatException expected) { 261 } 262 263 try { 264 UnsignedLongs.decode("-5"); 265 fail(); 266 } catch (NumberFormatException expected) { 267 } 268 269 try { 270 UnsignedLongs.decode("-0x5"); 271 fail(); 272 } catch (NumberFormatException expected) { 273 } 274 275 try { 276 UnsignedLongs.decode("-05"); 277 fail(); 278 } catch (NumberFormatException expected) { 279 } 280 } 281 testParseLongWithRadix()282 public void testParseLongWithRadix() { 283 assertThat(UnsignedLongs.parseUnsignedLong("ffffffffffffffff", 16)) 284 .isEqualTo(0xffffffffffffffffL); 285 assertThat(UnsignedLongs.parseUnsignedLong("1234567890abcdef", 16)) 286 .isEqualTo(0x1234567890abcdefL); 287 } 288 testParseLongWithRadixLimits()289 public void testParseLongWithRadixLimits() { 290 BigInteger max = BigInteger.ZERO.setBit(64).subtract(ONE); 291 // loops through all legal radix values. 292 for (int radix = Character.MIN_RADIX; radix <= Character.MAX_RADIX; radix++) { 293 // tests can successfully parse a number string with this radix. 294 String maxAsString = max.toString(radix); 295 assertThat(UnsignedLongs.parseUnsignedLong(maxAsString, radix)).isEqualTo(max.longValue()); 296 297 try { 298 // tests that we get exception where an overflow would occur. 299 BigInteger overflow = max.add(ONE); 300 String overflowAsString = overflow.toString(radix); 301 UnsignedLongs.parseUnsignedLong(overflowAsString, radix); 302 fail(); 303 } catch (NumberFormatException expected) { 304 } 305 } 306 307 try { 308 UnsignedLongs.parseUnsignedLong("1234567890abcdef1", 16); 309 fail(); 310 } catch (NumberFormatException expected) { 311 } 312 } 313 testParseLongThrowsExceptionForInvalidRadix()314 public void testParseLongThrowsExceptionForInvalidRadix() { 315 // Valid radix values are Character.MIN_RADIX to Character.MAX_RADIX, inclusive. 316 try { 317 UnsignedLongs.parseUnsignedLong("0", Character.MIN_RADIX - 1); 318 fail(); 319 } catch (NumberFormatException expected) { 320 } 321 322 try { 323 UnsignedLongs.parseUnsignedLong("0", Character.MAX_RADIX + 1); 324 fail(); 325 } catch (NumberFormatException expected) { 326 } 327 328 // The radix is used as an array index, so try a negative value. 329 try { 330 UnsignedLongs.parseUnsignedLong("0", -1); 331 fail(); 332 } catch (NumberFormatException expected) { 333 } 334 } 335 336 @J2ktIncompatible // TODO(b/285562794): Wrong result for j2kt testToString()337 public void testToString() { 338 String[] tests = { 339 "0", 340 "ffffffffffffffff", 341 "7fffffffffffffff", 342 "ff1a618b7f65ea12", 343 "5a4316b8c153ac4d", 344 "6cf78a4b139a4e2a" 345 }; 346 int[] bases = {2, 5, 7, 8, 10, 16}; 347 for (int base : bases) { 348 for (String x : tests) { 349 BigInteger xValue = new BigInteger(x, 16); 350 long xLong = xValue.longValue(); // signed 351 assertThat(UnsignedLongs.toString(xLong, base)).isEqualTo(xValue.toString(base)); 352 } 353 } 354 } 355 testJoin()356 public void testJoin() { 357 assertThat(UnsignedLongs.join(",")).isEmpty(); 358 assertThat(UnsignedLongs.join(",", 1)).isEqualTo("1"); 359 assertThat(UnsignedLongs.join(",", 1, 2)).isEqualTo("1,2"); 360 assertThat(UnsignedLongs.join(",", -1, Long.MIN_VALUE)) 361 .isEqualTo("18446744073709551615,9223372036854775808"); 362 assertThat(UnsignedLongs.join("", 1, 2, 3)).isEqualTo("123"); 363 assertThat(UnsignedLongs.join("", -1, Long.MIN_VALUE)) 364 .isEqualTo("184467440737095516159223372036854775808"); 365 } 366 367 @J2ktIncompatible 368 @GwtIncompatible // NullPointerTester testNulls()369 public void testNulls() { 370 new NullPointerTester().testAllPublicStaticMethods(UnsignedLongs.class); 371 } 372 } 373