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 @GwtIncompatible // Too slow in GWT (~3min fully optimized) testDivideRemainderEuclideanProperty()199 public void testDivideRemainderEuclideanProperty() { 200 // Use a seed so that the test is deterministic: 201 Random r = new Random(0L); 202 for (int i = 0; i < 1000000; i++) { 203 long dividend = r.nextLong(); 204 long divisor = r.nextLong(); 205 // Test that the Euclidean property is preserved: 206 assertThat( 207 dividend 208 - (divisor * UnsignedLongs.divide(dividend, divisor) 209 + UnsignedLongs.remainder(dividend, divisor))) 210 .isEqualTo(0); 211 } 212 } 213 testParseLong()214 public void testParseLong() { 215 assertThat(UnsignedLongs.parseUnsignedLong("18446744073709551615")) 216 .isEqualTo(0xffffffffffffffffL); 217 assertThat(UnsignedLongs.parseUnsignedLong("9223372036854775807")) 218 .isEqualTo(0x7fffffffffffffffL); 219 assertThat(UnsignedLongs.parseUnsignedLong("18382112080831834642")) 220 .isEqualTo(0xff1a618b7f65ea12L); 221 assertThat(UnsignedLongs.parseUnsignedLong("6504067269626408013")) 222 .isEqualTo(0x5a4316b8c153ac4dL); 223 assertThat(UnsignedLongs.parseUnsignedLong("7851896530399809066")) 224 .isEqualTo(0x6cf78a4b139a4e2aL); 225 } 226 testParseLongEmptyString()227 public void testParseLongEmptyString() { 228 try { 229 UnsignedLongs.parseUnsignedLong(""); 230 fail("NumberFormatException should have been raised."); 231 } catch (NumberFormatException expected) { 232 } 233 } 234 testParseLongFails()235 public void testParseLongFails() { 236 try { 237 // One more than maximum value 238 UnsignedLongs.parseUnsignedLong("18446744073709551616"); 239 fail(); 240 } catch (NumberFormatException expected) { 241 } 242 } 243 testDecodeLong()244 public void testDecodeLong() { 245 assertThat(UnsignedLongs.decode("0xffffffffffffffff")).isEqualTo(0xffffffffffffffffL); 246 assertThat(UnsignedLongs.decode("01234567")).isEqualTo(01234567); // octal 247 assertThat(UnsignedLongs.decode("#1234567890abcdef")).isEqualTo(0x1234567890abcdefL); 248 assertThat(UnsignedLongs.decode("987654321012345678")).isEqualTo(987654321012345678L); 249 assertThat(UnsignedLongs.decode("0x135791357913579")).isEqualTo(0x135791357913579L); 250 assertThat(UnsignedLongs.decode("0X135791357913579")).isEqualTo(0x135791357913579L); 251 assertThat(UnsignedLongs.decode("0")).isEqualTo(0L); 252 } 253 testDecodeLongFails()254 public void testDecodeLongFails() { 255 try { 256 // One more than maximum value 257 UnsignedLongs.decode("0xfffffffffffffffff"); 258 fail(); 259 } catch (NumberFormatException expected) { 260 } 261 262 try { 263 UnsignedLongs.decode("-5"); 264 fail(); 265 } catch (NumberFormatException expected) { 266 } 267 268 try { 269 UnsignedLongs.decode("-0x5"); 270 fail(); 271 } catch (NumberFormatException expected) { 272 } 273 274 try { 275 UnsignedLongs.decode("-05"); 276 fail(); 277 } catch (NumberFormatException expected) { 278 } 279 } 280 testParseLongWithRadix()281 public void testParseLongWithRadix() { 282 assertThat(UnsignedLongs.parseUnsignedLong("ffffffffffffffff", 16)) 283 .isEqualTo(0xffffffffffffffffL); 284 assertThat(UnsignedLongs.parseUnsignedLong("1234567890abcdef", 16)) 285 .isEqualTo(0x1234567890abcdefL); 286 } 287 testParseLongWithRadixLimits()288 public void testParseLongWithRadixLimits() { 289 BigInteger max = BigInteger.ZERO.setBit(64).subtract(ONE); 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 = max.toString(radix); 294 assertThat(UnsignedLongs.parseUnsignedLong(maxAsString, radix)).isEqualTo(max.longValue()); 295 296 try { 297 // tests that we get exception where an overflow would occur. 298 BigInteger overflow = max.add(ONE); 299 String overflowAsString = overflow.toString(radix); 300 UnsignedLongs.parseUnsignedLong(overflowAsString, radix); 301 fail(); 302 } catch (NumberFormatException expected) { 303 } 304 } 305 306 try { 307 UnsignedLongs.parseUnsignedLong("1234567890abcdef1", 16); 308 fail(); 309 } catch (NumberFormatException expected) { 310 } 311 } 312 testParseLongThrowsExceptionForInvalidRadix()313 public void testParseLongThrowsExceptionForInvalidRadix() { 314 // Valid radix values are Character.MIN_RADIX to Character.MAX_RADIX, inclusive. 315 try { 316 UnsignedLongs.parseUnsignedLong("0", Character.MIN_RADIX - 1); 317 fail(); 318 } catch (NumberFormatException expected) { 319 } 320 321 try { 322 UnsignedLongs.parseUnsignedLong("0", Character.MAX_RADIX + 1); 323 fail(); 324 } catch (NumberFormatException expected) { 325 } 326 327 // The radix is used as an array index, so try a negative value. 328 try { 329 UnsignedLongs.parseUnsignedLong("0", -1); 330 fail(); 331 } catch (NumberFormatException expected) { 332 } 333 } 334 testToString()335 public void testToString() { 336 String[] tests = { 337 "0", 338 "ffffffffffffffff", 339 "7fffffffffffffff", 340 "ff1a618b7f65ea12", 341 "5a4316b8c153ac4d", 342 "6cf78a4b139a4e2a" 343 }; 344 int[] bases = {2, 5, 7, 8, 10, 16}; 345 for (int base : bases) { 346 for (String x : tests) { 347 BigInteger xValue = new BigInteger(x, 16); 348 long xLong = xValue.longValue(); // signed 349 assertThat(UnsignedLongs.toString(xLong, base)).isEqualTo(xValue.toString(base)); 350 } 351 } 352 } 353 testJoin()354 public void testJoin() { 355 assertThat(UnsignedLongs.join(",")).isEmpty(); 356 assertThat(UnsignedLongs.join(",", 1)).isEqualTo("1"); 357 assertThat(UnsignedLongs.join(",", 1, 2)).isEqualTo("1,2"); 358 assertThat(UnsignedLongs.join(",", -1, Long.MIN_VALUE)) 359 .isEqualTo("18446744073709551615,9223372036854775808"); 360 assertThat(UnsignedLongs.join("", 1, 2, 3)).isEqualTo("123"); 361 assertThat(UnsignedLongs.join("", -1, Long.MIN_VALUE)) 362 .isEqualTo("184467440737095516159223372036854775808"); 363 } 364 365 @J2ktIncompatible 366 @GwtIncompatible // NullPointerTester testNulls()367 public void testNulls() { 368 new NullPointerTester().testAllPublicStaticMethods(UnsignedLongs.class); 369 } 370 } 371