| OLD | NEW |
| 1 // Protocol Buffers - Google's data interchange format | 1 // Protocol Buffers - Google's data interchange format |
| 2 // Copyright 2008 Google Inc. All rights reserved. | 2 // Copyright 2008 Google Inc. All rights reserved. |
| 3 // https://developers.google.com/protocol-buffers/ | 3 // https://developers.google.com/protocol-buffers/ |
| 4 // | 4 // |
| 5 // Redistribution and use in source and binary forms, with or without | 5 // Redistribution and use in source and binary forms, with or without |
| 6 // modification, are permitted provided that the following conditions are | 6 // modification, are permitted provided that the following conditions are |
| 7 // met: | 7 // met: |
| 8 // | 8 // |
| 9 // * Redistributions of source code must retain the above copyright | 9 // * Redistributions of source code must retain the above copyright |
| 10 // notice, this list of conditions and the following disclaimer. | 10 // notice, this list of conditions and the following disclaimer. |
| (...skipping 17 matching lines...) Expand all Loading... |
| 28 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 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. | 29 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 30 | 30 |
| 31 package com.google.protobuf; | 31 package com.google.protobuf; |
| 32 | 32 |
| 33 import com.google.protobuf.CodedOutputStream.OutOfSpaceException; | 33 import com.google.protobuf.CodedOutputStream.OutOfSpaceException; |
| 34 import protobuf_unittest.UnittestProto.SparseEnumMessage; | 34 import protobuf_unittest.UnittestProto.SparseEnumMessage; |
| 35 import protobuf_unittest.UnittestProto.TestAllTypes; | 35 import protobuf_unittest.UnittestProto.TestAllTypes; |
| 36 import protobuf_unittest.UnittestProto.TestPackedTypes; | 36 import protobuf_unittest.UnittestProto.TestPackedTypes; |
| 37 import protobuf_unittest.UnittestProto.TestSparseEnum; | 37 import protobuf_unittest.UnittestProto.TestSparseEnum; |
| 38 |
| 39 import junit.framework.TestCase; |
| 40 |
| 38 import java.io.ByteArrayInputStream; | 41 import java.io.ByteArrayInputStream; |
| 39 import java.io.ByteArrayOutputStream; | 42 import java.io.ByteArrayOutputStream; |
| 40 import java.nio.ByteBuffer; | 43 import java.nio.ByteBuffer; |
| 41 import java.util.ArrayList; | 44 import java.util.ArrayList; |
| 42 import java.util.Arrays; | 45 import java.util.Arrays; |
| 43 import java.util.List; | 46 import java.util.List; |
| 44 import junit.framework.TestCase; | |
| 45 | 47 |
| 46 /** | 48 /** |
| 47 * Unit test for {@link CodedOutputStream}. | 49 * Unit test for {@link CodedOutputStream}. |
| 48 * | 50 * |
| 49 * @author kenton@google.com Kenton Varda | 51 * @author kenton@google.com Kenton Varda |
| 50 */ | 52 */ |
| 51 public class CodedOutputStreamTest extends TestCase { | 53 public class CodedOutputStreamTest extends TestCase { |
| 52 private interface Coder { | 54 private interface Coder { |
| 53 CodedOutputStream stream(); | 55 CodedOutputStream stream(); |
| 54 | 56 |
| (...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 142 @Override | 144 @Override |
| 143 public OutputType getOutputType() { | 145 public OutputType getOutputType() { |
| 144 return OutputType.NIO_HEAP; | 146 return OutputType.NIO_HEAP; |
| 145 } | 147 } |
| 146 } | 148 } |
| 147 | 149 |
| 148 private static final class NioDirectCoder implements Coder { | 150 private static final class NioDirectCoder implements Coder { |
| 149 private final int initialPosition; | 151 private final int initialPosition; |
| 150 private final CodedOutputStream stream; | 152 private final CodedOutputStream stream; |
| 151 private final ByteBuffer buffer; | 153 private final ByteBuffer buffer; |
| 152 private final boolean unsafe; | |
| 153 | 154 |
| 154 NioDirectCoder(int size, boolean unsafe) { | 155 NioDirectCoder(int size) { |
| 155 this(size, 0, unsafe); | 156 this(size, 0); |
| 156 } | 157 } |
| 157 | 158 |
| 158 NioDirectCoder(int size, int initialPosition, boolean unsafe) { | 159 NioDirectCoder(int size, int initialPosition) { |
| 159 this.unsafe = unsafe; | |
| 160 this.initialPosition = initialPosition; | 160 this.initialPosition = initialPosition; |
| 161 buffer = ByteBuffer.allocateDirect(size); | 161 buffer = ByteBuffer.allocateDirect(size); |
| 162 buffer.position(initialPosition); | 162 buffer.position(initialPosition); |
| 163 stream = | 163 stream = CodedOutputStream.newInstance(buffer); |
| 164 unsafe | |
| 165 ? CodedOutputStream.newUnsafeInstance(buffer) | |
| 166 : CodedOutputStream.newSafeInstance(buffer); | |
| 167 } | 164 } |
| 168 | 165 |
| 169 @Override | 166 @Override |
| 170 public CodedOutputStream stream() { | 167 public CodedOutputStream stream() { |
| 171 return stream; | 168 return stream; |
| 172 } | 169 } |
| 173 | 170 |
| 174 @Override | 171 @Override |
| 175 public byte[] toByteArray() { | 172 public byte[] toByteArray() { |
| 176 ByteBuffer dup = buffer.duplicate(); | 173 ByteBuffer dup = buffer.duplicate(); |
| 177 dup.position(initialPosition); | 174 dup.position(initialPosition); |
| 178 dup.limit(buffer.position()); | 175 dup.limit(buffer.position()); |
| 179 | 176 |
| 180 byte[] bytes = new byte[dup.remaining()]; | 177 byte[] bytes = new byte[dup.remaining()]; |
| 181 dup.get(bytes); | 178 dup.get(bytes); |
| 182 return bytes; | 179 return bytes; |
| 183 } | 180 } |
| 184 | 181 |
| 185 @Override | 182 @Override |
| 186 public OutputType getOutputType() { | 183 public OutputType getOutputType() { |
| 187 return unsafe ? OutputType.NIO_DIRECT_SAFE : OutputType.NIO_DIRECT_UNSAFE; | 184 return OutputType.NIO_DIRECT; |
| 188 } | 185 } |
| 189 } | 186 } |
| 190 | 187 |
| 191 private enum OutputType { | 188 private enum OutputType { |
| 192 ARRAY() { | 189 ARRAY() { |
| 193 @Override | 190 @Override |
| 194 Coder newCoder(int size) { | 191 Coder newCoder(int size) { |
| 195 return new ArrayCoder(size); | 192 return new ArrayCoder(size); |
| 196 } | 193 } |
| 197 }, | 194 }, |
| 198 NIO_HEAP() { | 195 NIO_HEAP() { |
| 199 @Override | 196 @Override |
| 200 Coder newCoder(int size) { | 197 Coder newCoder(int size) { |
| 201 return new NioHeapCoder(size); | 198 return new NioHeapCoder(size); |
| 202 } | 199 } |
| 203 }, | 200 }, |
| 204 NIO_DIRECT_SAFE() { | 201 NIO_DIRECT() { |
| 205 @Override | 202 @Override |
| 206 Coder newCoder(int size) { | 203 Coder newCoder(int size) { |
| 207 return new NioDirectCoder(size, false); | 204 return new NioDirectCoder(size); |
| 208 } | |
| 209 }, | |
| 210 NIO_DIRECT_UNSAFE() { | |
| 211 @Override | |
| 212 Coder newCoder(int size) { | |
| 213 return new NioDirectCoder(size, true); | |
| 214 } | 205 } |
| 215 }, | 206 }, |
| 216 STREAM() { | 207 STREAM() { |
| 217 @Override | 208 @Override |
| 218 Coder newCoder(int size) { | 209 Coder newCoder(int size) { |
| 219 return new OutputStreamCoder(size); | 210 return new OutputStreamCoder(size); |
| 220 } | 211 } |
| 221 }; | 212 }; |
| 222 | 213 |
| 223 abstract Coder newCoder(int size); | 214 abstract Coder newCoder(int size); |
| (...skipping 167 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 391 assertEquals(value.length * 1024, coder.stream().getTotalBytesWritten()); | 382 assertEquals(value.length * 1024, coder.stream().getTotalBytesWritten()); |
| 392 | 383 |
| 393 // Now write an encoded string. | 384 // Now write an encoded string. |
| 394 String string = | 385 String string = |
| 395 "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrs
tuvwxyz"; | 386 "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrs
tuvwxyz"; |
| 396 // Ensure we take the slower fast path. | 387 // Ensure we take the slower fast path. |
| 397 assertTrue(CodedOutputStream.computeUInt32SizeNoTag(string.length()) | 388 assertTrue(CodedOutputStream.computeUInt32SizeNoTag(string.length()) |
| 398 != CodedOutputStream.computeUInt32SizeNoTag(string.length() * Utf8.MAX_B
YTES_PER_CHAR)); | 389 != CodedOutputStream.computeUInt32SizeNoTag(string.length() * Utf8.MAX_B
YTES_PER_CHAR)); |
| 399 | 390 |
| 400 coder.stream().writeStringNoTag(string); | 391 coder.stream().writeStringNoTag(string); |
| 401 coder.stream().flush(); | |
| 402 int stringSize = CodedOutputStream.computeStringSizeNoTag(string); | 392 int stringSize = CodedOutputStream.computeStringSizeNoTag(string); |
| 403 | 393 |
| 404 // Verify that the total bytes written is correct | 394 // Verify that the total bytes written is correct |
| 405 assertEquals((value.length * 1024) + stringSize, coder.stream().getTotalByte
sWritten()); | 395 assertEquals((value.length * 1024) + stringSize, coder.stream().getTotalByte
sWritten()); |
| 406 } | 396 } |
| 407 | 397 |
| 408 // TODO(dweis): Write a comprehensive test suite for CodedOutputStream that co
vers more than just | 398 // TODO(dweis): Write a comprehensive test suite for CodedOutputStream that co
vers more than just |
| 409 // this case. | 399 // this case. |
| 410 public void testWriteStringNoTag_fastpath() throws Exception { | 400 public void testWriteStringNoTag_fastpath() throws Exception { |
| 411 int bufferSize = 153; | 401 int bufferSize = 153; |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 481 byte[] result = outputStream.toByteArray(); | 471 byte[] result = outputStream.toByteArray(); |
| 482 assertEquals(6, result.length); | 472 assertEquals(6, result.length); |
| 483 for (int i = 0; i < 5; i++) { | 473 for (int i = 0; i < 5; i++) { |
| 484 assertEquals(value[i], result[i]); | 474 assertEquals(value[i], result[i]); |
| 485 } | 475 } |
| 486 assertEquals(value[2], result[5]); | 476 assertEquals(value[2], result[5]); |
| 487 } | 477 } |
| 488 | 478 |
| 489 public void testWriteByteArrayWithOffsets() throws Exception { | 479 public void testWriteByteArrayWithOffsets() throws Exception { |
| 490 byte[] fullArray = bytes(0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88); | 480 byte[] fullArray = bytes(0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88); |
| 491 for (OutputType type : new OutputType[] {OutputType.ARRAY}) { | 481 byte[] destination = new byte[4]; |
| 492 Coder coder = type.newCoder(4); | 482 CodedOutputStream codedStream = CodedOutputStream.newInstance(destination); |
| 493 coder.stream().writeByteArrayNoTag(fullArray, 2, 2); | 483 codedStream.writeByteArrayNoTag(fullArray, 2, 2); |
| 494 assertEqualBytes(type, bytes(0x02, 0x33, 0x44), coder.toByteArray()); | 484 assertEqualBytes(OutputType.ARRAY, bytes(0x02, 0x33, 0x44, 0x00), destinatio
n); |
| 495 assertEquals(3, coder.stream().getTotalBytesWritten()); | 485 assertEquals(3, codedStream.getTotalBytesWritten()); |
| 496 } | |
| 497 } | 486 } |
| 498 | 487 |
| 499 public void testSerializeUtf8_MultipleSmallWrites() throws Exception { | 488 public void testSerializeUtf8_MultipleSmallWrites() throws Exception { |
| 500 final String source = "abcdefghijklmnopqrstuvwxyz"; | 489 final String source = "abcdefghijklmnopqrstuvwxyz"; |
| 501 | 490 |
| 502 // Generate the expected output if the source string is written 2 bytes at a
time. | 491 // Generate the expected output if the source string is written 2 bytes at a
time. |
| 503 ByteArrayOutputStream expectedBytesStream = new ByteArrayOutputStream(); | 492 ByteArrayOutputStream expectedBytesStream = new ByteArrayOutputStream(); |
| 504 for (int pos = 0; pos < source.length(); pos += 2) { | 493 for (int pos = 0; pos < source.length(); pos += 2) { |
| 505 String substr = source.substring(pos, pos + 2); | 494 String substr = source.substring(pos, pos + 2); |
| 506 expectedBytesStream.write(2); | 495 expectedBytesStream.write(2); |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 565 /** Regression test for https://github.com/google/protobuf/issues/292 */ | 554 /** Regression test for https://github.com/google/protobuf/issues/292 */ |
| 566 public void testCorrectExceptionThrowWhenEncodingStringsWithoutEnoughSpace() t
hrows Exception { | 555 public void testCorrectExceptionThrowWhenEncodingStringsWithoutEnoughSpace() t
hrows Exception { |
| 567 String testCase = "Foooooooo"; | 556 String testCase = "Foooooooo"; |
| 568 assertEquals( | 557 assertEquals( |
| 569 CodedOutputStream.computeUInt32SizeNoTag(testCase.length()), | 558 CodedOutputStream.computeUInt32SizeNoTag(testCase.length()), |
| 570 CodedOutputStream.computeUInt32SizeNoTag(testCase.length() * 3)); | 559 CodedOutputStream.computeUInt32SizeNoTag(testCase.length() * 3)); |
| 571 assertEquals(11, CodedOutputStream.computeStringSize(1, testCase)); | 560 assertEquals(11, CodedOutputStream.computeStringSize(1, testCase)); |
| 572 // Tag is one byte, varint describing string length is 1 byte, string length
is 9 bytes. | 561 // Tag is one byte, varint describing string length is 1 byte, string length
is 9 bytes. |
| 573 // An array of size 1 will cause a failure when trying to write the varint. | 562 // An array of size 1 will cause a failure when trying to write the varint. |
| 574 for (OutputType outputType : | 563 for (OutputType outputType : |
| 575 new OutputType[] { | 564 new OutputType[] {OutputType.ARRAY, OutputType.NIO_HEAP, OutputType.NIO_
DIRECT}) { |
| 576 OutputType.ARRAY, | |
| 577 OutputType.NIO_HEAP, | |
| 578 OutputType.NIO_DIRECT_SAFE, | |
| 579 OutputType.NIO_DIRECT_UNSAFE | |
| 580 }) { | |
| 581 for (int i = 0; i < 11; i++) { | 565 for (int i = 0; i < 11; i++) { |
| 582 Coder coder = outputType.newCoder(i); | 566 Coder coder = outputType.newCoder(i); |
| 583 try { | 567 try { |
| 584 coder.stream().writeString(1, testCase); | 568 coder.stream().writeString(1, testCase); |
| 585 fail("Should have thrown an out of space exception"); | 569 fail("Should have thrown an out of space exception"); |
| 586 } catch (CodedOutputStream.OutOfSpaceException expected) { | 570 } catch (CodedOutputStream.OutOfSpaceException expected) { |
| 587 } | 571 } |
| 588 } | 572 } |
| 589 } | 573 } |
| 590 } | 574 } |
| (...skipping 17 matching lines...) Expand all Loading... |
| 608 for (int i : lengths) { | 592 for (int i : lengths) { |
| 609 testEncodingOfString(outputType, 'q', i); // 1 byte per char | 593 testEncodingOfString(outputType, 'q', i); // 1 byte per char |
| 610 testEncodingOfString(outputType, '\u07FF', i); // 2 bytes per char | 594 testEncodingOfString(outputType, '\u07FF', i); // 2 bytes per char |
| 611 testEncodingOfString(outputType, '\u0981', i); // 3 bytes per char | 595 testEncodingOfString(outputType, '\u0981', i); // 3 bytes per char |
| 612 } | 596 } |
| 613 } | 597 } |
| 614 } | 598 } |
| 615 | 599 |
| 616 public void testNioEncodersWithInitialOffsets() throws Exception { | 600 public void testNioEncodersWithInitialOffsets() throws Exception { |
| 617 String value = "abc"; | 601 String value = "abc"; |
| 618 for (Coder coder : | 602 for (Coder coder : new Coder[] {new NioHeapCoder(10, 2), new NioDirectCoder(
10, 2)}) { |
| 619 new Coder[] { | |
| 620 new NioHeapCoder(10, 2), new NioDirectCoder(10, 2, false), new NioDire
ctCoder(10, 2, true) | |
| 621 }) { | |
| 622 coder.stream().writeStringNoTag(value); | 603 coder.stream().writeStringNoTag(value); |
| 623 coder.stream().flush(); | 604 coder.stream().flush(); |
| 624 assertEqualBytes(coder.getOutputType(), new byte[] {3, 'a', 'b', 'c'}, cod
er.toByteArray()); | 605 assertEqualBytes(coder.getOutputType(), new byte[]{3, 'a', 'b', 'c'}, code
r.toByteArray()); |
| 625 } | 606 } |
| 626 } | 607 } |
| 627 | 608 |
| 628 /** | 609 /** |
| 629 * Parses the given bytes using writeRawLittleEndian32() and checks | 610 * Parses the given bytes using writeRawLittleEndian32() and checks |
| 630 * that the result matches the given value. | 611 * that the result matches the given value. |
| 631 */ | 612 */ |
| 632 private static void assertWriteLittleEndian32(byte[] data, int value) throws E
xception { | 613 private static void assertWriteLittleEndian32(byte[] data, int value) throws E
xception { |
| 633 for (OutputType outputType : OutputType.values()) { | 614 for (OutputType outputType : OutputType.values()) { |
| 634 Coder coder = outputType.newCoder(data.length); | 615 Coder coder = outputType.newCoder(data.length); |
| (...skipping 151 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 786 coder.stream().writeUInt32NoTag((int) value); | 767 coder.stream().writeUInt32NoTag((int) value); |
| 787 coder.stream().flush(); | 768 coder.stream().flush(); |
| 788 byte[] bytes = coder.toByteArray(); | 769 byte[] bytes = coder.toByteArray(); |
| 789 assertEquals( | 770 assertEquals( |
| 790 outputType.name(), bytes.length, CodedOutputStream.computeUInt32SizeNo
Tag((int) value)); | 771 outputType.name(), bytes.length, CodedOutputStream.computeUInt32SizeNo
Tag((int) value)); |
| 791 CodedInputStream input = CodedInputStream.newInstance(new ByteArrayInputSt
ream(bytes)); | 772 CodedInputStream input = CodedInputStream.newInstance(new ByteArrayInputSt
ream(bytes)); |
| 792 assertEquals(outputType.name(), value, input.readRawVarint32()); | 773 assertEquals(outputType.name(), value, input.readRawVarint32()); |
| 793 } | 774 } |
| 794 } | 775 } |
| 795 } | 776 } |
| OLD | NEW |