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