blob: 27ee13d4dfe179c0e4a769adc2e57d9db51f7547 [file] [log] [blame]
Yi Jinc3d4b282018-04-23 16:02:20 -07001// 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
24using namespace android::base;
25using namespace android::util;
26using ::testing::StrEq;
27
28static std::string flushToString(ProtoOutputStream* proto) {
29 TemporaryFile tf;
30 std::string content;
31
32 EXPECT_NE(tf.fd, -1);
33 EXPECT_TRUE(proto->flush(tf.fd));
34 EXPECT_TRUE(ReadFileToString(tf.path, &content));
35 return content;
36}
37
38static std::string iterateToString(ProtoOutputStream* proto) {
39 std::string content;
40 content.reserve(proto->size());
41 auto iter = proto->data();
42 while (iter.hasNext()) {
43 content.push_back(iter.next());
44 }
45 return content;
46}
47
48TEST(ProtoOutputStreamTest, Primitives) {
49 std::string s = "hello";
50 const char b[5] = { 'a', 'p', 'p', 'l', 'e' };
51
52 ProtoOutputStream proto;
53 EXPECT_TRUE(proto.write(FIELD_TYPE_INT32 | PrimitiveProto::kValInt32FieldNumber, 123));
54 EXPECT_TRUE(proto.write(FIELD_TYPE_INT64 | PrimitiveProto::kValInt64FieldNumber, -1LL));
55 EXPECT_TRUE(proto.write(FIELD_TYPE_FLOAT | PrimitiveProto::kValFloatFieldNumber, -23.5f));
56 EXPECT_TRUE(proto.write(FIELD_TYPE_DOUBLE | PrimitiveProto::kValDoubleFieldNumber, 324.5));
57 EXPECT_TRUE(proto.write(FIELD_TYPE_UINT32 | PrimitiveProto::kValUint32FieldNumber, 3424));
58 EXPECT_TRUE(proto.write(FIELD_TYPE_UINT64 | PrimitiveProto::kValUint64FieldNumber, 57LL));
59 EXPECT_TRUE(proto.write(FIELD_TYPE_FIXED32 | PrimitiveProto::kValFixed32FieldNumber, -20));
60 EXPECT_TRUE(proto.write(FIELD_TYPE_FIXED64 | PrimitiveProto::kValFixed64FieldNumber, -37LL));
61 EXPECT_TRUE(proto.write(FIELD_TYPE_BOOL | PrimitiveProto::kValBoolFieldNumber, true));
62 EXPECT_TRUE(proto.write(FIELD_TYPE_STRING | PrimitiveProto::kValStringFieldNumber, s));
63 EXPECT_TRUE(proto.write(FIELD_TYPE_BYTES | PrimitiveProto::kValBytesFieldNumber, b, 5));
64 EXPECT_TRUE(proto.write(FIELD_TYPE_SFIXED32 | PrimitiveProto::kValSfixed32FieldNumber, 63));
65 EXPECT_TRUE(proto.write(FIELD_TYPE_SFIXED64 | PrimitiveProto::kValSfixed64FieldNumber, -54));
66 EXPECT_TRUE(proto.write(FIELD_TYPE_SINT32 | PrimitiveProto::kValSint32FieldNumber, -533));
67 EXPECT_TRUE(proto.write(FIELD_TYPE_SINT64 | PrimitiveProto::kValSint64FieldNumber, -61224762453LL));
68 EXPECT_TRUE(proto.write(FIELD_TYPE_ENUM | PrimitiveProto::kValEnumFieldNumber, 2));
69
70 PrimitiveProto primitives;
71 ASSERT_TRUE(primitives.ParseFromString(flushToString(&proto)));
72 EXPECT_EQ(primitives.val_int32(), 123);
73 EXPECT_EQ(primitives.val_int64(), -1);
74 EXPECT_EQ(primitives.val_float(), -23.5f);
75 EXPECT_EQ(primitives.val_double(), 324.5f);
76 EXPECT_EQ(primitives.val_uint32(), 3424);
77 EXPECT_EQ(primitives.val_uint64(), 57);
78 EXPECT_EQ(primitives.val_fixed32(), -20);
79 EXPECT_EQ(primitives.val_fixed64(), -37);
80 EXPECT_EQ(primitives.val_bool(), true);
81 EXPECT_THAT(primitives.val_string(), StrEq(s.c_str()));
82 EXPECT_THAT(primitives.val_bytes(), StrEq("apple"));
83 EXPECT_EQ(primitives.val_sfixed32(), 63);
84 EXPECT_EQ(primitives.val_sfixed64(), -54);
85 EXPECT_EQ(primitives.val_sint32(), -533);
86 EXPECT_EQ(primitives.val_sint64(), -61224762453LL);
87 EXPECT_EQ(primitives.val_enum(), PrimitiveProto_Count_TWO);
88}
89
90TEST(ProtoOutputStreamTest, Complex) {
91 std::string name1 = "cat";
92 std::string name2 = "dog";
93 const char data1[6] = { 'f', 'u', 'n', 'n', 'y', '!' };
94 const char data2[4] = { 'f', 'o', 'o', 'd' };
95
96 ProtoOutputStream proto;
97 EXPECT_TRUE(proto.write(FIELD_TYPE_INT32 | ComplexProto::kIntsFieldNumber, 23));
98 EXPECT_TRUE(proto.write(FIELD_TYPE_INT32 | ComplexProto::kIntsFieldNumber, 101));
99 EXPECT_TRUE(proto.write(FIELD_TYPE_INT32 | ComplexProto::kIntsFieldNumber, -72));
100 uint64_t token1 = proto.start(FIELD_TYPE_MESSAGE | ComplexProto::kLogsFieldNumber);
101 EXPECT_TRUE(proto.write(FIELD_TYPE_INT32 | ComplexProto::Log::kIdFieldNumber, 12));
102 EXPECT_TRUE(proto.write(FIELD_TYPE_STRING | ComplexProto::Log::kNameFieldNumber, name1));
103 // specify the length to test the write(id, bytes, length) function.
104 EXPECT_TRUE(proto.write(FIELD_TYPE_BYTES | ComplexProto::Log::kDataFieldNumber, data1, 5));
105 proto.end(token1);
106 uint64_t token2 = proto.start(FIELD_TYPE_MESSAGE | ComplexProto::kLogsFieldNumber);
107 EXPECT_TRUE(proto.write(FIELD_TYPE_INT32 | ComplexProto::Log::kIdFieldNumber, 98));
108 EXPECT_TRUE(proto.write(FIELD_TYPE_STRING | ComplexProto::Log::kNameFieldNumber, name2));
109 EXPECT_TRUE(proto.write(FIELD_TYPE_BYTES | ComplexProto::Log::kDataFieldNumber, data2, 4));
110 proto.end(token2);
111
112 ComplexProto complex;
113 ASSERT_TRUE(complex.ParseFromString(iterateToString(&proto)));
114 EXPECT_EQ(complex.ints_size(), 3);
115 EXPECT_EQ(complex.ints(0), 23);
116 EXPECT_EQ(complex.ints(1), 101);
117 EXPECT_EQ(complex.ints(2), -72);
118 EXPECT_EQ(complex.logs_size(), 2);
119 ComplexProto::Log log1 = complex.logs(0);
120 EXPECT_EQ(log1.id(), 12);
121 EXPECT_THAT(log1.name(), StrEq(name1.c_str()));
122 EXPECT_THAT(log1.data(), StrEq("funny")); // should not contain '!'
123 ComplexProto::Log log2 = complex.logs(1);
124 EXPECT_EQ(log2.id(), 98);
125 EXPECT_THAT(log2.name(), StrEq(name2.c_str()));
126 EXPECT_THAT(log2.data(), StrEq("food"));
127}
128
129TEST(ProtoOutputStreamTest, Reusability) {
130 ProtoOutputStream proto;
131 EXPECT_TRUE(proto.write(FIELD_TYPE_INT32 | ComplexProto::kIntsFieldNumber, 32));
132 EXPECT_TRUE(proto.write(FIELD_TYPE_INT32 | ComplexProto::kIntsFieldNumber, 15));
133 EXPECT_EQ(proto.bytesWritten(), 4);
134 EXPECT_EQ(proto.size(), 4);
Yi Jinfd2a4c72018-04-26 11:49:08 -0700135 // Can't write to proto after compact
136 EXPECT_FALSE(proto.write(FIELD_TYPE_INT32 | ComplexProto::kIntsFieldNumber, 94));
137
138 ComplexProto beforeClear;
139 ASSERT_TRUE(beforeClear.ParseFromString(flushToString(&proto)));
140 EXPECT_EQ(beforeClear.ints_size(), 2);
141 EXPECT_EQ(beforeClear.ints(0), 32);
142 EXPECT_EQ(beforeClear.ints(1), 15);
143
Yi Jinc3d4b282018-04-23 16:02:20 -0700144 proto.clear();
145 EXPECT_EQ(proto.bytesWritten(), 0);
Yi Jinfd2a4c72018-04-26 11:49:08 -0700146 EXPECT_TRUE(proto.write(FIELD_TYPE_INT32 | ComplexProto::kIntsFieldNumber, 1076));
147
148 ComplexProto afterClear;
149 ASSERT_TRUE(afterClear.ParseFromString(flushToString(&proto)));
150 EXPECT_EQ(afterClear.ints_size(), 1);
151 EXPECT_EQ(afterClear.ints(0), 1076);
Yi Jinc3d4b282018-04-23 16:02:20 -0700152}
153
154TEST(ProtoOutputStreamTest, AdvancedEncoding) {
155 ProtoOutputStream proto;
Yi Jinfd2a4c72018-04-26 11:49:08 -0700156 proto.writeRawVarint((ComplexProto::kIntsFieldNumber << FIELD_ID_SHIFT) + WIRE_TYPE_VARINT);
Yi Jinc3d4b282018-04-23 16:02:20 -0700157 proto.writeRawVarint(UINT64_C(-123809234));
158 proto.writeLengthDelimitedHeader(ComplexProto::kLogsFieldNumber, 8);
Yi Jinfd2a4c72018-04-26 11:49:08 -0700159 proto.writeRawByte((ComplexProto::Log::kDataFieldNumber << FIELD_ID_SHIFT) + WIRE_TYPE_LENGTH_DELIMITED);
Yi Jinc3d4b282018-04-23 16:02:20 -0700160 proto.writeRawByte(6);
161 proto.writeRawByte('b');
162 proto.writeRawByte('a');
163 proto.writeRawByte('n');
164 proto.writeRawByte('a');
165 proto.writeRawByte('n');
166 proto.writeRawByte('a');
167 uint64_t token = proto.start(FIELD_TYPE_MESSAGE | ComplexProto::kLogsFieldNumber);
168 proto.write(FIELD_TYPE_INT32 | ComplexProto::Log::kIdFieldNumber, 14);
169 proto.end(token);
170
171 ComplexProto complex;
172 ASSERT_TRUE(complex.ParseFromString(flushToString(&proto)));
173 EXPECT_EQ(complex.ints_size(), 1);
174 EXPECT_EQ(complex.ints(0), UINT64_C(-123809234));
175 EXPECT_EQ(complex.logs_size(), 2);
176 ComplexProto::Log log1 = complex.logs(0);
177 EXPECT_FALSE(log1.has_id());
178 EXPECT_FALSE(log1.has_name());
179 EXPECT_THAT(log1.data(), StrEq("banana"));
180 ComplexProto::Log log2 = complex.logs(1);
181 EXPECT_EQ(log2.id(), 14);
182 EXPECT_FALSE(log2.has_name());
183 EXPECT_FALSE(log2.has_data());
184}
Yi Jinfd2a4c72018-04-26 11:49:08 -0700185
186TEST(ProtoOutputStreamTest, InvalidTypes) {
187 ProtoOutputStream proto;
188 EXPECT_FALSE(proto.write(FIELD_TYPE_UNKNOWN | PrimitiveProto::kValInt32FieldNumber, 790));
189 EXPECT_FALSE(proto.write(FIELD_TYPE_ENUM | PrimitiveProto::kValEnumFieldNumber, 234.34));
190 EXPECT_FALSE(proto.write(FIELD_TYPE_BOOL | PrimitiveProto::kValBoolFieldNumber, 18.73f));
191 EXPECT_EQ(proto.size(), 0);
Yi Jin18678bd2018-04-27 11:51:13 -0700192}
193
194TEST(ProtoOutputStreamTest, NoEndCalled) {
195 ProtoOutputStream proto;
196 proto.start(FIELD_TYPE_MESSAGE | ComplexProto::kLogsFieldNumber);
197 proto.write(FIELD_TYPE_INT32 | ComplexProto::Log::kIdFieldNumber, 53);
198 // no proto.end called
199 EXPECT_NE(proto.bytesWritten(), 0);
200 EXPECT_EQ(proto.size(), 0);
201 EXPECT_EQ(proto.data().size(), 0);
202 EXPECT_FALSE(proto.flush(STDOUT_FILENO));
203}
204
205
206TEST(ProtoOutputStreamTest, TwoEndCalled) {
207 ProtoOutputStream proto;
208 uint64_t token = proto.start(FIELD_TYPE_MESSAGE | ComplexProto::kLogsFieldNumber);
209 proto.write(FIELD_TYPE_INT32 | ComplexProto::Log::kIdFieldNumber, 53);
210 proto.end(token);
211 proto.end(token);
212 EXPECT_NE(proto.bytesWritten(), 0);
213 EXPECT_EQ(proto.size(), 0);
214 EXPECT_EQ(proto.data().size(), 0);
215 EXPECT_FALSE(proto.flush(STDOUT_FILENO));
216}
217
218TEST(ProtoOutputStreamTest, NoStartCalled) {
219 ProtoOutputStream proto;
220 uint64_t wrongToken = UINT64_C(324536345);
221 // no proto.start called
222 proto.write(FIELD_TYPE_INT32 | ComplexProto::Log::kIdFieldNumber, 53);
223 proto.end(wrongToken);
224 EXPECT_NE(proto.bytesWritten(), 0);
225 EXPECT_EQ(proto.size(), 0);
226 EXPECT_EQ(proto.data().size(), 0);
227 EXPECT_FALSE(proto.flush(STDOUT_FILENO));
228}