1 // Protocol Buffers - Google's data interchange format 2 // Copyright 2008 Google Inc. All rights reserved. 3 // 4 // Use of this source code is governed by a BSD-style 5 // license that can be found in the LICENSE file or at 6 // https://developers.google.com/open-source/licenses/bsd 7 8 package com.google.protobuf; 9 10 import static com.google.common.truth.Truth.assertThat; 11 12 import protobuf_unittest.UnittestProto; 13 import java.io.IOException; 14 import org.junit.Before; 15 import org.junit.Test; 16 import org.junit.runner.RunWith; 17 import org.junit.runners.JUnit4; 18 19 /** 20 * Tests to make sure the lazy conversion of UTF8-encoded byte arrays to strings works 21 * correctly. 22 */ 23 @RunWith(JUnit4.class) 24 public class LazyStringEndToEndTest { 25 26 private static final ByteString TEST_ALL_TYPES_SERIALIZED_WITH_ILLEGAL_UTF8 = 27 ByteString.copyFrom( 28 new byte[] { 29 114, 4, -1, 0, -1, 0, -30, 2, 4, -1, 30 0, -1, 0, -30, 2, 4, -1, 0, -1, 0, 31 }); 32 33 private ByteString encodedTestAllTypes; 34 35 @Before setUp()36 public void setUp() throws Exception { 37 this.encodedTestAllTypes = 38 UnittestProto.TestAllTypes.newBuilder() 39 .setOptionalString("foo") 40 .addRepeatedString("bar") 41 .addRepeatedString("baz") 42 .build() 43 .toByteString(); 44 } 45 46 /** Tests that an invalid UTF8 string will roundtrip through a parse and serialization. */ 47 @Test testParseAndSerialize()48 public void testParseAndSerialize() throws InvalidProtocolBufferException { 49 UnittestProto.TestAllTypes tV2 = 50 UnittestProto.TestAllTypes.parseFrom( 51 TEST_ALL_TYPES_SERIALIZED_WITH_ILLEGAL_UTF8, 52 ExtensionRegistryLite.getEmptyRegistry()); 53 ByteString bytes = tV2.toByteString(); 54 assertThat(bytes).isEqualTo(TEST_ALL_TYPES_SERIALIZED_WITH_ILLEGAL_UTF8); 55 56 String unused = tV2.getOptionalString(); 57 bytes = tV2.toByteString(); 58 assertThat(bytes).isEqualTo(TEST_ALL_TYPES_SERIALIZED_WITH_ILLEGAL_UTF8); 59 } 60 61 @Test testParseAndWrite()62 public void testParseAndWrite() throws IOException { 63 UnittestProto.TestAllTypes tV2 = 64 UnittestProto.TestAllTypes.parseFrom( 65 TEST_ALL_TYPES_SERIALIZED_WITH_ILLEGAL_UTF8, 66 ExtensionRegistryLite.getEmptyRegistry()); 67 byte[] sink = new byte[TEST_ALL_TYPES_SERIALIZED_WITH_ILLEGAL_UTF8.size()]; 68 CodedOutputStream outputStream = CodedOutputStream.newInstance(sink); 69 tV2.writeTo(outputStream); 70 outputStream.flush(); 71 assertThat(ByteString.copyFrom(sink)).isEqualTo(TEST_ALL_TYPES_SERIALIZED_WITH_ILLEGAL_UTF8); 72 } 73 74 @Test testCaching()75 public void testCaching() { 76 String a = "a"; 77 String b = "b"; 78 String c = "c"; 79 UnittestProto.TestAllTypes proto = 80 UnittestProto.TestAllTypes.newBuilder() 81 .setOptionalString(a) 82 .addRepeatedString(b) 83 .addRepeatedString(c) 84 .build(); 85 86 // String should be the one we passed it. 87 assertThat(proto.getOptionalString()).isSameInstanceAs(a); 88 assertThat(proto.getRepeatedString(0)).isSameInstanceAs(b); 89 assertThat(proto.getRepeatedString(1)).isSameInstanceAs(c); 90 91 // Ensure serialization keeps strings cached. 92 ByteString unused = proto.toByteString(); 93 94 // And now the string should stay cached. 95 assertThat(proto.getOptionalString()).isSameInstanceAs(a); 96 assertThat(proto.getRepeatedString(0)).isSameInstanceAs(b); 97 assertThat(proto.getRepeatedString(1)).isSameInstanceAs(c); 98 } 99 100 @Test testNoStringCachingIfOnlyBytesAccessed()101 public void testNoStringCachingIfOnlyBytesAccessed() throws Exception { 102 UnittestProto.TestAllTypes proto = 103 UnittestProto.TestAllTypes.parseFrom( 104 encodedTestAllTypes, ExtensionRegistryLite.getEmptyRegistry()); 105 ByteString optional = proto.getOptionalStringBytes(); 106 assertThat(proto.getOptionalStringBytes()).isSameInstanceAs(optional); 107 assertThat(proto.toBuilder().getOptionalStringBytes()).isSameInstanceAs(optional); 108 109 ByteString repeated0 = proto.getRepeatedStringBytes(0); 110 ByteString repeated1 = proto.getRepeatedStringBytes(1); 111 assertThat(proto.getRepeatedStringBytes(0)).isSameInstanceAs(repeated0); 112 assertThat(proto.getRepeatedStringBytes(1)).isSameInstanceAs(repeated1); 113 assertThat(proto.toBuilder().getRepeatedStringBytes(0)).isSameInstanceAs(repeated0); 114 assertThat(proto.toBuilder().getRepeatedStringBytes(1)).isSameInstanceAs(repeated1); 115 } 116 } 117