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