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