1 /*- 2 * See the file LICENSE for redistribution information. 3 * 4 * Copyright (c) 2002, 2014 Oracle and/or its affiliates. All rights reserved. 5 * 6 */ 7 8 package com.sleepycat.bind.tuple.test; 9 10 import static org.junit.Assert.fail; 11 12 import java.math.BigDecimal; 13 import java.math.BigInteger; 14 15 import org.junit.After; 16 import org.junit.Before; 17 import org.junit.Test; 18 19 import com.sleepycat.bind.tuple.TupleOutput; 20 21 /** 22 * @author Mark Hayes 23 */ 24 public class TupleOrderingTest { 25 26 private TupleOutput out; 27 private byte[] prevBuf; 28 29 @Before setUp()30 public void setUp() { 31 32 out = new TupleOutput(); 33 prevBuf = null; 34 } 35 36 @After tearDown()37 public void tearDown() { 38 39 /* Ensure that GC can cleanup. */ 40 out = null; 41 prevBuf = null; 42 } 43 44 /** 45 * Each tuple written must be strictly less than (by comparison of bytes) 46 * the tuple written just before it. The check() method compares bytes 47 * just written to those written before the previous call to check(). 48 */ check()49 private void check() { 50 51 check(-1); 52 } 53 check(int dataIndex)54 private void check(int dataIndex) { 55 56 byte[] buf = new byte[out.size()]; 57 System.arraycopy(out.getBufferBytes(), out.getBufferOffset(), 58 buf, 0, buf.length); 59 if (prevBuf != null) { 60 int errOffset = -1; 61 int len = Math.min(prevBuf.length, buf.length); 62 boolean areEqual = true; 63 for (int i = 0; i < len; i += 1) { 64 int val1 = prevBuf[i] & 0xFF; 65 int val2 = buf[i] & 0xFF; 66 if (val1 < val2) { 67 areEqual = false; 68 break; 69 } else if (val1 > val2) { 70 errOffset = i; 71 break; 72 } 73 } 74 if (areEqual) { 75 if (prevBuf.length < buf.length) { 76 areEqual = false; 77 } else if (prevBuf.length > buf.length) { 78 areEqual = false; 79 errOffset = buf.length + 1; 80 } 81 } 82 if (errOffset != -1 || areEqual) { 83 StringBuilder msg = new StringBuilder(); 84 if (errOffset != -1) { 85 msg.append("Left >= right at byte offset " + errOffset); 86 } else if (areEqual) { 87 msg.append("Bytes are equal"); 88 } else { 89 throw new IllegalStateException(); 90 } 91 msg.append("\nLeft hex bytes: "); 92 for (int i = 0; i < prevBuf.length; i += 1) { 93 msg.append(' '); 94 int val = prevBuf[i] & 0xFF; 95 if ((val & 0xF0) == 0) { 96 msg.append('0'); 97 } 98 msg.append(Integer.toHexString(val)); 99 } 100 msg.append("\nRight hex bytes:"); 101 for (int i = 0; i < buf.length; i += 1) { 102 msg.append(' '); 103 int val = buf[i] & 0xFF; 104 if ((val & 0xF0) == 0) { 105 msg.append('0'); 106 } 107 msg.append(Integer.toHexString(val)); 108 } 109 if (dataIndex >= 0) { 110 msg.append("\nData index: " + dataIndex); 111 } 112 fail(msg.toString()); 113 } 114 } 115 prevBuf = buf; 116 out.reset(); 117 } 118 reset()119 private void reset() { 120 121 prevBuf = null; 122 out.reset(); 123 } 124 125 @Test testString()126 public void testString() { 127 128 final String[] DATA = { 129 "", "\u0001", "\u0002", 130 "A", "a", "ab", "b", "bb", "bba", 131 "c", "c\u0001", "d", 132 new String(new char[] { 0x7F }), 133 new String(new char[] { 0x7F, 0 }), 134 new String(new char[] { 0xFF }), 135 new String(new char[] { Character.MAX_VALUE }), 136 }; 137 for (int i = 0; i < DATA.length; i += 1) { 138 out.writeString(DATA[i]); 139 check(i); 140 } 141 reset(); 142 out.writeString("a"); 143 check(); 144 out.writeString("a"); 145 out.writeString(""); 146 check(); 147 out.writeString("a"); 148 out.writeString(""); 149 out.writeString("a"); 150 check(); 151 out.writeString("a"); 152 out.writeString("b"); 153 check(); 154 out.writeString("aa"); 155 check(); 156 out.writeString("b"); 157 check(); 158 } 159 160 @Test testFixedString()161 public void testFixedString() { 162 163 final char[][] DATA = { 164 {}, {'a'}, {'a', 'b'}, {'b'}, {'b', 'b'}, {0x7F}, {0xFF}, 165 }; 166 for (int i = 0; i < DATA.length; i += 1) { 167 out.writeString(DATA[i]); 168 check(i); 169 } 170 } 171 172 @Test testChars()173 public void testChars() { 174 175 final char[][] DATA = { 176 {}, {0}, {'a'}, {'a', 0}, {'a', 'b'}, {'b'}, {'b', 'b'}, 177 {0x7F}, {0x7F, 0}, {0xFF}, {0xFF, 0}, 178 }; 179 for (int i = 0; i < DATA.length; i += 1) { 180 out.writeChars(DATA[i]); 181 check(i); 182 } 183 } 184 185 @Test testBytes()186 public void testBytes() { 187 188 final char[][] DATA = { 189 {}, {0}, {'a'}, {'a', 0}, {'a', 'b'}, {'b'}, {'b', 'b'}, 190 {0x7F}, {0xFF}, 191 }; 192 for (int i = 0; i < DATA.length; i += 1) { 193 out.writeBytes(DATA[i]); 194 check(i); 195 } 196 } 197 198 @Test testBoolean()199 public void testBoolean() { 200 201 final boolean[] DATA = { 202 false, true 203 }; 204 for (int i = 0; i < DATA.length; i += 1) { 205 out.writeBoolean(DATA[i]); 206 check(i); 207 } 208 } 209 210 @Test testUnsignedByte()211 public void testUnsignedByte() { 212 213 final int[] DATA = { 214 0, 1, 0x7F, 0xFF 215 }; 216 for (int i = 0; i < DATA.length; i += 1) { 217 out.writeUnsignedByte(DATA[i]); 218 check(i); 219 } 220 } 221 222 @Test testUnsignedShort()223 public void testUnsignedShort() { 224 225 final int[] DATA = { 226 0, 1, 0xFE, 0xFF, 0x800, 0x7FFF, 0xFFFF 227 }; 228 for (int i = 0; i < DATA.length; i += 1) { 229 out.writeUnsignedShort(DATA[i]); 230 check(i); 231 } 232 } 233 234 @Test testUnsignedInt()235 public void testUnsignedInt() { 236 237 final long[] DATA = { 238 0, 1, 0xFE, 0xFF, 0x800, 0x7FFF, 0xFFFF, 0x80000, 239 0x7FFFFFFF, 0x80000000, 0xFFFFFFFF 240 }; 241 for (int i = 0; i < DATA.length; i += 1) { 242 out.writeUnsignedInt(DATA[i]); 243 check(i); 244 } 245 } 246 247 @Test testByte()248 public void testByte() { 249 250 final byte[] DATA = { 251 Byte.MIN_VALUE, Byte.MIN_VALUE + 1, 252 -1, 0, 1, 253 Byte.MAX_VALUE - 1, Byte.MAX_VALUE, 254 }; 255 for (int i = 0; i < DATA.length; i += 1) { 256 out.writeByte(DATA[i]); 257 check(i); 258 } 259 } 260 261 @Test testShort()262 public void testShort() { 263 264 final short[] DATA = { 265 Short.MIN_VALUE, Short.MIN_VALUE + 1, 266 Byte.MIN_VALUE, Byte.MIN_VALUE + 1, 267 -1, 0, 1, 268 Byte.MAX_VALUE - 1, Byte.MAX_VALUE, 269 Short.MAX_VALUE - 1, Short.MAX_VALUE, 270 }; 271 for (int i = 0; i < DATA.length; i += 1) { 272 out.writeShort(DATA[i]); 273 check(i); 274 } 275 } 276 277 @Test testInt()278 public void testInt() { 279 280 final int[] DATA = { 281 Integer.MIN_VALUE, Integer.MIN_VALUE + 1, 282 Short.MIN_VALUE, Short.MIN_VALUE + 1, 283 Byte.MIN_VALUE, Byte.MIN_VALUE + 1, 284 -1, 0, 1, 285 Byte.MAX_VALUE - 1, Byte.MAX_VALUE, 286 Short.MAX_VALUE - 1, Short.MAX_VALUE, 287 Integer.MAX_VALUE - 1, Integer.MAX_VALUE, 288 }; 289 for (int i = 0; i < DATA.length; i += 1) { 290 out.writeInt(DATA[i]); 291 check(i); 292 } 293 } 294 295 @Test testLong()296 public void testLong() { 297 298 final long[] DATA = { 299 Long.MIN_VALUE, Long.MIN_VALUE + 1, 300 Integer.MIN_VALUE, Integer.MIN_VALUE + 1, 301 Short.MIN_VALUE, Short.MIN_VALUE + 1, 302 Byte.MIN_VALUE, Byte.MIN_VALUE + 1, 303 -1, 0, 1, 304 Byte.MAX_VALUE - 1, Byte.MAX_VALUE, 305 Short.MAX_VALUE - 1, Short.MAX_VALUE, 306 Integer.MAX_VALUE - 1, Integer.MAX_VALUE, 307 Long.MAX_VALUE - 1, Long.MAX_VALUE, 308 }; 309 for (int i = 0; i < DATA.length; i += 1) { 310 out.writeLong(DATA[i]); 311 check(i); 312 } 313 } 314 315 @Test testFloat()316 public void testFloat() { 317 318 // Only positive floats and doubles are ordered deterministically 319 320 final float[] DATA = { 321 0, Float.MIN_VALUE, 2 * Float.MIN_VALUE, 322 (float) 0.01, (float) 0.02, (float) 0.99, 323 1, (float) 1.01, (float) 1.02, (float) 1.99, 324 Byte.MAX_VALUE - 1, Byte.MAX_VALUE, 325 Short.MAX_VALUE - 1, Short.MAX_VALUE, 326 Integer.MAX_VALUE, 327 Long.MAX_VALUE / 2, Long.MAX_VALUE, 328 Float.MAX_VALUE, 329 Float.POSITIVE_INFINITY, 330 Float.NaN, 331 }; 332 for (int i = 0; i < DATA.length; i += 1) { 333 out.writeFloat(DATA[i]); 334 check(i); 335 } 336 } 337 338 @Test testDouble()339 public void testDouble() { 340 341 // Only positive floats and doubles are ordered deterministically 342 343 final double[] DATA = { 344 0, Double.MIN_VALUE, 2 * Double.MIN_VALUE, 345 0.001, 0.002, 0.999, 346 1, 1.001, 1.002, 1.999, 347 Byte.MAX_VALUE - 1, Byte.MAX_VALUE, 348 Short.MAX_VALUE - 1, Short.MAX_VALUE, 349 Integer.MAX_VALUE - 1, Integer.MAX_VALUE, 350 Long.MAX_VALUE / 2, Long.MAX_VALUE, 351 Float.MAX_VALUE, Double.MAX_VALUE, 352 Double.POSITIVE_INFINITY, 353 Double.NaN, 354 }; 355 for (int i = 0; i < DATA.length; i += 1) { 356 out.writeDouble(DATA[i]); 357 check(i); 358 } 359 } 360 361 @Test testSortedFloat()362 public void testSortedFloat() { 363 364 final float[] DATA = { 365 Float.NEGATIVE_INFINITY, 366 (- Float.MAX_VALUE), 367 Long.MIN_VALUE, 368 Long.MIN_VALUE / 2, 369 Integer.MIN_VALUE, 370 Short.MIN_VALUE, 371 Short.MIN_VALUE + 1, 372 Byte.MIN_VALUE, 373 Byte.MIN_VALUE + 1, 374 (float) -1.99, 375 (float) -1.02, 376 (float) -1.01, 377 -1, 378 (float) -0.99, 379 (float) -0.02, 380 (float) -0.01, 381 2 * (- Float.MIN_VALUE), 382 (- Float.MIN_VALUE), 383 0, 384 Float.MIN_VALUE, 385 2 * Float.MIN_VALUE, 386 (float) 0.01, 387 (float) 0.02, 388 (float) 0.99, 389 1, 390 (float) 1.01, 391 (float) 1.02, 392 (float) 1.99, 393 Byte.MAX_VALUE - 1, 394 Byte.MAX_VALUE, 395 Short.MAX_VALUE - 1, 396 Short.MAX_VALUE, 397 Integer.MAX_VALUE, 398 Long.MAX_VALUE / 2, 399 Long.MAX_VALUE, 400 Float.MAX_VALUE, 401 Float.POSITIVE_INFINITY, 402 Float.NaN, 403 }; 404 for (int i = 0; i < DATA.length; i += 1) { 405 out.writeSortedFloat(DATA[i]); 406 check(i); 407 } 408 } 409 410 @Test testSortedDouble()411 public void testSortedDouble() { 412 413 final double[] DATA = { 414 Double.NEGATIVE_INFINITY, 415 (- Double.MAX_VALUE), 416 (- Float.MAX_VALUE), 417 Long.MIN_VALUE, 418 Long.MIN_VALUE / 2, 419 Integer.MIN_VALUE, 420 Short.MIN_VALUE, 421 Short.MIN_VALUE + 1, 422 Byte.MIN_VALUE, 423 Byte.MIN_VALUE + 1, 424 -1.999, 425 -1.002, 426 -1.001, 427 -1, 428 -0.999, 429 -0.002, 430 -0.001, 431 2 * (- Double.MIN_VALUE), 432 (- Double.MIN_VALUE), 433 0, 434 Double.MIN_VALUE, 435 2 * Double.MIN_VALUE, 436 0.001, 437 0.002, 438 0.999, 439 1, 440 1.001, 441 1.002, 442 1.999, 443 Byte.MAX_VALUE - 1, 444 Byte.MAX_VALUE, 445 Short.MAX_VALUE - 1, 446 Short.MAX_VALUE, 447 Integer.MAX_VALUE - 1, 448 Integer.MAX_VALUE, 449 Long.MAX_VALUE / 2, 450 Long.MAX_VALUE, 451 Float.MAX_VALUE, 452 Double.MAX_VALUE, 453 Double.POSITIVE_INFINITY, 454 Double.NaN, 455 }; 456 for (int i = 0; i < DATA.length; i += 1) { 457 out.writeSortedDouble(DATA[i]); 458 check(i); 459 } 460 } 461 462 @Test testPackedIntAndLong()463 public void testPackedIntAndLong() { 464 /* Only packed int/long values from 0 to 630 are ordered correctly */ 465 for (int i = 0; i <= 630; i += 1) { 466 out.writePackedInt(i); 467 check(i); 468 } 469 reset(); 470 for (int i = 0; i <= 630; i += 1) { 471 out.writePackedLong(i); 472 check(i); 473 } 474 } 475 476 @Test testSortedPackedInt()477 public void testSortedPackedInt() { 478 final int[] DATA = { 479 Integer.MIN_VALUE, Integer.MIN_VALUE + 1, 480 Short.MIN_VALUE, Short.MIN_VALUE + 1, 481 Byte.MIN_VALUE, Byte.MIN_VALUE + 1, 482 -1, 0, 1, 483 Byte.MAX_VALUE - 1, Byte.MAX_VALUE, 484 Short.MAX_VALUE - 1, Short.MAX_VALUE, 485 Integer.MAX_VALUE - 1, Integer.MAX_VALUE, 486 }; 487 for (int i = 0; i < DATA.length; i += 1) { 488 out.writeSortedPackedInt(DATA[i]); 489 check(i); 490 } 491 } 492 493 @Test testSortedPackedLong()494 public void testSortedPackedLong() { 495 final long[] DATA = { 496 Long.MIN_VALUE, Long.MIN_VALUE + 1, 497 Integer.MIN_VALUE, Integer.MIN_VALUE + 1, 498 Short.MIN_VALUE, Short.MIN_VALUE + 1, 499 Byte.MIN_VALUE, Byte.MIN_VALUE + 1, 500 -1, 0, 1, 501 Byte.MAX_VALUE - 1, Byte.MAX_VALUE, 502 Short.MAX_VALUE - 1, Short.MAX_VALUE, 503 Integer.MAX_VALUE - 1, Integer.MAX_VALUE, 504 Long.MAX_VALUE - 1, Long.MAX_VALUE, 505 }; 506 for (int i = 0; i < DATA.length; i += 1) { 507 out.writeSortedPackedLong(DATA[i]); 508 check(i); 509 } 510 } 511 512 @Test testBigInteger()513 public void testBigInteger() { 514 final BigInteger[] DATA = { 515 new BigInteger("-1111111111111111111111111"), 516 new BigInteger("-11111111111111111111"), 517 BigInteger.valueOf(Long.MIN_VALUE), 518 BigInteger.valueOf(Long.MIN_VALUE + 1), 519 BigInteger.valueOf(Integer.MIN_VALUE), 520 BigInteger.valueOf(Integer.MIN_VALUE + 1), 521 BigInteger.valueOf(Short.MIN_VALUE), 522 BigInteger.valueOf(Short.MIN_VALUE + 1), 523 BigInteger.valueOf(Byte.MIN_VALUE), 524 BigInteger.valueOf(Byte.MIN_VALUE + 1), 525 BigInteger.valueOf(-1), 526 BigInteger.ZERO, BigInteger.ONE, 527 BigInteger.valueOf(Byte.MAX_VALUE - 1), 528 BigInteger.valueOf(Byte.MAX_VALUE), 529 BigInteger.valueOf(Short.MAX_VALUE - 1), 530 BigInteger.valueOf(Short.MAX_VALUE), 531 BigInteger.valueOf(Integer.MAX_VALUE - 1), 532 BigInteger.valueOf(Integer.MAX_VALUE), 533 BigInteger.valueOf(Long.MAX_VALUE - 1), 534 BigInteger.valueOf(Long.MAX_VALUE), 535 new BigInteger("11111111111111111111"), 536 new BigInteger("1111111111111111111111111"), 537 }; 538 for (int i = 0; i < DATA.length; i += 1) { 539 out.writeBigInteger(DATA[i]); 540 check(i); 541 } 542 } 543 544 @Test testSortedBigDecimal()545 public void testSortedBigDecimal() { 546 final BigDecimal[] DATA = { 547 new BigDecimal(BigInteger.valueOf(Long.MIN_VALUE), 548 Short.MIN_VALUE), 549 new BigDecimal("-9999999999999999999.9999999999999999999"), 550 new BigDecimal("-123456789.123456789"), 551 new BigDecimal("-0.9999999999999999999999999999999999999"), 552 new BigDecimal("-123456789.123456789E-700"), 553 new BigDecimal("-123456789.123456789E-6700"), 554 new BigDecimal(BigInteger.valueOf(Long.MIN_VALUE), 555 Short.MAX_VALUE), 556 new BigDecimal("0.0"), 557 new BigDecimal(BigInteger.valueOf(Long.MAX_VALUE), 558 Short.MAX_VALUE), 559 new BigDecimal("0.9999999999999999999999999999999999999"), 560 new BigDecimal("123456789.123456789"), 561 new BigDecimal("9999999999999999999.9999999999999999999"), 562 new BigDecimal("123456789.123456789E700"), 563 new BigDecimal("123456789.123456789E6700"), 564 new BigDecimal(BigInteger.valueOf(Long.MAX_VALUE), 565 Short.MIN_VALUE), 566 }; 567 for (int i = 0; i < DATA.length; i += 1) { 568 out.writeSortedBigDecimal(DATA[i]); 569 check(i); 570 } 571 } 572 } 573