• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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