• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (C) 2018 The Android Open Source Project
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //      http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #include <android-base/file.h>
16 #include <android-base/test_utils.h>
17 #include <android/util/protobuf.h>
18 #include <android/util/ProtoOutputStream.h>
19 #include <gmock/gmock.h>
20 #include <gtest/gtest.h>
21 
22 #include "frameworks/base/libs/protoutil/tests/test.pb.h"
23 
24 using android::sp;
25 using namespace android::base;
26 using namespace android::util;
27 using ::testing::StrEq;
28 
flushToString(ProtoOutputStream * proto)29 static std::string flushToString(ProtoOutputStream* proto) {
30     TemporaryFile tf;
31     std::string content;
32 
33     EXPECT_NE(tf.fd, -1);
34     EXPECT_TRUE(proto->flush(tf.fd));
35     EXPECT_TRUE(ReadFileToString(tf.path, &content));
36     return content;
37 }
38 
iterateToString(ProtoOutputStream * proto)39 static std::string iterateToString(ProtoOutputStream* proto) {
40     std::string content;
41     content.reserve(proto->size());
42     sp<ProtoReader> reader = proto->data();
43     while (reader->hasNext()) {
44         content.push_back(reader->next());
45     }
46     return content;
47 }
48 
TEST(ProtoOutputStreamTest,Primitives)49 TEST(ProtoOutputStreamTest, Primitives) {
50     std::string s = "hello";
51     const char b[5] = { 'a', 'p', 'p', 'l', 'e' };
52 
53     ProtoOutputStream proto;
54     EXPECT_TRUE(proto.write(FIELD_TYPE_INT32 | PrimitiveProto::kValInt32FieldNumber, 123));
55     EXPECT_TRUE(proto.write(FIELD_TYPE_INT64 | PrimitiveProto::kValInt64FieldNumber, -1LL));
56     EXPECT_TRUE(proto.write(FIELD_TYPE_FLOAT | PrimitiveProto::kValFloatFieldNumber, -23.5f));
57     EXPECT_TRUE(proto.write(FIELD_TYPE_DOUBLE | PrimitiveProto::kValDoubleFieldNumber, 324.5));
58     EXPECT_TRUE(proto.write(FIELD_TYPE_UINT32 | PrimitiveProto::kValUint32FieldNumber, 3424));
59     EXPECT_TRUE(proto.write(FIELD_TYPE_UINT64 | PrimitiveProto::kValUint64FieldNumber, 57LL));
60     EXPECT_TRUE(proto.write(FIELD_TYPE_FIXED32 | PrimitiveProto::kValFixed32FieldNumber, -20));
61     EXPECT_TRUE(proto.write(FIELD_TYPE_FIXED64 | PrimitiveProto::kValFixed64FieldNumber, -37LL));
62     EXPECT_TRUE(proto.write(FIELD_TYPE_BOOL | PrimitiveProto::kValBoolFieldNumber, true));
63     EXPECT_TRUE(proto.write(FIELD_TYPE_STRING | PrimitiveProto::kValStringFieldNumber, s));
64     EXPECT_TRUE(proto.write(FIELD_TYPE_BYTES | PrimitiveProto::kValBytesFieldNumber, b, 5));
65     EXPECT_TRUE(proto.write(FIELD_TYPE_SFIXED32 | PrimitiveProto::kValSfixed32FieldNumber, 63));
66     EXPECT_TRUE(proto.write(FIELD_TYPE_SFIXED64 | PrimitiveProto::kValSfixed64FieldNumber, -54));
67     EXPECT_TRUE(proto.write(FIELD_TYPE_SINT32 | PrimitiveProto::kValSint32FieldNumber, -533));
68     EXPECT_TRUE(proto.write(FIELD_TYPE_SINT64 | PrimitiveProto::kValSint64FieldNumber, -61224762453LL));
69     EXPECT_TRUE(proto.write(FIELD_TYPE_ENUM | PrimitiveProto::kValEnumFieldNumber, 2));
70 
71     PrimitiveProto primitives;
72     ASSERT_TRUE(primitives.ParseFromString(flushToString(&proto)));
73     EXPECT_EQ(primitives.val_int32(), 123);
74     EXPECT_EQ(primitives.val_int64(), -1);
75     EXPECT_EQ(primitives.val_float(), -23.5f);
76     EXPECT_EQ(primitives.val_double(), 324.5f);
77     EXPECT_EQ(primitives.val_uint32(), 3424);
78     EXPECT_EQ(primitives.val_uint64(), 57);
79     EXPECT_EQ(primitives.val_fixed32(), -20);
80     EXPECT_EQ(primitives.val_fixed64(), -37);
81     EXPECT_EQ(primitives.val_bool(), true);
82     EXPECT_THAT(primitives.val_string(), StrEq(s.c_str()));
83     EXPECT_THAT(primitives.val_bytes(), StrEq("apple"));
84     EXPECT_EQ(primitives.val_sfixed32(), 63);
85     EXPECT_EQ(primitives.val_sfixed64(), -54);
86     EXPECT_EQ(primitives.val_sint32(), -533);
87     EXPECT_EQ(primitives.val_sint64(), -61224762453LL);
88     EXPECT_EQ(primitives.val_enum(), PrimitiveProto_Count_TWO);
89 }
90 
TEST(ProtoOutputStreamTest,SerializeToStringPrimitives)91 TEST(ProtoOutputStreamTest, SerializeToStringPrimitives) {
92     std::string s = "hello";
93     const char b[5] = { 'a', 'p', 'p', 'l', 'e' };
94 
95     ProtoOutputStream proto;
96     EXPECT_TRUE(proto.write(FIELD_TYPE_INT32 | PrimitiveProto::kValInt32FieldNumber, 123));
97     EXPECT_TRUE(proto.write(FIELD_TYPE_INT64 | PrimitiveProto::kValInt64FieldNumber, -1LL));
98     EXPECT_TRUE(proto.write(FIELD_TYPE_FLOAT | PrimitiveProto::kValFloatFieldNumber, -23.5f));
99     EXPECT_TRUE(proto.write(FIELD_TYPE_DOUBLE | PrimitiveProto::kValDoubleFieldNumber, 324.5));
100     EXPECT_TRUE(proto.write(FIELD_TYPE_UINT32 | PrimitiveProto::kValUint32FieldNumber, 3424));
101     EXPECT_TRUE(proto.write(FIELD_TYPE_UINT64 | PrimitiveProto::kValUint64FieldNumber, 57LL));
102     EXPECT_TRUE(proto.write(FIELD_TYPE_FIXED32 | PrimitiveProto::kValFixed32FieldNumber, -20));
103     EXPECT_TRUE(proto.write(FIELD_TYPE_FIXED64 | PrimitiveProto::kValFixed64FieldNumber, -37LL));
104     EXPECT_TRUE(proto.write(FIELD_TYPE_BOOL | PrimitiveProto::kValBoolFieldNumber, true));
105     EXPECT_TRUE(proto.write(FIELD_TYPE_STRING | PrimitiveProto::kValStringFieldNumber, s));
106     EXPECT_TRUE(proto.write(FIELD_TYPE_BYTES | PrimitiveProto::kValBytesFieldNumber, b, 5));
107     EXPECT_TRUE(proto.write(FIELD_TYPE_SFIXED32 | PrimitiveProto::kValSfixed32FieldNumber, 63));
108     EXPECT_TRUE(proto.write(FIELD_TYPE_SFIXED64 | PrimitiveProto::kValSfixed64FieldNumber, -54));
109     EXPECT_TRUE(proto.write(FIELD_TYPE_SINT32 | PrimitiveProto::kValSint32FieldNumber, -533));
110     EXPECT_TRUE(proto.write(FIELD_TYPE_SINT64 | PrimitiveProto::kValSint64FieldNumber, -61224762453LL));
111     EXPECT_TRUE(proto.write(FIELD_TYPE_ENUM | PrimitiveProto::kValEnumFieldNumber, 2));
112 
113     PrimitiveProto primitives;
114     std::string serialized;
115     ASSERT_TRUE(proto.serializeToString(&serialized));
116     ASSERT_TRUE(primitives.ParseFromString(serialized));
117     EXPECT_EQ(primitives.val_int32(), 123);
118     EXPECT_EQ(primitives.val_int64(), -1);
119     EXPECT_EQ(primitives.val_float(), -23.5f);
120     EXPECT_EQ(primitives.val_double(), 324.5f);
121     EXPECT_EQ(primitives.val_uint32(), 3424);
122     EXPECT_EQ(primitives.val_uint64(), 57);
123     EXPECT_EQ(primitives.val_fixed32(), -20);
124     EXPECT_EQ(primitives.val_fixed64(), -37);
125     EXPECT_EQ(primitives.val_bool(), true);
126     EXPECT_THAT(primitives.val_string(), StrEq(s.c_str()));
127     EXPECT_THAT(primitives.val_bytes(), StrEq("apple"));
128     EXPECT_EQ(primitives.val_sfixed32(), 63);
129     EXPECT_EQ(primitives.val_sfixed64(), -54);
130     EXPECT_EQ(primitives.val_sint32(), -533);
131     EXPECT_EQ(primitives.val_sint64(), -61224762453LL);
132     EXPECT_EQ(primitives.val_enum(), PrimitiveProto_Count_TWO);
133 }
134 
TEST(ProtoOutputStreamTest,SerializeToVectorPrimitives)135 TEST(ProtoOutputStreamTest, SerializeToVectorPrimitives) {
136     std::string s = "hello";
137     const char b[5] = { 'a', 'p', 'p', 'l', 'e' };
138 
139     ProtoOutputStream proto;
140     EXPECT_TRUE(proto.write(FIELD_TYPE_INT32 | PrimitiveProto::kValInt32FieldNumber, 123));
141     EXPECT_TRUE(proto.write(FIELD_TYPE_INT64 | PrimitiveProto::kValInt64FieldNumber, -1LL));
142     EXPECT_TRUE(proto.write(FIELD_TYPE_FLOAT | PrimitiveProto::kValFloatFieldNumber, -23.5f));
143     EXPECT_TRUE(proto.write(FIELD_TYPE_DOUBLE | PrimitiveProto::kValDoubleFieldNumber, 324.5));
144     EXPECT_TRUE(proto.write(FIELD_TYPE_UINT32 | PrimitiveProto::kValUint32FieldNumber, 3424));
145     EXPECT_TRUE(proto.write(FIELD_TYPE_UINT64 | PrimitiveProto::kValUint64FieldNumber, 57LL));
146     EXPECT_TRUE(proto.write(FIELD_TYPE_FIXED32 | PrimitiveProto::kValFixed32FieldNumber, -20));
147     EXPECT_TRUE(proto.write(FIELD_TYPE_FIXED64 | PrimitiveProto::kValFixed64FieldNumber, -37LL));
148     EXPECT_TRUE(proto.write(FIELD_TYPE_BOOL | PrimitiveProto::kValBoolFieldNumber, true));
149     EXPECT_TRUE(proto.write(FIELD_TYPE_STRING | PrimitiveProto::kValStringFieldNumber, s));
150     EXPECT_TRUE(proto.write(FIELD_TYPE_BYTES | PrimitiveProto::kValBytesFieldNumber, b, 5));
151     EXPECT_TRUE(proto.write(FIELD_TYPE_SFIXED32 | PrimitiveProto::kValSfixed32FieldNumber, 63));
152     EXPECT_TRUE(proto.write(FIELD_TYPE_SFIXED64 | PrimitiveProto::kValSfixed64FieldNumber, -54));
153     EXPECT_TRUE(proto.write(FIELD_TYPE_SINT32 | PrimitiveProto::kValSint32FieldNumber, -533));
154     EXPECT_TRUE(proto.write(FIELD_TYPE_SINT64 | PrimitiveProto::kValSint64FieldNumber, -61224762453LL));
155     EXPECT_TRUE(proto.write(FIELD_TYPE_ENUM | PrimitiveProto::kValEnumFieldNumber, 2));
156 
157     PrimitiveProto primitives;
158     std::vector<uint8_t> vec;
159     ASSERT_TRUE(proto.serializeToVector(&vec));
160 
161     std::string serialized(vec.data(), vec.data() + vec.size());
162     ASSERT_TRUE(primitives.ParseFromString(serialized));
163 
164     EXPECT_EQ(primitives.val_int32(), 123);
165     EXPECT_EQ(primitives.val_int64(), -1);
166     EXPECT_EQ(primitives.val_float(), -23.5f);
167     EXPECT_EQ(primitives.val_double(), 324.5f);
168     EXPECT_EQ(primitives.val_uint32(), 3424);
169     EXPECT_EQ(primitives.val_uint64(), 57);
170     EXPECT_EQ(primitives.val_fixed32(), -20);
171     EXPECT_EQ(primitives.val_fixed64(), -37);
172     EXPECT_EQ(primitives.val_bool(), true);
173     EXPECT_THAT(primitives.val_string(), StrEq(s.c_str()));
174     EXPECT_THAT(primitives.val_bytes(), StrEq("apple"));
175     EXPECT_EQ(primitives.val_sfixed32(), 63);
176     EXPECT_EQ(primitives.val_sfixed64(), -54);
177     EXPECT_EQ(primitives.val_sint32(), -533);
178     EXPECT_EQ(primitives.val_sint64(), -61224762453LL);
179     EXPECT_EQ(primitives.val_enum(), PrimitiveProto_Count_TWO);
180 }
181 
TEST(ProtoOutputStreamTest,Complex)182 TEST(ProtoOutputStreamTest, Complex) {
183     std::string name1 = "cat";
184     std::string name2 = "dog";
185     const char data1[6] = { 'f', 'u', 'n', 'n', 'y', '!' };
186     const char data2[4] = { 'f', 'o', 'o', 'd' };
187 
188     ProtoOutputStream proto;
189     EXPECT_TRUE(proto.write(FIELD_TYPE_INT32 | ComplexProto::kIntsFieldNumber, 23));
190     EXPECT_TRUE(proto.write(FIELD_TYPE_INT32 | ComplexProto::kIntsFieldNumber, 101));
191     EXPECT_TRUE(proto.write(FIELD_TYPE_INT32 | ComplexProto::kIntsFieldNumber, -72));
192     uint64_t token1 = proto.start(FIELD_TYPE_MESSAGE | ComplexProto::kLogsFieldNumber);
193     EXPECT_TRUE(proto.write(FIELD_TYPE_INT32 | ComplexProto::Log::kIdFieldNumber, 12));
194     EXPECT_TRUE(proto.write(FIELD_TYPE_STRING | ComplexProto::Log::kNameFieldNumber, name1));
195     // specify the length to test the write(id, bytes, length) function.
196     EXPECT_TRUE(proto.write(FIELD_TYPE_BYTES | ComplexProto::Log::kDataFieldNumber, data1, 5));
197     proto.end(token1);
198     uint64_t token2 = proto.start(FIELD_TYPE_MESSAGE | ComplexProto::kLogsFieldNumber);
199     EXPECT_TRUE(proto.write(FIELD_TYPE_INT32 | ComplexProto::Log::kIdFieldNumber, 98));
200     EXPECT_TRUE(proto.write(FIELD_TYPE_STRING | ComplexProto::Log::kNameFieldNumber, name2));
201     EXPECT_TRUE(proto.write(FIELD_TYPE_BYTES | ComplexProto::Log::kDataFieldNumber, data2, 4));
202     proto.end(token2);
203 
204     ComplexProto complex;
205     ASSERT_TRUE(complex.ParseFromString(iterateToString(&proto)));
206     EXPECT_EQ(complex.ints_size(), 3);
207     EXPECT_EQ(complex.ints(0), 23);
208     EXPECT_EQ(complex.ints(1), 101);
209     EXPECT_EQ(complex.ints(2), -72);
210     EXPECT_EQ(complex.logs_size(), 2);
211     ComplexProto::Log log1 = complex.logs(0);
212     EXPECT_EQ(log1.id(), 12);
213     EXPECT_THAT(log1.name(), StrEq(name1.c_str()));
214     EXPECT_THAT(log1.data(), StrEq("funny")); // should not contain '!'
215     ComplexProto::Log log2 = complex.logs(1);
216     EXPECT_EQ(log2.id(), 98);
217     EXPECT_THAT(log2.name(), StrEq(name2.c_str()));
218     EXPECT_THAT(log2.data(), StrEq("food"));
219 }
220 
TEST(ProtoOutputStreamTest,SerializeToStringComplex)221 TEST(ProtoOutputStreamTest, SerializeToStringComplex) {
222     std::string name1 = "cat";
223     std::string name2 = "dog";
224     const char data1[6] = { 'f', 'u', 'n', 'n', 'y', '!' };
225     const char data2[4] = { 'f', 'o', 'o', 'd' };
226 
227     ProtoOutputStream proto;
228     EXPECT_TRUE(proto.write(FIELD_TYPE_INT32 | ComplexProto::kIntsFieldNumber, 23));
229     EXPECT_TRUE(proto.write(FIELD_TYPE_INT32 | ComplexProto::kIntsFieldNumber, 101));
230     EXPECT_TRUE(proto.write(FIELD_TYPE_INT32 | ComplexProto::kIntsFieldNumber, -72));
231     uint64_t token1 = proto.start(FIELD_TYPE_MESSAGE | ComplexProto::kLogsFieldNumber);
232     EXPECT_TRUE(proto.write(FIELD_TYPE_INT32 | ComplexProto::Log::kIdFieldNumber, 12));
233     EXPECT_TRUE(proto.write(FIELD_TYPE_STRING | ComplexProto::Log::kNameFieldNumber, name1));
234     // specify the length to test the write(id, bytes, length) function.
235     EXPECT_TRUE(proto.write(FIELD_TYPE_BYTES | ComplexProto::Log::kDataFieldNumber, data1, 5));
236     proto.end(token1);
237     uint64_t token2 = proto.start(FIELD_TYPE_MESSAGE | ComplexProto::kLogsFieldNumber);
238     EXPECT_TRUE(proto.write(FIELD_TYPE_INT32 | ComplexProto::Log::kIdFieldNumber, 98));
239     EXPECT_TRUE(proto.write(FIELD_TYPE_STRING | ComplexProto::Log::kNameFieldNumber, name2));
240     EXPECT_TRUE(proto.write(FIELD_TYPE_BYTES | ComplexProto::Log::kDataFieldNumber, data2, 4));
241     proto.end(token2);
242 
243     ComplexProto complex;
244     std::string serialized;
245     ASSERT_TRUE(proto.serializeToString(&serialized));
246     ASSERT_TRUE(complex.ParseFromString(serialized));
247     EXPECT_EQ(complex.ints_size(), 3);
248     EXPECT_EQ(complex.ints(0), 23);
249     EXPECT_EQ(complex.ints(1), 101);
250     EXPECT_EQ(complex.ints(2), -72);
251     EXPECT_EQ(complex.logs_size(), 2);
252     ComplexProto::Log log1 = complex.logs(0);
253     EXPECT_EQ(log1.id(), 12);
254     EXPECT_THAT(log1.name(), StrEq(name1.c_str()));
255     EXPECT_THAT(log1.data(), StrEq("funny")); // should not contain '!'
256     ComplexProto::Log log2 = complex.logs(1);
257     EXPECT_EQ(log2.id(), 98);
258     EXPECT_THAT(log2.name(), StrEq(name2.c_str()));
259     EXPECT_THAT(log2.data(), StrEq("food"));
260 }
261 
TEST(ProtoOutputStreamTest,Reusability)262 TEST(ProtoOutputStreamTest, Reusability) {
263     ProtoOutputStream proto;
264     EXPECT_TRUE(proto.write(FIELD_TYPE_INT32 | ComplexProto::kIntsFieldNumber, 32));
265     EXPECT_TRUE(proto.write(FIELD_TYPE_INT32 | ComplexProto::kIntsFieldNumber, 15));
266     EXPECT_EQ(proto.bytesWritten(), 4);
267     EXPECT_EQ(proto.size(), 4);
268     // Can't write to proto after compact
269     EXPECT_FALSE(proto.write(FIELD_TYPE_INT32 | ComplexProto::kIntsFieldNumber, 94));
270 
271     ComplexProto beforeClear;
272     ASSERT_TRUE(beforeClear.ParseFromString(flushToString(&proto)));
273     EXPECT_EQ(beforeClear.ints_size(), 2);
274     EXPECT_EQ(beforeClear.ints(0), 32);
275     EXPECT_EQ(beforeClear.ints(1), 15);
276 
277     proto.clear();
278     EXPECT_EQ(proto.bytesWritten(), 0);
279     EXPECT_TRUE(proto.write(FIELD_TYPE_INT32 | ComplexProto::kIntsFieldNumber, 1076));
280 
281     ComplexProto afterClear;
282     ASSERT_TRUE(afterClear.ParseFromString(flushToString(&proto)));
283     EXPECT_EQ(afterClear.ints_size(), 1);
284     EXPECT_EQ(afterClear.ints(0), 1076);
285 }
286 
TEST(ProtoOutputStreamTest,AdvancedEncoding)287 TEST(ProtoOutputStreamTest, AdvancedEncoding) {
288     ProtoOutputStream proto;
289     proto.writeRawVarint((ComplexProto::kIntsFieldNumber << FIELD_ID_SHIFT) + WIRE_TYPE_VARINT);
290     proto.writeRawVarint(UINT64_C(-123809234));
291     proto.writeLengthDelimitedHeader(ComplexProto::kLogsFieldNumber, 8);
292     proto.writeRawByte((ComplexProto::Log::kDataFieldNumber << FIELD_ID_SHIFT) + WIRE_TYPE_LENGTH_DELIMITED);
293     proto.writeRawByte(6);
294     proto.writeRawByte('b');
295     proto.writeRawByte('a');
296     proto.writeRawByte('n');
297     proto.writeRawByte('a');
298     proto.writeRawByte('n');
299     proto.writeRawByte('a');
300     uint64_t token = proto.start(FIELD_TYPE_MESSAGE | ComplexProto::kLogsFieldNumber);
301     proto.write(FIELD_TYPE_INT32 | ComplexProto::Log::kIdFieldNumber, 14);
302     proto.end(token);
303 
304     ComplexProto complex;
305     ASSERT_TRUE(complex.ParseFromString(flushToString(&proto)));
306     EXPECT_EQ(complex.ints_size(), 1);
307     EXPECT_EQ(complex.ints(0), UINT64_C(-123809234));
308     EXPECT_EQ(complex.logs_size(), 2);
309     ComplexProto::Log log1 = complex.logs(0);
310     EXPECT_FALSE(log1.has_id());
311     EXPECT_FALSE(log1.has_name());
312     EXPECT_THAT(log1.data(), StrEq("banana"));
313     ComplexProto::Log log2 = complex.logs(1);
314     EXPECT_EQ(log2.id(), 14);
315     EXPECT_FALSE(log2.has_name());
316     EXPECT_FALSE(log2.has_data());
317 }
318 
TEST(ProtoOutputStreamTest,InvalidTypes)319 TEST(ProtoOutputStreamTest, InvalidTypes) {
320     ProtoOutputStream proto;
321     EXPECT_FALSE(proto.write(FIELD_TYPE_UNKNOWN | PrimitiveProto::kValInt32FieldNumber, 790));
322     EXPECT_FALSE(proto.write(FIELD_TYPE_ENUM | PrimitiveProto::kValEnumFieldNumber, 234.34));
323     EXPECT_FALSE(proto.write(FIELD_TYPE_BOOL | PrimitiveProto::kValBoolFieldNumber, 18.73f));
324     EXPECT_EQ(proto.size(), 0);
325 }
326 
TEST(ProtoOutputStreamTest,NoEndCalled)327 TEST(ProtoOutputStreamTest, NoEndCalled) {
328     ProtoOutputStream proto;
329     proto.start(FIELD_TYPE_MESSAGE | ComplexProto::kLogsFieldNumber);
330     proto.write(FIELD_TYPE_INT32 | ComplexProto::Log::kIdFieldNumber, 53);
331     // no proto.end called
332     EXPECT_NE(proto.bytesWritten(), 0);
333     EXPECT_EQ(proto.size(), 0);
334     EXPECT_FALSE(proto.flush(STDOUT_FILENO));
335 }
336 
337 
TEST(ProtoOutputStreamTest,TwoEndCalled)338 TEST(ProtoOutputStreamTest, TwoEndCalled) {
339     ProtoOutputStream proto;
340     uint64_t token = proto.start(FIELD_TYPE_MESSAGE | ComplexProto::kLogsFieldNumber);
341     proto.write(FIELD_TYPE_INT32 | ComplexProto::Log::kIdFieldNumber, 53);
342     proto.end(token);
343     proto.end(token);
344     EXPECT_NE(proto.bytesWritten(), 0);
345     EXPECT_EQ(proto.size(), 0);
346     EXPECT_FALSE(proto.flush(STDOUT_FILENO));
347 }
348 
TEST(ProtoOutputStreamTest,NoStartCalled)349 TEST(ProtoOutputStreamTest, NoStartCalled) {
350     ProtoOutputStream proto;
351     uint64_t wrongToken = UINT64_C(324536345);
352     // no proto.start called
353     proto.write(FIELD_TYPE_INT32 | ComplexProto::Log::kIdFieldNumber, 53);
354     proto.end(wrongToken);
355     EXPECT_NE(proto.bytesWritten(), 0);
356     EXPECT_EQ(proto.size(), 0);
357     EXPECT_FALSE(proto.flush(STDOUT_FILENO));
358 }
359