1*6dbdd20aSAndroid Build Coastguard Worker /*
2*6dbdd20aSAndroid Build Coastguard Worker * Copyright (C) 2017 The Android Open Source Project
3*6dbdd20aSAndroid Build Coastguard Worker *
4*6dbdd20aSAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*6dbdd20aSAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*6dbdd20aSAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*6dbdd20aSAndroid Build Coastguard Worker *
8*6dbdd20aSAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*6dbdd20aSAndroid Build Coastguard Worker *
10*6dbdd20aSAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*6dbdd20aSAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*6dbdd20aSAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*6dbdd20aSAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*6dbdd20aSAndroid Build Coastguard Worker * limitations under the License.
15*6dbdd20aSAndroid Build Coastguard Worker */
16*6dbdd20aSAndroid Build Coastguard Worker
17*6dbdd20aSAndroid Build Coastguard Worker #include "perfetto/protozero/message.h"
18*6dbdd20aSAndroid Build Coastguard Worker
19*6dbdd20aSAndroid Build Coastguard Worker #include <limits>
20*6dbdd20aSAndroid Build Coastguard Worker #include <memory>
21*6dbdd20aSAndroid Build Coastguard Worker #include <utility>
22*6dbdd20aSAndroid Build Coastguard Worker #include <vector>
23*6dbdd20aSAndroid Build Coastguard Worker
24*6dbdd20aSAndroid Build Coastguard Worker #include "perfetto/base/logging.h"
25*6dbdd20aSAndroid Build Coastguard Worker #include "perfetto/protozero/message_handle.h"
26*6dbdd20aSAndroid Build Coastguard Worker #include "perfetto/protozero/proto_utils.h"
27*6dbdd20aSAndroid Build Coastguard Worker #include "perfetto/protozero/root_message.h"
28*6dbdd20aSAndroid Build Coastguard Worker #include "src/base/test/utils.h"
29*6dbdd20aSAndroid Build Coastguard Worker #include "src/protozero/test/fake_scattered_buffer.h"
30*6dbdd20aSAndroid Build Coastguard Worker #include "test/gtest_and_gmock.h"
31*6dbdd20aSAndroid Build Coastguard Worker
32*6dbdd20aSAndroid Build Coastguard Worker namespace protozero {
33*6dbdd20aSAndroid Build Coastguard Worker
34*6dbdd20aSAndroid Build Coastguard Worker namespace {
35*6dbdd20aSAndroid Build Coastguard Worker
36*6dbdd20aSAndroid Build Coastguard Worker constexpr size_t kChunkSize = 16;
37*6dbdd20aSAndroid Build Coastguard Worker constexpr uint8_t kTestBytes[] = {0, 0, 0, 0, 0x42, 1, 0x42, 0xff, 0x42, 0};
38*6dbdd20aSAndroid Build Coastguard Worker constexpr const char kStartWatermark[] = {'a', 'b', 'c', 'd',
39*6dbdd20aSAndroid Build Coastguard Worker '1', '2', '3', '\0'};
40*6dbdd20aSAndroid Build Coastguard Worker constexpr const char kEndWatermark[] = {'9', '8', '7', '6',
41*6dbdd20aSAndroid Build Coastguard Worker 'z', 'w', 'y', '\0'};
42*6dbdd20aSAndroid Build Coastguard Worker
43*6dbdd20aSAndroid Build Coastguard Worker class FakeRootMessage : public RootMessage<Message> {};
44*6dbdd20aSAndroid Build Coastguard Worker class FakeChildMessage : public Message {};
45*6dbdd20aSAndroid Build Coastguard Worker
SimpleHash(const std::string & str)46*6dbdd20aSAndroid Build Coastguard Worker uint32_t SimpleHash(const std::string& str) {
47*6dbdd20aSAndroid Build Coastguard Worker uint32_t hash = 5381;
48*6dbdd20aSAndroid Build Coastguard Worker for (char c : str)
49*6dbdd20aSAndroid Build Coastguard Worker hash = 33 * hash + static_cast<uint32_t>(c);
50*6dbdd20aSAndroid Build Coastguard Worker return hash;
51*6dbdd20aSAndroid Build Coastguard Worker }
52*6dbdd20aSAndroid Build Coastguard Worker
53*6dbdd20aSAndroid Build Coastguard Worker class MessageTest : public ::testing::Test {
54*6dbdd20aSAndroid Build Coastguard Worker public:
SetUp()55*6dbdd20aSAndroid Build Coastguard Worker void SetUp() override { SetChunkSize(kChunkSize); }
56*6dbdd20aSAndroid Build Coastguard Worker
TearDown()57*6dbdd20aSAndroid Build Coastguard Worker void TearDown() override {
58*6dbdd20aSAndroid Build Coastguard Worker // Check that none of the messages created by the text fixtures below did
59*6dbdd20aSAndroid Build Coastguard Worker // under/overflow their heap boundaries.
60*6dbdd20aSAndroid Build Coastguard Worker for (std::unique_ptr<uint8_t[]>& mem : messages_) {
61*6dbdd20aSAndroid Build Coastguard Worker EXPECT_STREQ(kStartWatermark, reinterpret_cast<char*>(mem.get()));
62*6dbdd20aSAndroid Build Coastguard Worker EXPECT_STREQ(kEndWatermark,
63*6dbdd20aSAndroid Build Coastguard Worker reinterpret_cast<char*>(mem.get() + sizeof(kStartWatermark) +
64*6dbdd20aSAndroid Build Coastguard Worker sizeof(FakeRootMessage)));
65*6dbdd20aSAndroid Build Coastguard Worker FakeRootMessage* msg = reinterpret_cast<FakeRootMessage*>(
66*6dbdd20aSAndroid Build Coastguard Worker mem.get() + sizeof(kStartWatermark));
67*6dbdd20aSAndroid Build Coastguard Worker msg->~FakeRootMessage();
68*6dbdd20aSAndroid Build Coastguard Worker mem.reset();
69*6dbdd20aSAndroid Build Coastguard Worker }
70*6dbdd20aSAndroid Build Coastguard Worker messages_.clear();
71*6dbdd20aSAndroid Build Coastguard Worker stream_writer_.reset();
72*6dbdd20aSAndroid Build Coastguard Worker buffer_.reset();
73*6dbdd20aSAndroid Build Coastguard Worker }
74*6dbdd20aSAndroid Build Coastguard Worker
ResetMessage(FakeRootMessage * msg)75*6dbdd20aSAndroid Build Coastguard Worker void ResetMessage(FakeRootMessage* msg) { msg->Reset(stream_writer_.get()); }
76*6dbdd20aSAndroid Build Coastguard Worker
SetChunkSize(size_t size)77*6dbdd20aSAndroid Build Coastguard Worker void SetChunkSize(size_t size) {
78*6dbdd20aSAndroid Build Coastguard Worker buffer_.reset(new FakeScatteredBuffer(size));
79*6dbdd20aSAndroid Build Coastguard Worker stream_writer_.reset(new ScatteredStreamWriter(buffer_.get()));
80*6dbdd20aSAndroid Build Coastguard Worker chunk_size_ = size;
81*6dbdd20aSAndroid Build Coastguard Worker readback_pos_ = 0;
82*6dbdd20aSAndroid Build Coastguard Worker }
83*6dbdd20aSAndroid Build Coastguard Worker
NewMessage()84*6dbdd20aSAndroid Build Coastguard Worker FakeRootMessage* NewMessage() {
85*6dbdd20aSAndroid Build Coastguard Worker std::unique_ptr<uint8_t[]> mem(
86*6dbdd20aSAndroid Build Coastguard Worker new uint8_t[sizeof(kStartWatermark) + sizeof(FakeRootMessage) +
87*6dbdd20aSAndroid Build Coastguard Worker sizeof(kEndWatermark)]);
88*6dbdd20aSAndroid Build Coastguard Worker uint8_t* msg_start = mem.get() + sizeof(kStartWatermark);
89*6dbdd20aSAndroid Build Coastguard Worker memcpy(mem.get(), kStartWatermark, sizeof(kStartWatermark));
90*6dbdd20aSAndroid Build Coastguard Worker memset(msg_start, 0, sizeof(FakeRootMessage));
91*6dbdd20aSAndroid Build Coastguard Worker memcpy(msg_start + sizeof(FakeRootMessage), kEndWatermark,
92*6dbdd20aSAndroid Build Coastguard Worker sizeof(kEndWatermark));
93*6dbdd20aSAndroid Build Coastguard Worker messages_.push_back(std::move(mem));
94*6dbdd20aSAndroid Build Coastguard Worker FakeRootMessage* msg = new (msg_start) FakeRootMessage();
95*6dbdd20aSAndroid Build Coastguard Worker msg->Reset(stream_writer_.get());
96*6dbdd20aSAndroid Build Coastguard Worker return msg;
97*6dbdd20aSAndroid Build Coastguard Worker }
98*6dbdd20aSAndroid Build Coastguard Worker
NewMessageWithSizeField()99*6dbdd20aSAndroid Build Coastguard Worker FakeRootMessage* NewMessageWithSizeField() {
100*6dbdd20aSAndroid Build Coastguard Worker FakeRootMessage* msg = NewMessage();
101*6dbdd20aSAndroid Build Coastguard Worker uint8_t* size_field =
102*6dbdd20aSAndroid Build Coastguard Worker stream_writer_->ReserveBytes(proto_utils::kMessageLengthFieldSize);
103*6dbdd20aSAndroid Build Coastguard Worker memset(size_field, 0u, proto_utils::kMessageLengthFieldSize);
104*6dbdd20aSAndroid Build Coastguard Worker msg->set_size_field(size_field);
105*6dbdd20aSAndroid Build Coastguard Worker return msg;
106*6dbdd20aSAndroid Build Coastguard Worker }
107*6dbdd20aSAndroid Build Coastguard Worker
GetNumSerializedBytes()108*6dbdd20aSAndroid Build Coastguard Worker size_t GetNumSerializedBytes() {
109*6dbdd20aSAndroid Build Coastguard Worker if (buffer_->chunks().empty())
110*6dbdd20aSAndroid Build Coastguard Worker return 0;
111*6dbdd20aSAndroid Build Coastguard Worker return buffer_->chunks().size() * chunk_size_ -
112*6dbdd20aSAndroid Build Coastguard Worker stream_writer_->bytes_available();
113*6dbdd20aSAndroid Build Coastguard Worker }
114*6dbdd20aSAndroid Build Coastguard Worker
GetNextSerializedBytes(size_t num_bytes)115*6dbdd20aSAndroid Build Coastguard Worker std::string GetNextSerializedBytes(size_t num_bytes) {
116*6dbdd20aSAndroid Build Coastguard Worker size_t old_readback_pos = readback_pos_;
117*6dbdd20aSAndroid Build Coastguard Worker readback_pos_ += num_bytes;
118*6dbdd20aSAndroid Build Coastguard Worker return buffer_->GetBytesAsString(old_readback_pos, num_bytes);
119*6dbdd20aSAndroid Build Coastguard Worker }
120*6dbdd20aSAndroid Build Coastguard Worker
BuildNestedMessages(Message * msg,uint32_t max_depth,bool empty=false,uint32_t depth=0)121*6dbdd20aSAndroid Build Coastguard Worker static void BuildNestedMessages(Message* msg,
122*6dbdd20aSAndroid Build Coastguard Worker uint32_t max_depth,
123*6dbdd20aSAndroid Build Coastguard Worker bool empty = false,
124*6dbdd20aSAndroid Build Coastguard Worker uint32_t depth = 0) {
125*6dbdd20aSAndroid Build Coastguard Worker if (!empty) {
126*6dbdd20aSAndroid Build Coastguard Worker for (uint32_t i = 1; i <= 128; ++i)
127*6dbdd20aSAndroid Build Coastguard Worker msg->AppendBytes(i, kTestBytes, sizeof(kTestBytes));
128*6dbdd20aSAndroid Build Coastguard Worker }
129*6dbdd20aSAndroid Build Coastguard Worker
130*6dbdd20aSAndroid Build Coastguard Worker if (depth < max_depth) {
131*6dbdd20aSAndroid Build Coastguard Worker auto* nested_msg =
132*6dbdd20aSAndroid Build Coastguard Worker msg->BeginNestedMessage<FakeChildMessage>(1 + depth * 10);
133*6dbdd20aSAndroid Build Coastguard Worker BuildNestedMessages(nested_msg, max_depth, empty, depth + 1);
134*6dbdd20aSAndroid Build Coastguard Worker }
135*6dbdd20aSAndroid Build Coastguard Worker
136*6dbdd20aSAndroid Build Coastguard Worker if (!empty) {
137*6dbdd20aSAndroid Build Coastguard Worker for (uint32_t i = 129; i <= 256; ++i)
138*6dbdd20aSAndroid Build Coastguard Worker msg->AppendVarInt(i, 42);
139*6dbdd20aSAndroid Build Coastguard Worker }
140*6dbdd20aSAndroid Build Coastguard Worker
141*6dbdd20aSAndroid Build Coastguard Worker if ((depth & 2) == 0)
142*6dbdd20aSAndroid Build Coastguard Worker msg->Finalize();
143*6dbdd20aSAndroid Build Coastguard Worker }
144*6dbdd20aSAndroid Build Coastguard Worker
145*6dbdd20aSAndroid Build Coastguard Worker private:
146*6dbdd20aSAndroid Build Coastguard Worker std::unique_ptr<FakeScatteredBuffer> buffer_;
147*6dbdd20aSAndroid Build Coastguard Worker std::unique_ptr<ScatteredStreamWriter> stream_writer_;
148*6dbdd20aSAndroid Build Coastguard Worker std::vector<std::unique_ptr<uint8_t[]>> messages_;
149*6dbdd20aSAndroid Build Coastguard Worker size_t chunk_size_{};
150*6dbdd20aSAndroid Build Coastguard Worker size_t readback_pos_{};
151*6dbdd20aSAndroid Build Coastguard Worker };
152*6dbdd20aSAndroid Build Coastguard Worker
TEST_F(MessageTest,ZeroLengthArraysAndStrings)153*6dbdd20aSAndroid Build Coastguard Worker TEST_F(MessageTest, ZeroLengthArraysAndStrings) {
154*6dbdd20aSAndroid Build Coastguard Worker Message* msg = NewMessage();
155*6dbdd20aSAndroid Build Coastguard Worker msg->AppendBytes(1 /* field_id */, nullptr, 0);
156*6dbdd20aSAndroid Build Coastguard Worker msg->AppendString(2 /* field_id */, "");
157*6dbdd20aSAndroid Build Coastguard Worker
158*6dbdd20aSAndroid Build Coastguard Worker EXPECT_EQ(4u, msg->Finalize());
159*6dbdd20aSAndroid Build Coastguard Worker EXPECT_EQ(4u, GetNumSerializedBytes());
160*6dbdd20aSAndroid Build Coastguard Worker
161*6dbdd20aSAndroid Build Coastguard Worker // These lines match the serialization of the Append* calls above.
162*6dbdd20aSAndroid Build Coastguard Worker ASSERT_EQ("0A00", GetNextSerializedBytes(2));
163*6dbdd20aSAndroid Build Coastguard Worker ASSERT_EQ("1200", GetNextSerializedBytes(2));
164*6dbdd20aSAndroid Build Coastguard Worker }
165*6dbdd20aSAndroid Build Coastguard Worker
TEST_F(MessageTest,BasicTypesNoNesting)166*6dbdd20aSAndroid Build Coastguard Worker TEST_F(MessageTest, BasicTypesNoNesting) {
167*6dbdd20aSAndroid Build Coastguard Worker Message* msg = NewMessage();
168*6dbdd20aSAndroid Build Coastguard Worker msg->AppendVarInt(1 /* field_id */, 0);
169*6dbdd20aSAndroid Build Coastguard Worker msg->AppendVarInt(2 /* field_id */, std::numeric_limits<uint32_t>::max());
170*6dbdd20aSAndroid Build Coastguard Worker msg->AppendVarInt(3 /* field_id */, 42);
171*6dbdd20aSAndroid Build Coastguard Worker msg->AppendVarInt(4 /* field_id */, std::numeric_limits<uint64_t>::max());
172*6dbdd20aSAndroid Build Coastguard Worker msg->AppendFixed(5 /* field_id */, 3.1415f /* float */);
173*6dbdd20aSAndroid Build Coastguard Worker msg->AppendFixed(6 /* field_id */, 3.14159265358979323846 /* double */);
174*6dbdd20aSAndroid Build Coastguard Worker msg->AppendBytes(7 /* field_id */, kTestBytes, sizeof(kTestBytes));
175*6dbdd20aSAndroid Build Coastguard Worker
176*6dbdd20aSAndroid Build Coastguard Worker // Field ids > 16 are expected to be varint encoded (preamble > 1 byte)
177*6dbdd20aSAndroid Build Coastguard Worker msg->AppendString(257 /* field_id */, "0123456789abcdefABCDEF");
178*6dbdd20aSAndroid Build Coastguard Worker msg->AppendSignedVarInt(3 /* field_id */, -21);
179*6dbdd20aSAndroid Build Coastguard Worker
180*6dbdd20aSAndroid Build Coastguard Worker EXPECT_EQ(74u, msg->Finalize());
181*6dbdd20aSAndroid Build Coastguard Worker EXPECT_EQ(74u, GetNumSerializedBytes());
182*6dbdd20aSAndroid Build Coastguard Worker
183*6dbdd20aSAndroid Build Coastguard Worker // These lines match the serialization of the Append* calls above.
184*6dbdd20aSAndroid Build Coastguard Worker ASSERT_EQ("0800", GetNextSerializedBytes(2));
185*6dbdd20aSAndroid Build Coastguard Worker ASSERT_EQ("10FFFFFFFF0F", GetNextSerializedBytes(6));
186*6dbdd20aSAndroid Build Coastguard Worker ASSERT_EQ("182A", GetNextSerializedBytes(2));
187*6dbdd20aSAndroid Build Coastguard Worker ASSERT_EQ("20FFFFFFFFFFFFFFFFFF01", GetNextSerializedBytes(11));
188*6dbdd20aSAndroid Build Coastguard Worker ASSERT_EQ("2D560E4940", GetNextSerializedBytes(5));
189*6dbdd20aSAndroid Build Coastguard Worker ASSERT_EQ("31182D4454FB210940", GetNextSerializedBytes(9));
190*6dbdd20aSAndroid Build Coastguard Worker ASSERT_EQ("3A0A00000000420142FF4200", GetNextSerializedBytes(12));
191*6dbdd20aSAndroid Build Coastguard Worker ASSERT_EQ("8A101630313233343536373839616263646566414243444546",
192*6dbdd20aSAndroid Build Coastguard Worker GetNextSerializedBytes(25));
193*6dbdd20aSAndroid Build Coastguard Worker ASSERT_EQ("1829", GetNextSerializedBytes(2));
194*6dbdd20aSAndroid Build Coastguard Worker }
195*6dbdd20aSAndroid Build Coastguard Worker
TEST_F(MessageTest,NestedMessagesSimple)196*6dbdd20aSAndroid Build Coastguard Worker TEST_F(MessageTest, NestedMessagesSimple) {
197*6dbdd20aSAndroid Build Coastguard Worker Message* root_msg = NewMessage();
198*6dbdd20aSAndroid Build Coastguard Worker root_msg->AppendVarInt(1 /* field_id */, 1);
199*6dbdd20aSAndroid Build Coastguard Worker
200*6dbdd20aSAndroid Build Coastguard Worker FakeChildMessage* nested_msg =
201*6dbdd20aSAndroid Build Coastguard Worker root_msg->BeginNestedMessage<FakeChildMessage>(128 /* field_id */);
202*6dbdd20aSAndroid Build Coastguard Worker ASSERT_EQ(0u, reinterpret_cast<uintptr_t>(nested_msg) % sizeof(void*));
203*6dbdd20aSAndroid Build Coastguard Worker nested_msg->AppendVarInt(2 /* field_id */, 2);
204*6dbdd20aSAndroid Build Coastguard Worker
205*6dbdd20aSAndroid Build Coastguard Worker nested_msg =
206*6dbdd20aSAndroid Build Coastguard Worker root_msg->BeginNestedMessage<FakeChildMessage>(129 /* field_id */);
207*6dbdd20aSAndroid Build Coastguard Worker nested_msg->AppendVarInt(4 /* field_id */, 2);
208*6dbdd20aSAndroid Build Coastguard Worker
209*6dbdd20aSAndroid Build Coastguard Worker root_msg->AppendVarInt(5 /* field_id */, 3);
210*6dbdd20aSAndroid Build Coastguard Worker
211*6dbdd20aSAndroid Build Coastguard Worker // The expected size of the root message is supposed to be 14 bytes:
212*6dbdd20aSAndroid Build Coastguard Worker // 2 bytes for the varint field (id: 1) (1 for preamble and one for payload)
213*6dbdd20aSAndroid Build Coastguard Worker // 3 bytes for the preamble of the 1st nested message (2 for id, 1 for size)
214*6dbdd20aSAndroid Build Coastguard Worker // 2 bytes for the varint field (id: 2) of the 1st nested message
215*6dbdd20aSAndroid Build Coastguard Worker // 3 bytes for the premable of the 2nd nested message
216*6dbdd20aSAndroid Build Coastguard Worker // 2 bytes for the varint field (id: 4) of the 2nd nested message.
217*6dbdd20aSAndroid Build Coastguard Worker // 2 bytes for the last varint (id : 5) field of the root message.
218*6dbdd20aSAndroid Build Coastguard Worker // Test also that finalization is idempontent and Finalize() can be safely
219*6dbdd20aSAndroid Build Coastguard Worker // called more than once without side effects.
220*6dbdd20aSAndroid Build Coastguard Worker for (int i = 0; i < 3; ++i) {
221*6dbdd20aSAndroid Build Coastguard Worker EXPECT_EQ(14u, root_msg->Finalize());
222*6dbdd20aSAndroid Build Coastguard Worker EXPECT_EQ(14u, GetNumSerializedBytes());
223*6dbdd20aSAndroid Build Coastguard Worker }
224*6dbdd20aSAndroid Build Coastguard Worker
225*6dbdd20aSAndroid Build Coastguard Worker ASSERT_EQ("0801", GetNextSerializedBytes(2));
226*6dbdd20aSAndroid Build Coastguard Worker
227*6dbdd20aSAndroid Build Coastguard Worker ASSERT_EQ("820802", GetNextSerializedBytes(3));
228*6dbdd20aSAndroid Build Coastguard Worker ASSERT_EQ("1002", GetNextSerializedBytes(2));
229*6dbdd20aSAndroid Build Coastguard Worker
230*6dbdd20aSAndroid Build Coastguard Worker ASSERT_EQ("8A0802", GetNextSerializedBytes(3));
231*6dbdd20aSAndroid Build Coastguard Worker ASSERT_EQ("2002", GetNextSerializedBytes(2));
232*6dbdd20aSAndroid Build Coastguard Worker
233*6dbdd20aSAndroid Build Coastguard Worker ASSERT_EQ("2803", GetNextSerializedBytes(2));
234*6dbdd20aSAndroid Build Coastguard Worker }
235*6dbdd20aSAndroid Build Coastguard Worker
236*6dbdd20aSAndroid Build Coastguard Worker // Tests using a AppendScatteredBytes to append raw bytes to
237*6dbdd20aSAndroid Build Coastguard Worker // a message using multiple individual buffers.
TEST_F(MessageTest,AppendScatteredBytes)238*6dbdd20aSAndroid Build Coastguard Worker TEST_F(MessageTest, AppendScatteredBytes) {
239*6dbdd20aSAndroid Build Coastguard Worker Message* root_msg = NewMessage();
240*6dbdd20aSAndroid Build Coastguard Worker
241*6dbdd20aSAndroid Build Coastguard Worker uint8_t buffer[42];
242*6dbdd20aSAndroid Build Coastguard Worker memset(buffer, 0x42, sizeof(buffer));
243*6dbdd20aSAndroid Build Coastguard Worker
244*6dbdd20aSAndroid Build Coastguard Worker ContiguousMemoryRange ranges[] = {{buffer, buffer + sizeof(buffer)},
245*6dbdd20aSAndroid Build Coastguard Worker {buffer, buffer + sizeof(buffer)}};
246*6dbdd20aSAndroid Build Coastguard Worker root_msg->AppendScatteredBytes(1 /* field_id */, ranges, 2);
247*6dbdd20aSAndroid Build Coastguard Worker EXPECT_EQ(86u, root_msg->Finalize());
248*6dbdd20aSAndroid Build Coastguard Worker EXPECT_EQ(86u, GetNumSerializedBytes());
249*6dbdd20aSAndroid Build Coastguard Worker
250*6dbdd20aSAndroid Build Coastguard Worker // field_id
251*6dbdd20aSAndroid Build Coastguard Worker EXPECT_EQ("0A", GetNextSerializedBytes(1));
252*6dbdd20aSAndroid Build Coastguard Worker // field length
253*6dbdd20aSAndroid Build Coastguard Worker EXPECT_EQ("54", GetNextSerializedBytes(1));
254*6dbdd20aSAndroid Build Coastguard Worker // start of contents
255*6dbdd20aSAndroid Build Coastguard Worker EXPECT_EQ("42424242", GetNextSerializedBytes(4));
256*6dbdd20aSAndroid Build Coastguard Worker }
257*6dbdd20aSAndroid Build Coastguard Worker
TEST_F(MessageTest,AppendRawProtoBytesFinalizesNestedMessage)258*6dbdd20aSAndroid Build Coastguard Worker TEST_F(MessageTest, AppendRawProtoBytesFinalizesNestedMessage) {
259*6dbdd20aSAndroid Build Coastguard Worker Message* root_msg = NewMessage();
260*6dbdd20aSAndroid Build Coastguard Worker
261*6dbdd20aSAndroid Build Coastguard Worker uint8_t buffer[42];
262*6dbdd20aSAndroid Build Coastguard Worker memset(buffer, 0x42, sizeof(buffer));
263*6dbdd20aSAndroid Build Coastguard Worker
264*6dbdd20aSAndroid Build Coastguard Worker FakeChildMessage* nested_msg =
265*6dbdd20aSAndroid Build Coastguard Worker root_msg->BeginNestedMessage<FakeChildMessage>(9001 /* field_id */);
266*6dbdd20aSAndroid Build Coastguard Worker nested_msg->AppendVarInt(4 /* field_id */, 2);
267*6dbdd20aSAndroid Build Coastguard Worker uint8_t* nested_msg_size_field = nested_msg->size_field();
268*6dbdd20aSAndroid Build Coastguard Worker
269*6dbdd20aSAndroid Build Coastguard Worker EXPECT_FALSE(nested_msg->is_finalized());
270*6dbdd20aSAndroid Build Coastguard Worker EXPECT_EQ(0u, *nested_msg_size_field);
271*6dbdd20aSAndroid Build Coastguard Worker
272*6dbdd20aSAndroid Build Coastguard Worker root_msg->AppendRawProtoBytes(buffer, sizeof(buffer));
273*6dbdd20aSAndroid Build Coastguard Worker
274*6dbdd20aSAndroid Build Coastguard Worker // Nested message should have been finalized as a side effect of appending
275*6dbdd20aSAndroid Build Coastguard Worker // raw bytes.
276*6dbdd20aSAndroid Build Coastguard Worker EXPECT_EQ(0x2u, *nested_msg_size_field);
277*6dbdd20aSAndroid Build Coastguard Worker }
278*6dbdd20aSAndroid Build Coastguard Worker
TEST_F(MessageTest,AppendScatteredBytesFinalizesNestedMessage)279*6dbdd20aSAndroid Build Coastguard Worker TEST_F(MessageTest, AppendScatteredBytesFinalizesNestedMessage) {
280*6dbdd20aSAndroid Build Coastguard Worker Message* root_msg = NewMessage();
281*6dbdd20aSAndroid Build Coastguard Worker
282*6dbdd20aSAndroid Build Coastguard Worker uint8_t buffer[42];
283*6dbdd20aSAndroid Build Coastguard Worker memset(buffer, 0x42, sizeof(buffer));
284*6dbdd20aSAndroid Build Coastguard Worker
285*6dbdd20aSAndroid Build Coastguard Worker FakeChildMessage* nested_msg =
286*6dbdd20aSAndroid Build Coastguard Worker root_msg->BeginNestedMessage<FakeChildMessage>(9001 /* field_id */);
287*6dbdd20aSAndroid Build Coastguard Worker nested_msg->AppendVarInt(4 /* field_id */, 2);
288*6dbdd20aSAndroid Build Coastguard Worker uint8_t* nested_msg_size_field = nested_msg->size_field();
289*6dbdd20aSAndroid Build Coastguard Worker
290*6dbdd20aSAndroid Build Coastguard Worker EXPECT_FALSE(nested_msg->is_finalized());
291*6dbdd20aSAndroid Build Coastguard Worker EXPECT_EQ(0u, *nested_msg_size_field);
292*6dbdd20aSAndroid Build Coastguard Worker
293*6dbdd20aSAndroid Build Coastguard Worker ContiguousMemoryRange ranges[] = {{buffer, buffer + sizeof(buffer)}};
294*6dbdd20aSAndroid Build Coastguard Worker root_msg->AppendScatteredBytes(1 /* field_id */, ranges, 1);
295*6dbdd20aSAndroid Build Coastguard Worker
296*6dbdd20aSAndroid Build Coastguard Worker // Nested message should have been finalized as a side effect of appending
297*6dbdd20aSAndroid Build Coastguard Worker // scattered bytes.
298*6dbdd20aSAndroid Build Coastguard Worker EXPECT_EQ(0x2u, *nested_msg_size_field);
299*6dbdd20aSAndroid Build Coastguard Worker }
300*6dbdd20aSAndroid Build Coastguard Worker
TEST_F(MessageTest,StressTest)301*6dbdd20aSAndroid Build Coastguard Worker TEST_F(MessageTest, StressTest) {
302*6dbdd20aSAndroid Build Coastguard Worker std::vector<Message*> nested_msgs;
303*6dbdd20aSAndroid Build Coastguard Worker
304*6dbdd20aSAndroid Build Coastguard Worker Message* root_msg = NewMessage();
305*6dbdd20aSAndroid Build Coastguard Worker BuildNestedMessages(root_msg, /*max_depth=*/10);
306*6dbdd20aSAndroid Build Coastguard Worker root_msg->Finalize();
307*6dbdd20aSAndroid Build Coastguard Worker
308*6dbdd20aSAndroid Build Coastguard Worker // The main point of this test is to stress the code paths and test for
309*6dbdd20aSAndroid Build Coastguard Worker // unexpected crashes of the production code. The actual serialization is
310*6dbdd20aSAndroid Build Coastguard Worker // already covered in the other text fixtures. Keeping just a final smoke test
311*6dbdd20aSAndroid Build Coastguard Worker // here on the full buffer hash.
312*6dbdd20aSAndroid Build Coastguard Worker std::string full_buf = GetNextSerializedBytes(GetNumSerializedBytes());
313*6dbdd20aSAndroid Build Coastguard Worker size_t buf_hash = SimpleHash(full_buf);
314*6dbdd20aSAndroid Build Coastguard Worker EXPECT_EQ(0xf9e32b65, buf_hash);
315*6dbdd20aSAndroid Build Coastguard Worker }
316*6dbdd20aSAndroid Build Coastguard Worker
TEST_F(MessageTest,DeeplyNested)317*6dbdd20aSAndroid Build Coastguard Worker TEST_F(MessageTest, DeeplyNested) {
318*6dbdd20aSAndroid Build Coastguard Worker Message* root_msg = NewMessage();
319*6dbdd20aSAndroid Build Coastguard Worker BuildNestedMessages(root_msg, /*max_depth=*/1000);
320*6dbdd20aSAndroid Build Coastguard Worker root_msg->Finalize();
321*6dbdd20aSAndroid Build Coastguard Worker
322*6dbdd20aSAndroid Build Coastguard Worker std::string full_buf = GetNextSerializedBytes(GetNumSerializedBytes());
323*6dbdd20aSAndroid Build Coastguard Worker size_t buf_hash = SimpleHash(full_buf);
324*6dbdd20aSAndroid Build Coastguard Worker EXPECT_EQ(0xc0fde419, buf_hash);
325*6dbdd20aSAndroid Build Coastguard Worker }
326*6dbdd20aSAndroid Build Coastguard Worker
TEST_F(MessageTest,DeeplyNestedEmptyMessages)327*6dbdd20aSAndroid Build Coastguard Worker TEST_F(MessageTest, DeeplyNestedEmptyMessages) {
328*6dbdd20aSAndroid Build Coastguard Worker // Stress test writing deeply nested empty messages, many of which will be
329*6dbdd20aSAndroid Build Coastguard Worker // packed into the protobuf length field.
330*6dbdd20aSAndroid Build Coastguard Worker
331*6dbdd20aSAndroid Build Coastguard Worker // Use a larger chunk size for this test so there is more opportunity to pack
332*6dbdd20aSAndroid Build Coastguard Worker // messages.
333*6dbdd20aSAndroid Build Coastguard Worker SetChunkSize(4096u);
334*6dbdd20aSAndroid Build Coastguard Worker
335*6dbdd20aSAndroid Build Coastguard Worker Message* root_msg = NewMessage();
336*6dbdd20aSAndroid Build Coastguard Worker BuildNestedMessages(root_msg, /*max_depth=*/1000, /*empty=*/true);
337*6dbdd20aSAndroid Build Coastguard Worker root_msg->Finalize();
338*6dbdd20aSAndroid Build Coastguard Worker
339*6dbdd20aSAndroid Build Coastguard Worker std::string full_buf = GetNextSerializedBytes(GetNumSerializedBytes());
340*6dbdd20aSAndroid Build Coastguard Worker size_t buf_hash = SimpleHash(full_buf);
341*6dbdd20aSAndroid Build Coastguard Worker EXPECT_EQ(0x9371fe8eu, buf_hash);
342*6dbdd20aSAndroid Build Coastguard Worker }
343*6dbdd20aSAndroid Build Coastguard Worker
TEST_F(MessageTest,DestructInvalidMessageHandle)344*6dbdd20aSAndroid Build Coastguard Worker TEST_F(MessageTest, DestructInvalidMessageHandle) {
345*6dbdd20aSAndroid Build Coastguard Worker FakeRootMessage* msg = NewMessage();
346*6dbdd20aSAndroid Build Coastguard Worker EXPECT_DCHECK_DEATH({
347*6dbdd20aSAndroid Build Coastguard Worker MessageHandle<FakeRootMessage> handle(msg);
348*6dbdd20aSAndroid Build Coastguard Worker ResetMessage(msg);
349*6dbdd20aSAndroid Build Coastguard Worker });
350*6dbdd20aSAndroid Build Coastguard Worker }
351*6dbdd20aSAndroid Build Coastguard Worker
TEST_F(MessageTest,MessageHandle)352*6dbdd20aSAndroid Build Coastguard Worker TEST_F(MessageTest, MessageHandle) {
353*6dbdd20aSAndroid Build Coastguard Worker FakeRootMessage* msg3 = NewMessageWithSizeField();
354*6dbdd20aSAndroid Build Coastguard Worker FakeRootMessage* msg2 = NewMessageWithSizeField();
355*6dbdd20aSAndroid Build Coastguard Worker FakeRootMessage* msg1 = NewMessageWithSizeField();
356*6dbdd20aSAndroid Build Coastguard Worker FakeRootMessage* ignored_msg = NewMessage();
357*6dbdd20aSAndroid Build Coastguard Worker uint8_t* msg1_size = msg1->size_field();
358*6dbdd20aSAndroid Build Coastguard Worker uint8_t* msg2_size = msg2->size_field();
359*6dbdd20aSAndroid Build Coastguard Worker uint8_t* msg3_size = msg3->size_field();
360*6dbdd20aSAndroid Build Coastguard Worker
361*6dbdd20aSAndroid Build Coastguard Worker // Test that the handle going out of scope causes the finalization of the
362*6dbdd20aSAndroid Build Coastguard Worker // target message and triggers the optional callback.
363*6dbdd20aSAndroid Build Coastguard Worker {
364*6dbdd20aSAndroid Build Coastguard Worker MessageHandle<FakeRootMessage> handle1(msg1);
365*6dbdd20aSAndroid Build Coastguard Worker handle1->AppendBytes(1 /* field_id */, kTestBytes, 1 /* size */);
366*6dbdd20aSAndroid Build Coastguard Worker ASSERT_EQ(0u, msg1_size[0]);
367*6dbdd20aSAndroid Build Coastguard Worker }
368*6dbdd20aSAndroid Build Coastguard Worker ASSERT_EQ(0x3u, msg1_size[0]);
369*6dbdd20aSAndroid Build Coastguard Worker
370*6dbdd20aSAndroid Build Coastguard Worker // Test that the handle can be late initialized.
371*6dbdd20aSAndroid Build Coastguard Worker MessageHandle<FakeRootMessage> handle2(ignored_msg);
372*6dbdd20aSAndroid Build Coastguard Worker handle2 = MessageHandle<FakeRootMessage>(msg2);
373*6dbdd20aSAndroid Build Coastguard Worker handle2->AppendBytes(1 /* field_id */, kTestBytes, 2 /* size */);
374*6dbdd20aSAndroid Build Coastguard Worker ASSERT_EQ(0u, msg2_size[0]); // |msg2| should not be finalized yet.
375*6dbdd20aSAndroid Build Coastguard Worker
376*6dbdd20aSAndroid Build Coastguard Worker // Test that std::move works and does NOT cause finalization of the moved
377*6dbdd20aSAndroid Build Coastguard Worker // message.
378*6dbdd20aSAndroid Build Coastguard Worker MessageHandle<FakeRootMessage> handle_swp(ignored_msg);
379*6dbdd20aSAndroid Build Coastguard Worker handle_swp = std::move(handle2);
380*6dbdd20aSAndroid Build Coastguard Worker ASSERT_EQ(0u, msg2_size[0]); // msg2 should be NOT finalized yet.
381*6dbdd20aSAndroid Build Coastguard Worker handle_swp->AppendBytes(2 /* field_id */, kTestBytes, 3 /* size */);
382*6dbdd20aSAndroid Build Coastguard Worker
383*6dbdd20aSAndroid Build Coastguard Worker MessageHandle<FakeRootMessage> handle3(msg3);
384*6dbdd20aSAndroid Build Coastguard Worker handle3->AppendBytes(1 /* field_id */, kTestBytes, 4 /* size */);
385*6dbdd20aSAndroid Build Coastguard Worker ASSERT_EQ(0u, msg3_size[0]); // msg2 should be NOT finalized yet.
386*6dbdd20aSAndroid Build Coastguard Worker
387*6dbdd20aSAndroid Build Coastguard Worker // Both |handle3| and |handle_swp| point to a valid message (respectively,
388*6dbdd20aSAndroid Build Coastguard Worker // |msg3| and |msg2|). Now move |handle3| into |handle_swp|.
389*6dbdd20aSAndroid Build Coastguard Worker handle_swp = std::move(handle3);
390*6dbdd20aSAndroid Build Coastguard Worker ASSERT_EQ(0x89u, msg2_size[0]); // |msg2| should be finalized at this point.
391*6dbdd20aSAndroid Build Coastguard Worker
392*6dbdd20aSAndroid Build Coastguard Worker // At this point writing into handle_swp should actually write into |msg3|.
393*6dbdd20aSAndroid Build Coastguard Worker ASSERT_EQ(msg3, &*handle_swp);
394*6dbdd20aSAndroid Build Coastguard Worker handle_swp->AppendBytes(2 /* field_id */, kTestBytes, 8 /* size */);
395*6dbdd20aSAndroid Build Coastguard Worker MessageHandle<FakeRootMessage> another_handle(ignored_msg);
396*6dbdd20aSAndroid Build Coastguard Worker handle_swp = std::move(another_handle);
397*6dbdd20aSAndroid Build Coastguard Worker ASSERT_EQ(0x90u, msg3_size[0]); // |msg3| should be finalized at this point.
398*6dbdd20aSAndroid Build Coastguard Worker
399*6dbdd20aSAndroid Build Coastguard Worker #if PERFETTO_DCHECK_IS_ON()
400*6dbdd20aSAndroid Build Coastguard Worker // In developer builds w/ PERFETTO_DCHECK on a finalized message should
401*6dbdd20aSAndroid Build Coastguard Worker // invalidate the handle, in order to early catch bugs in the client code.
402*6dbdd20aSAndroid Build Coastguard Worker FakeRootMessage* msg4 = NewMessage();
403*6dbdd20aSAndroid Build Coastguard Worker MessageHandle<FakeRootMessage> handle4(msg4);
404*6dbdd20aSAndroid Build Coastguard Worker ASSERT_EQ(msg4, &*handle4);
405*6dbdd20aSAndroid Build Coastguard Worker msg4->Finalize();
406*6dbdd20aSAndroid Build Coastguard Worker ASSERT_EQ(nullptr, &*handle4);
407*6dbdd20aSAndroid Build Coastguard Worker #endif
408*6dbdd20aSAndroid Build Coastguard Worker
409*6dbdd20aSAndroid Build Coastguard Worker // Test also the behavior of handle with non-root (nested) messages.
410*6dbdd20aSAndroid Build Coastguard Worker
411*6dbdd20aSAndroid Build Coastguard Worker uint8_t* size_msg_2;
412*6dbdd20aSAndroid Build Coastguard Worker {
413*6dbdd20aSAndroid Build Coastguard Worker auto* nested_msg_1 = NewMessage()->BeginNestedMessage<FakeChildMessage>(3);
414*6dbdd20aSAndroid Build Coastguard Worker MessageHandle<FakeChildMessage> child_handle_1(nested_msg_1);
415*6dbdd20aSAndroid Build Coastguard Worker uint8_t* size_msg_1 = nested_msg_1->size_field();
416*6dbdd20aSAndroid Build Coastguard Worker memset(size_msg_1, 0, proto_utils::kMessageLengthFieldSize);
417*6dbdd20aSAndroid Build Coastguard Worker child_handle_1->AppendVarInt(1, 0x11);
418*6dbdd20aSAndroid Build Coastguard Worker
419*6dbdd20aSAndroid Build Coastguard Worker auto* nested_msg_2 = NewMessage()->BeginNestedMessage<FakeChildMessage>(2);
420*6dbdd20aSAndroid Build Coastguard Worker size_msg_2 = nested_msg_2->size_field();
421*6dbdd20aSAndroid Build Coastguard Worker memset(size_msg_2, 0, proto_utils::kMessageLengthFieldSize);
422*6dbdd20aSAndroid Build Coastguard Worker MessageHandle<FakeChildMessage> child_handle_2(nested_msg_2);
423*6dbdd20aSAndroid Build Coastguard Worker child_handle_2->AppendVarInt(2, 0xFF);
424*6dbdd20aSAndroid Build Coastguard Worker
425*6dbdd20aSAndroid Build Coastguard Worker // |nested_msg_1| should not be finalized yet.
426*6dbdd20aSAndroid Build Coastguard Worker ASSERT_EQ(0u, size_msg_1[0]);
427*6dbdd20aSAndroid Build Coastguard Worker
428*6dbdd20aSAndroid Build Coastguard Worker // This move should cause |nested_msg_1| to be finalized, but not
429*6dbdd20aSAndroid Build Coastguard Worker // |nested_msg_2|, which will be finalized only after the current scope.
430*6dbdd20aSAndroid Build Coastguard Worker child_handle_1 = std::move(child_handle_2);
431*6dbdd20aSAndroid Build Coastguard Worker ASSERT_EQ(0x82u, size_msg_1[0]);
432*6dbdd20aSAndroid Build Coastguard Worker ASSERT_EQ(0u, size_msg_2[0]);
433*6dbdd20aSAndroid Build Coastguard Worker }
434*6dbdd20aSAndroid Build Coastguard Worker ASSERT_EQ(0x3u, size_msg_2[0]);
435*6dbdd20aSAndroid Build Coastguard Worker }
436*6dbdd20aSAndroid Build Coastguard Worker
TEST_F(MessageTest,MoveMessageHandle)437*6dbdd20aSAndroid Build Coastguard Worker TEST_F(MessageTest, MoveMessageHandle) {
438*6dbdd20aSAndroid Build Coastguard Worker FakeRootMessage* msg = NewMessageWithSizeField();
439*6dbdd20aSAndroid Build Coastguard Worker uint8_t* msg_size = msg->size_field();
440*6dbdd20aSAndroid Build Coastguard Worker
441*6dbdd20aSAndroid Build Coastguard Worker // Test that the handle going out of scope causes the finalization of the
442*6dbdd20aSAndroid Build Coastguard Worker // target message.
443*6dbdd20aSAndroid Build Coastguard Worker {
444*6dbdd20aSAndroid Build Coastguard Worker MessageHandle<FakeRootMessage> handle1(msg);
445*6dbdd20aSAndroid Build Coastguard Worker MessageHandle<FakeRootMessage> handle2{};
446*6dbdd20aSAndroid Build Coastguard Worker handle1->AppendBytes(1 /* field_id */, kTestBytes, 1 /* size */);
447*6dbdd20aSAndroid Build Coastguard Worker handle2 = std::move(handle1);
448*6dbdd20aSAndroid Build Coastguard Worker ASSERT_EQ(0u, msg_size[0]);
449*6dbdd20aSAndroid Build Coastguard Worker }
450*6dbdd20aSAndroid Build Coastguard Worker ASSERT_EQ(0x3u, msg_size[0]);
451*6dbdd20aSAndroid Build Coastguard Worker }
452*6dbdd20aSAndroid Build Coastguard Worker
TEST_F(MessageTest,FinalizeWithCompaction)453*6dbdd20aSAndroid Build Coastguard Worker TEST_F(MessageTest, FinalizeWithCompaction) {
454*6dbdd20aSAndroid Build Coastguard Worker FakeRootMessage* msg = NewMessageWithSizeField();
455*6dbdd20aSAndroid Build Coastguard Worker
456*6dbdd20aSAndroid Build Coastguard Worker msg->AppendBytes(1 /* field_id */, kTestBytes, 5 /* size */);
457*6dbdd20aSAndroid Build Coastguard Worker uint32_t size = msg->Finalize();
458*6dbdd20aSAndroid Build Coastguard Worker EXPECT_EQ(7u, size);
459*6dbdd20aSAndroid Build Coastguard Worker EXPECT_EQ(8u, GetNumSerializedBytes());
460*6dbdd20aSAndroid Build Coastguard Worker }
461*6dbdd20aSAndroid Build Coastguard Worker
TEST_F(MessageTest,FinalizeWithoutCompaction)462*6dbdd20aSAndroid Build Coastguard Worker TEST_F(MessageTest, FinalizeWithoutCompaction) {
463*6dbdd20aSAndroid Build Coastguard Worker FakeRootMessage* msg = NewMessageWithSizeField();
464*6dbdd20aSAndroid Build Coastguard Worker
465*6dbdd20aSAndroid Build Coastguard Worker // This message doesn't fit into a single chunk, so it won't be compacted.
466*6dbdd20aSAndroid Build Coastguard Worker msg->AppendBytes(1 /* field_id */, kTestBytes, sizeof(kTestBytes) /* size */);
467*6dbdd20aSAndroid Build Coastguard Worker msg->AppendBytes(1 /* field_id */, kTestBytes, sizeof(kTestBytes) /* size */);
468*6dbdd20aSAndroid Build Coastguard Worker uint32_t size = msg->Finalize();
469*6dbdd20aSAndroid Build Coastguard Worker EXPECT_EQ(24u, size);
470*6dbdd20aSAndroid Build Coastguard Worker EXPECT_EQ(28u, GetNumSerializedBytes());
471*6dbdd20aSAndroid Build Coastguard Worker }
472*6dbdd20aSAndroid Build Coastguard Worker
473*6dbdd20aSAndroid Build Coastguard Worker } // namespace
474*6dbdd20aSAndroid Build Coastguard Worker } // namespace protozero
475