1 // Protocol Buffers - Google's data interchange format 2 // Copyright 2008 Google Inc. All rights reserved. 3 // https://developers.google.com/protocol-buffers/ 4 // 5 // Redistribution and use in source and binary forms, with or without 6 // modification, are permitted provided that the following conditions are 7 // met: 8 // 9 // * Redistributions of source code must retain the above copyright 10 // notice, this list of conditions and the following disclaimer. 11 // * Redistributions in binary form must reproduce the above 12 // copyright notice, this list of conditions and the following disclaimer 13 // in the documentation and/or other materials provided with the 14 // distribution. 15 // * Neither the name of Google Inc. nor the names of its 16 // contributors may be used to endorse or promote products derived from 17 // this software without specific prior written permission. 18 // 19 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 31 package com.google.protobuf; 32 33 import static com.google.protobuf.Internal.UTF_8; 34 35 import junit.framework.TestCase; 36 37 import java.io.ByteArrayInputStream; 38 import java.io.ByteArrayOutputStream; 39 import java.io.EOFException; 40 import java.io.IOException; 41 import java.io.InputStream; 42 import java.io.ObjectInputStream; 43 import java.io.ObjectOutputStream; 44 import java.io.OutputStream; 45 import java.io.UnsupportedEncodingException; 46 import java.nio.BufferOverflowException; 47 import java.nio.ByteBuffer; 48 import java.util.Arrays; 49 import java.util.List; 50 import java.util.NoSuchElementException; 51 52 /** 53 * Tests for {@link NioByteString}. 54 */ 55 public class NioByteStringTest extends TestCase { 56 private static final ByteString EMPTY = new NioByteString(ByteBuffer.wrap(new byte[0])); 57 private static final String CLASSNAME = NioByteString.class.getSimpleName(); 58 private static final byte[] BYTES = ByteStringTest.getTestBytes(1234, 11337766L); 59 private static final int EXPECTED_HASH = ByteString.wrap(BYTES).hashCode(); 60 61 private final ByteBuffer backingBuffer = ByteBuffer.wrap(BYTES.clone()); 62 private final ByteString testString = new NioByteString(backingBuffer); 63 testExpectedType()64 public void testExpectedType() { 65 String actualClassName = getActualClassName(testString); 66 assertEquals(CLASSNAME + " should match type exactly", CLASSNAME, actualClassName); 67 } 68 getActualClassName(Object object)69 protected String getActualClassName(Object object) { 70 String actualClassName = object.getClass().getName(); 71 actualClassName = actualClassName.substring(actualClassName.lastIndexOf('.') + 1); 72 return actualClassName; 73 } 74 testByteAt()75 public void testByteAt() { 76 boolean stillEqual = true; 77 for (int i = 0; stillEqual && i < BYTES.length; ++i) { 78 stillEqual = (BYTES[i] == testString.byteAt(i)); 79 } 80 assertTrue(CLASSNAME + " must capture the right bytes", stillEqual); 81 } 82 testByteIterator()83 public void testByteIterator() { 84 boolean stillEqual = true; 85 ByteString.ByteIterator iter = testString.iterator(); 86 for (int i = 0; stillEqual && i < BYTES.length; ++i) { 87 stillEqual = (iter.hasNext() && BYTES[i] == iter.nextByte()); 88 } 89 assertTrue(CLASSNAME + " must capture the right bytes", stillEqual); 90 assertFalse(CLASSNAME + " must have exhausted the itertor", iter.hasNext()); 91 92 try { 93 iter.nextByte(); 94 fail("Should have thrown an exception."); 95 } catch (NoSuchElementException e) { 96 // This is success 97 } 98 } 99 testByteIterable()100 public void testByteIterable() { 101 boolean stillEqual = true; 102 int j = 0; 103 for (byte quantum : testString) { 104 stillEqual = (BYTES[j] == quantum); 105 ++j; 106 } 107 assertTrue(CLASSNAME + " must capture the right bytes as Bytes", stillEqual); 108 assertEquals(CLASSNAME + " iterable character count", BYTES.length, j); 109 } 110 testSize()111 public void testSize() { 112 assertEquals(CLASSNAME + " must have the expected size", BYTES.length, 113 testString.size()); 114 } 115 testGetTreeDepth()116 public void testGetTreeDepth() { 117 assertEquals(CLASSNAME + " must have depth 0", 0, testString.getTreeDepth()); 118 } 119 testIsBalanced()120 public void testIsBalanced() { 121 assertTrue(CLASSNAME + " is technically balanced", testString.isBalanced()); 122 } 123 testCopyTo_ByteArrayOffsetLength()124 public void testCopyTo_ByteArrayOffsetLength() { 125 int destinationOffset = 50; 126 int length = 100; 127 byte[] destination = new byte[destinationOffset + length]; 128 int sourceOffset = 213; 129 testString.copyTo(destination, sourceOffset, destinationOffset, length); 130 boolean stillEqual = true; 131 for (int i = 0; stillEqual && i < length; ++i) { 132 stillEqual = BYTES[i + sourceOffset] == destination[i + destinationOffset]; 133 } 134 assertTrue(CLASSNAME + ".copyTo(4 arg) must give the expected bytes", stillEqual); 135 } 136 testCopyTo_ByteArrayOffsetLengthErrors()137 public void testCopyTo_ByteArrayOffsetLengthErrors() { 138 int destinationOffset = 50; 139 int length = 100; 140 byte[] destination = new byte[destinationOffset + length]; 141 142 try { 143 // Copy one too many bytes 144 testString.copyTo(destination, testString.size() + 1 - length, 145 destinationOffset, length); 146 fail("Should have thrown an exception when copying too many bytes of a " 147 + CLASSNAME); 148 } catch (IndexOutOfBoundsException expected) { 149 // This is success 150 } 151 152 try { 153 // Copy with illegal negative sourceOffset 154 testString.copyTo(destination, -1, destinationOffset, length); 155 fail("Should have thrown an exception when given a negative sourceOffset in " 156 + CLASSNAME); 157 } catch (IndexOutOfBoundsException expected) { 158 // This is success 159 } 160 161 try { 162 // Copy with illegal negative destinationOffset 163 testString.copyTo(destination, 0, -1, length); 164 fail("Should have thrown an exception when given a negative destinationOffset in " 165 + CLASSNAME); 166 } catch (IndexOutOfBoundsException expected) { 167 // This is success 168 } 169 170 try { 171 // Copy with illegal negative size 172 testString.copyTo(destination, 0, 0, -1); 173 fail("Should have thrown an exception when given a negative size in " 174 + CLASSNAME); 175 } catch (IndexOutOfBoundsException expected) { 176 // This is success 177 } 178 179 try { 180 // Copy with illegal too-large sourceOffset 181 testString.copyTo(destination, 2 * testString.size(), 0, length); 182 fail("Should have thrown an exception when the destinationOffset is too large in " 183 + CLASSNAME); 184 } catch (IndexOutOfBoundsException expected) { 185 // This is success 186 } 187 188 try { 189 // Copy with illegal too-large destinationOffset 190 testString.copyTo(destination, 0, 2 * destination.length, length); 191 fail("Should have thrown an exception when the destinationOffset is too large in " 192 + CLASSNAME); 193 } catch (IndexOutOfBoundsException expected) { 194 // This is success 195 } 196 } 197 testCopyTo_ByteBuffer()198 public void testCopyTo_ByteBuffer() { 199 // Same length. 200 ByteBuffer myBuffer = ByteBuffer.allocate(BYTES.length); 201 testString.copyTo(myBuffer); 202 myBuffer.flip(); 203 assertEquals(CLASSNAME + ".copyTo(ByteBuffer) must give back the same bytes", 204 backingBuffer, myBuffer); 205 206 // Target buffer bigger than required. 207 myBuffer = ByteBuffer.allocate(testString.size() + 1); 208 testString.copyTo(myBuffer); 209 myBuffer.flip(); 210 assertEquals(backingBuffer, myBuffer); 211 212 // Target buffer has no space. 213 myBuffer = ByteBuffer.allocate(0); 214 try { 215 testString.copyTo(myBuffer); 216 fail("Should have thrown an exception when target ByteBuffer has insufficient capacity"); 217 } catch (BufferOverflowException e) { 218 // Expected. 219 } 220 221 // Target buffer too small. 222 myBuffer = ByteBuffer.allocate(1); 223 try { 224 testString.copyTo(myBuffer); 225 fail("Should have thrown an exception when target ByteBuffer has insufficient capacity"); 226 } catch (BufferOverflowException e) { 227 // Expected. 228 } 229 } 230 testMarkSupported()231 public void testMarkSupported() { 232 InputStream stream = testString.newInput(); 233 assertTrue(CLASSNAME + ".newInput() must support marking", stream.markSupported()); 234 } 235 testMarkAndReset()236 public void testMarkAndReset() throws IOException { 237 int fraction = testString.size() / 3; 238 239 InputStream stream = testString.newInput(); 240 stream.mark(testString.size()); // First, mark() the end. 241 242 skipFully(stream, fraction); // Skip a large fraction, but not all. 243 assertEquals( 244 CLASSNAME + ": after skipping to the 'middle', half the bytes are available", 245 (testString.size() - fraction), stream.available()); 246 stream.reset(); 247 assertEquals( 248 CLASSNAME + ": after resetting, all bytes are available", 249 testString.size(), stream.available()); 250 251 skipFully(stream, testString.size()); // Skip to the end. 252 assertEquals( 253 CLASSNAME + ": after skipping to the end, no more bytes are available", 254 0, stream.available()); 255 } 256 257 /** 258 * Discards {@code n} bytes of data from the input stream. This method 259 * will block until the full amount has been skipped. Does not close the 260 * stream. 261 * <p>Copied from com.google.common.io.ByteStreams to avoid adding dependency. 262 * 263 * @param in the input stream to read from 264 * @param n the number of bytes to skip 265 * @throws EOFException if this stream reaches the end before skipping all 266 * the bytes 267 * @throws IOException if an I/O error occurs, or the stream does not 268 * support skipping 269 */ skipFully(InputStream in, long n)270 static void skipFully(InputStream in, long n) throws IOException { 271 long toSkip = n; 272 while (n > 0) { 273 long amt = in.skip(n); 274 if (amt == 0) { 275 // Force a blocking read to avoid infinite loop 276 if (in.read() == -1) { 277 long skipped = toSkip - n; 278 throw new EOFException("reached end of stream after skipping " 279 + skipped + " bytes; " + toSkip + " bytes expected"); 280 } 281 n--; 282 } else { 283 n -= amt; 284 } 285 } 286 } 287 testAsReadOnlyByteBuffer()288 public void testAsReadOnlyByteBuffer() { 289 ByteBuffer byteBuffer = testString.asReadOnlyByteBuffer(); 290 byte[] roundTripBytes = new byte[BYTES.length]; 291 assertTrue(byteBuffer.remaining() == BYTES.length); 292 assertTrue(byteBuffer.isReadOnly()); 293 byteBuffer.get(roundTripBytes); 294 assertTrue(CLASSNAME + ".asReadOnlyByteBuffer() must give back the same bytes", 295 Arrays.equals(BYTES, roundTripBytes)); 296 } 297 testAsReadOnlyByteBufferList()298 public void testAsReadOnlyByteBufferList() { 299 List<ByteBuffer> byteBuffers = testString.asReadOnlyByteBufferList(); 300 int bytesSeen = 0; 301 byte[] roundTripBytes = new byte[BYTES.length]; 302 for (ByteBuffer byteBuffer : byteBuffers) { 303 int thisLength = byteBuffer.remaining(); 304 assertTrue(byteBuffer.isReadOnly()); 305 assertTrue(bytesSeen + thisLength <= BYTES.length); 306 byteBuffer.get(roundTripBytes, bytesSeen, thisLength); 307 bytesSeen += thisLength; 308 } 309 assertTrue(bytesSeen == BYTES.length); 310 assertTrue(CLASSNAME + ".asReadOnlyByteBufferTest() must give back the same bytes", 311 Arrays.equals(BYTES, roundTripBytes)); 312 } 313 testToByteArray()314 public void testToByteArray() { 315 byte[] roundTripBytes = testString.toByteArray(); 316 assertTrue(CLASSNAME + ".toByteArray() must give back the same bytes", 317 Arrays.equals(BYTES, roundTripBytes)); 318 } 319 testWriteTo()320 public void testWriteTo() throws IOException { 321 ByteArrayOutputStream bos = new ByteArrayOutputStream(); 322 testString.writeTo(bos); 323 byte[] roundTripBytes = bos.toByteArray(); 324 assertTrue(CLASSNAME + ".writeTo() must give back the same bytes", 325 Arrays.equals(BYTES, roundTripBytes)); 326 } 327 testWriteToShouldNotExposeInternalBufferToOutputStream()328 public void testWriteToShouldNotExposeInternalBufferToOutputStream() throws IOException { 329 OutputStream os = new OutputStream() { 330 @Override 331 public void write(byte[] b, int off, int len) { 332 Arrays.fill(b, off, off + len, (byte) 0); 333 } 334 335 @Override 336 public void write(int b) { 337 throw new UnsupportedOperationException(); 338 } 339 }; 340 341 byte[] original = Arrays.copyOf(BYTES, BYTES.length); 342 testString.writeTo(os); 343 assertTrue(CLASSNAME + ".writeTo() must NOT grant access to underlying buffer", 344 Arrays.equals(original, BYTES)); 345 } 346 testWriteToInternalShouldExposeInternalBufferToOutputStream()347 public void testWriteToInternalShouldExposeInternalBufferToOutputStream() throws IOException { 348 OutputStream os = new OutputStream() { 349 @Override 350 public void write(byte[] b, int off, int len) { 351 Arrays.fill(b, off, off + len, (byte) 0); 352 } 353 354 @Override 355 public void write(int b) { 356 throw new UnsupportedOperationException(); 357 } 358 }; 359 360 testString.writeToInternal(os, 0, testString.size()); 361 byte[] allZeros = new byte[testString.size()]; 362 assertTrue(CLASSNAME + ".writeToInternal() must grant access to underlying buffer", 363 Arrays.equals(allZeros, backingBuffer.array())); 364 } 365 testWriteToShouldExposeInternalBufferToByteOutput()366 public void testWriteToShouldExposeInternalBufferToByteOutput() throws IOException { 367 ByteOutput out = new ByteOutput() { 368 @Override 369 public void write(byte value) throws IOException { 370 throw new UnsupportedOperationException(); 371 } 372 373 @Override 374 public void write(byte[] value, int offset, int length) throws IOException { 375 throw new UnsupportedOperationException(); 376 } 377 378 @Override 379 public void writeLazy(byte[] value, int offset, int length) throws IOException { 380 throw new UnsupportedOperationException(); 381 } 382 383 @Override 384 public void write(ByteBuffer value) throws IOException { 385 throw new UnsupportedOperationException(); 386 } 387 388 @Override 389 public void writeLazy(ByteBuffer value) throws IOException { 390 Arrays.fill(value.array(), value.arrayOffset(), value.arrayOffset() + value.limit(), 391 (byte) 0); 392 } 393 }; 394 395 testString.writeTo(out); 396 byte[] allZeros = new byte[testString.size()]; 397 assertTrue(CLASSNAME + ".writeTo() must grant access to underlying buffer", 398 Arrays.equals(allZeros, backingBuffer.array())); 399 } 400 testNewOutput()401 public void testNewOutput() throws IOException { 402 ByteArrayOutputStream bos = new ByteArrayOutputStream(); 403 ByteString.Output output = ByteString.newOutput(); 404 testString.writeTo(output); 405 assertEquals("Output Size returns correct result", 406 output.size(), testString.size()); 407 output.writeTo(bos); 408 assertTrue("Output.writeTo() must give back the same bytes", 409 Arrays.equals(BYTES, bos.toByteArray())); 410 411 // write the output stream to itself! This should cause it to double 412 output.writeTo(output); 413 assertEquals("Writing an output stream to itself is successful", 414 testString.concat(testString), output.toByteString()); 415 416 output.reset(); 417 assertEquals("Output.reset() resets the output", 0, output.size()); 418 assertEquals("Output.reset() resets the output", 419 EMPTY, output.toByteString()); 420 } 421 testToString()422 public void testToString() { 423 String testString = "I love unicode \u1234\u5678 characters"; 424 ByteString unicode = forString(testString); 425 String roundTripString = unicode.toString(UTF_8); 426 assertEquals(CLASSNAME + " unicode must match", testString, roundTripString); 427 } 428 testCharsetToString()429 public void testCharsetToString() { 430 String testString = "I love unicode \u1234\u5678 characters"; 431 ByteString unicode = forString(testString); 432 String roundTripString = unicode.toString(UTF_8); 433 assertEquals(CLASSNAME + " unicode must match", testString, roundTripString); 434 } 435 testToString_returnsCanonicalEmptyString()436 public void testToString_returnsCanonicalEmptyString() { 437 assertSame(CLASSNAME + " must be the same string references", 438 EMPTY.toString(UTF_8), 439 new NioByteString(ByteBuffer.wrap(new byte[0])).toString(UTF_8)); 440 } 441 testToString_raisesException()442 public void testToString_raisesException() { 443 try { 444 EMPTY.toString("invalid"); 445 fail("Should have thrown an exception."); 446 } catch (UnsupportedEncodingException expected) { 447 // This is success 448 } 449 450 try { 451 testString.toString("invalid"); 452 fail("Should have thrown an exception."); 453 } catch (UnsupportedEncodingException expected) { 454 // This is success 455 } 456 } 457 testEquals()458 public void testEquals() { 459 assertEquals(CLASSNAME + " must not equal null", false, testString.equals(null)); 460 assertEquals(CLASSNAME + " must equal self", testString, testString); 461 assertFalse(CLASSNAME + " must not equal the empty string", 462 testString.equals(EMPTY)); 463 assertEquals(CLASSNAME + " empty strings must be equal", 464 EMPTY, testString.substring(55, 55)); 465 assertEquals(CLASSNAME + " must equal another string with the same value", 466 testString, new NioByteString(backingBuffer)); 467 468 byte[] mungedBytes = mungedBytes(); 469 assertFalse(CLASSNAME + " must not equal every string with the same length", 470 testString.equals(new NioByteString(ByteBuffer.wrap(mungedBytes)))); 471 } 472 testEqualsLiteralByteString()473 public void testEqualsLiteralByteString() { 474 ByteString literal = ByteString.copyFrom(BYTES); 475 assertEquals(CLASSNAME + " must equal LiteralByteString with same value", literal, 476 testString); 477 assertEquals(CLASSNAME + " must equal LiteralByteString with same value", testString, 478 literal); 479 assertFalse(CLASSNAME + " must not equal the empty string", 480 testString.equals(ByteString.EMPTY)); 481 assertEquals(CLASSNAME + " empty strings must be equal", 482 ByteString.EMPTY, testString.substring(55, 55)); 483 484 literal = ByteString.copyFrom(mungedBytes()); 485 assertFalse(CLASSNAME + " must not equal every LiteralByteString with the same length", 486 testString.equals(literal)); 487 assertFalse(CLASSNAME + " must not equal every LiteralByteString with the same length", 488 literal.equals(testString)); 489 } 490 testEqualsRopeByteString()491 public void testEqualsRopeByteString() { 492 ByteString p1 = ByteString.copyFrom(BYTES, 0, 5); 493 ByteString p2 = ByteString.copyFrom(BYTES, 5, BYTES.length - 5); 494 ByteString rope = p1.concat(p2); 495 496 assertEquals(CLASSNAME + " must equal RopeByteString with same value", rope, 497 testString); 498 assertEquals(CLASSNAME + " must equal RopeByteString with same value", testString, 499 rope); 500 assertFalse(CLASSNAME + " must not equal the empty string", 501 testString.equals(ByteString.EMPTY.concat(ByteString.EMPTY))); 502 assertEquals(CLASSNAME + " empty strings must be equal", 503 ByteString.EMPTY.concat(ByteString.EMPTY), testString.substring(55, 55)); 504 505 byte[] mungedBytes = mungedBytes(); 506 p1 = ByteString.copyFrom(mungedBytes, 0, 5); 507 p2 = ByteString.copyFrom(mungedBytes, 5, mungedBytes.length - 5); 508 rope = p1.concat(p2); 509 assertFalse(CLASSNAME + " must not equal every RopeByteString with the same length", 510 testString.equals(rope)); 511 assertFalse(CLASSNAME + " must not equal every RopeByteString with the same length", 512 rope.equals(testString)); 513 } 514 mungedBytes()515 private byte[] mungedBytes() { 516 byte[] mungedBytes = new byte[BYTES.length]; 517 System.arraycopy(BYTES, 0, mungedBytes, 0, BYTES.length); 518 mungedBytes[mungedBytes.length - 5] = (byte) (mungedBytes[mungedBytes.length - 5] ^ 0xFF); 519 return mungedBytes; 520 } 521 testHashCode()522 public void testHashCode() { 523 int hash = testString.hashCode(); 524 assertEquals(CLASSNAME + " must have expected hashCode", EXPECTED_HASH, hash); 525 } 526 testPeekCachedHashCode()527 public void testPeekCachedHashCode() { 528 ByteString newString = new NioByteString(backingBuffer); 529 assertEquals(CLASSNAME + ".peekCachedHashCode() should return zero at first", 0, 530 newString.peekCachedHashCode()); 531 newString.hashCode(); 532 assertEquals(CLASSNAME + ".peekCachedHashCode should return zero at first", 533 EXPECTED_HASH, newString.peekCachedHashCode()); 534 } 535 testPartialHash()536 public void testPartialHash() { 537 // partialHash() is more strenuously tested elsewhere by testing hashes of substrings. 538 // This test would fail if the expected hash were 1. It's not. 539 int hash = testString.partialHash(testString.size(), 0, testString.size()); 540 assertEquals(CLASSNAME + ".partialHash() must yield expected hashCode", 541 EXPECTED_HASH, hash); 542 } 543 testNewInput()544 public void testNewInput() throws IOException { 545 InputStream input = testString.newInput(); 546 assertEquals("InputStream.available() returns correct value", 547 testString.size(), input.available()); 548 boolean stillEqual = true; 549 for (byte referenceByte : BYTES) { 550 int expectedInt = (referenceByte & 0xFF); 551 stillEqual = (expectedInt == input.read()); 552 } 553 assertEquals("InputStream.available() returns correct value", 554 0, input.available()); 555 assertTrue(CLASSNAME + " must give the same bytes from the InputStream", stillEqual); 556 assertEquals(CLASSNAME + " InputStream must now be exhausted", -1, input.read()); 557 } 558 testNewInput_skip()559 public void testNewInput_skip() throws IOException { 560 InputStream input = testString.newInput(); 561 int stringSize = testString.size(); 562 int nearEndIndex = stringSize * 2 / 3; 563 long skipped1 = input.skip(nearEndIndex); 564 assertEquals("InputStream.skip()", skipped1, nearEndIndex); 565 assertEquals("InputStream.available()", 566 stringSize - skipped1, input.available()); 567 assertTrue("InputStream.mark() is available", input.markSupported()); 568 input.mark(0); 569 assertEquals("InputStream.skip(), read()", 570 testString.byteAt(nearEndIndex) & 0xFF, input.read()); 571 assertEquals("InputStream.available()", 572 stringSize - skipped1 - 1, input.available()); 573 long skipped2 = input.skip(stringSize); 574 assertEquals("InputStream.skip() incomplete", 575 skipped2, stringSize - skipped1 - 1); 576 assertEquals("InputStream.skip(), no more input", 0, input.available()); 577 assertEquals("InputStream.skip(), no more input", -1, input.read()); 578 input.reset(); 579 assertEquals("InputStream.reset() succeded", 580 stringSize - skipped1, input.available()); 581 assertEquals("InputStream.reset(), read()", 582 testString.byteAt(nearEndIndex) & 0xFF, input.read()); 583 } 584 testNewCodedInput()585 public void testNewCodedInput() throws IOException { 586 CodedInputStream cis = testString.newCodedInput(); 587 byte[] roundTripBytes = cis.readRawBytes(BYTES.length); 588 assertTrue(CLASSNAME + " must give the same bytes back from the CodedInputStream", 589 Arrays.equals(BYTES, roundTripBytes)); 590 assertTrue(CLASSNAME + " CodedInputStream must now be exhausted", cis.isAtEnd()); 591 } 592 593 /** 594 * Make sure we keep things simple when concatenating with empty. See also 595 * {@link ByteStringTest#testConcat_empty()}. 596 */ testConcat_empty()597 public void testConcat_empty() { 598 assertSame(CLASSNAME + " concatenated with empty must give " + CLASSNAME, 599 testString.concat(EMPTY), testString); 600 assertSame("empty concatenated with " + CLASSNAME + " must give " + CLASSNAME, 601 EMPTY.concat(testString), testString); 602 } 603 testJavaSerialization()604 public void testJavaSerialization() throws Exception { 605 ByteArrayOutputStream out = new ByteArrayOutputStream(); 606 ObjectOutputStream oos = new ObjectOutputStream(out); 607 oos.writeObject(testString); 608 oos.close(); 609 byte[] pickled = out.toByteArray(); 610 InputStream in = new ByteArrayInputStream(pickled); 611 ObjectInputStream ois = new ObjectInputStream(in); 612 Object o = ois.readObject(); 613 assertTrue("Didn't get a ByteString back", o instanceof ByteString); 614 assertEquals("Should get an equal ByteString back", testString, o); 615 } 616 forString(String str)617 private static ByteString forString(String str) { 618 return new NioByteString(ByteBuffer.wrap(str.getBytes(UTF_8))); 619 } 620 } 621