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