Primiano Tucci | 4f9b6d7 | 2017-12-05 20:59:16 +0000 | [diff] [blame] | 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 | |
Hector Dearman | e1e56b6 | 2018-02-21 19:11:58 +0000 | [diff] [blame] | 17 | #include "perfetto/protozero/message.h" |
Primiano Tucci | 4f9b6d7 | 2017-12-05 20:59:16 +0000 | [diff] [blame] | 18 | |
| 19 | #include <limits> |
| 20 | #include <memory> |
| 21 | #include <utility> |
| 22 | #include <vector> |
| 23 | |
Primiano Tucci | 4f9b6d7 | 2017-12-05 20:59:16 +0000 | [diff] [blame] | 24 | #include "perfetto/base/logging.h" |
Primiano Tucci | acb6ca3 | 2020-08-19 13:27:52 +0200 | [diff] [blame] | 25 | #include "perfetto/protozero/message_handle.h" |
| 26 | #include "perfetto/protozero/root_message.h" |
Eric Seckler | 2643c8f | 2019-01-18 07:35:58 +0000 | [diff] [blame] | 27 | #include "src/base/test/utils.h" |
Primiano Tucci | 4f9b6d7 | 2017-12-05 20:59:16 +0000 | [diff] [blame] | 28 | #include "src/protozero/test/fake_scattered_buffer.h" |
Primiano Tucci | 919ca1e | 2019-08-21 20:26:58 +0200 | [diff] [blame] | 29 | #include "test/gtest_and_gmock.h" |
Primiano Tucci | 4f9b6d7 | 2017-12-05 20:59:16 +0000 | [diff] [blame] | 30 | |
| 31 | namespace protozero { |
| 32 | |
| 33 | namespace { |
| 34 | |
Florian Mayer | dbd0878 | 2018-03-21 14:07:51 +0000 | [diff] [blame] | 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'}; |
Primiano Tucci | 4f9b6d7 | 2017-12-05 20:59:16 +0000 | [diff] [blame] | 41 | |
Primiano Tucci | acb6ca3 | 2020-08-19 13:27:52 +0200 | [diff] [blame] | 42 | class FakeRootMessage : public RootMessage<Message> {}; |
Hector Dearman | aaa4c19 | 2018-02-19 11:57:35 +0000 | [diff] [blame] | 43 | class FakeChildMessage : public Message {}; |
Primiano Tucci | 4f9b6d7 | 2017-12-05 20:59:16 +0000 | [diff] [blame] | 44 | |
| 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 | |
Hector Dearman | aaa4c19 | 2018-02-19 11:57:35 +0000 | [diff] [blame] | 52 | class MessageTest : public ::testing::Test { |
Primiano Tucci | 4f9b6d7 | 2017-12-05 20:59:16 +0000 | [diff] [blame] | 53 | public: |
| 54 | void SetUp() override { |
| 55 | buffer_.reset(new FakeScatteredBuffer(kChunkSize)); |
| 56 | stream_writer_.reset(new ScatteredStreamWriter(buffer_.get())); |
| 57 | readback_pos_ = 0; |
| 58 | } |
| 59 | |
| 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) + |
Primiano Tucci | acb6ca3 | 2020-08-19 13:27:52 +0200 | [diff] [blame] | 67 | sizeof(FakeRootMessage))); |
| 68 | FakeRootMessage* msg = reinterpret_cast<FakeRootMessage*>( |
| 69 | mem.get() + sizeof(kStartWatermark)); |
| 70 | msg->~FakeRootMessage(); |
Primiano Tucci | 4f9b6d7 | 2017-12-05 20:59:16 +0000 | [diff] [blame] | 71 | mem.reset(); |
| 72 | } |
| 73 | messages_.clear(); |
| 74 | stream_writer_.reset(); |
| 75 | buffer_.reset(); |
| 76 | } |
| 77 | |
Florian Mayer | 8a8044f | 2018-01-11 16:03:09 +0000 | [diff] [blame] | 78 | void ResetMessage(FakeRootMessage* msg) { msg->Reset(stream_writer_.get()); } |
| 79 | |
Primiano Tucci | 4f9b6d7 | 2017-12-05 20:59:16 +0000 | [diff] [blame] | 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)); |
Primiano Tucci | acb6ca3 | 2020-08-19 13:27:52 +0200 | [diff] [blame] | 90 | FakeRootMessage* msg = new (msg_start) FakeRootMessage(); |
Primiano Tucci | 4f9b6d7 | 2017-12-05 20:59:16 +0000 | [diff] [blame] | 91 | msg->Reset(stream_writer_.get()); |
| 92 | return msg; |
| 93 | } |
| 94 | |
| 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 | |
| 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 | |
Primiano Tucci | acb6ca3 | 2020-08-19 13:27:52 +0200 | [diff] [blame] | 108 | static void BuildNestedMessages(Message* msg, |
| 109 | uint32_t max_depth, |
| 110 | uint32_t depth = 0) { |
Primiano Tucci | 4f9b6d7 | 2017-12-05 20:59:16 +0000 | [diff] [blame] | 111 | for (uint32_t i = 1; i <= 128; ++i) |
| 112 | msg->AppendBytes(i, kTestBytes, sizeof(kTestBytes)); |
| 113 | |
Primiano Tucci | acb6ca3 | 2020-08-19 13:27:52 +0200 | [diff] [blame] | 114 | if (depth < max_depth) { |
Primiano Tucci | 4f9b6d7 | 2017-12-05 20:59:16 +0000 | [diff] [blame] | 115 | auto* nested_msg = |
| 116 | msg->BeginNestedMessage<FakeChildMessage>(1 + depth * 10); |
Primiano Tucci | acb6ca3 | 2020-08-19 13:27:52 +0200 | [diff] [blame] | 117 | BuildNestedMessages(nested_msg, max_depth, depth + 1); |
Primiano Tucci | 4f9b6d7 | 2017-12-05 20:59:16 +0000 | [diff] [blame] | 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 | |
Hector Dearman | aaa4c19 | 2018-02-19 11:57:35 +0000 | [diff] [blame] | 134 | TEST_F(MessageTest, ZeroLengthArraysAndStrings) { |
| 135 | Message* msg = NewMessage(); |
Hector Dearman | 8bf3e25 | 2018-01-26 11:33:58 +0000 | [diff] [blame] | 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 | |
Hector Dearman | aaa4c19 | 2018-02-19 11:57:35 +0000 | [diff] [blame] | 147 | TEST_F(MessageTest, BasicTypesNoNesting) { |
| 148 | Message* msg = NewMessage(); |
Primiano Tucci | 4f9b6d7 | 2017-12-05 20:59:16 +0000 | [diff] [blame] | 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 | |
Hector Dearman | aaa4c19 | 2018-02-19 11:57:35 +0000 | [diff] [blame] | 177 | TEST_F(MessageTest, NestedMessagesSimple) { |
| 178 | Message* root_msg = NewMessage(); |
Primiano Tucci | 4f9b6d7 | 2017-12-05 20:59:16 +0000 | [diff] [blame] | 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 | |
Oystein Eftevaag | aeecabf | 2018-10-19 13:11:57 -0700 | [diff] [blame] | 217 | // Tests using a AppendScatteredBytes to append raw bytes to |
| 218 | // a message using multiple individual buffers. |
| 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 | |
Primiano Tucci | 4f9b6d7 | 2017-12-05 20:59:16 +0000 | [diff] [blame] | 239 | // Checks that the size field of root and nested messages is properly written |
| 240 | // on finalization. |
Hector Dearman | aaa4c19 | 2018-02-19 11:57:35 +0000 | [diff] [blame] | 241 | TEST_F(MessageTest, BackfillSizeOnFinalization) { |
| 242 | Message* root_msg = NewMessage(); |
Primiano Tucci | 4f9b6d7 | 2017-12-05 20:59:16 +0000 | [diff] [blame] | 243 | uint8_t root_msg_size[proto_utils::kMessageLengthFieldSize] = {}; |
Primiano Tucci | 3a91887 | 2017-12-18 10:53:39 +0100 | [diff] [blame] | 244 | root_msg->set_size_field(&root_msg_size[0]); |
Primiano Tucci | 4f9b6d7 | 2017-12-05 20:59:16 +0000 | [diff] [blame] | 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 | |
Primiano Tucci | 3a91887 | 2017-12-18 10:53:39 +0100 | [diff] [blame] | 257 | root_msg->inc_size_already_written(6); |
| 258 | |
Primiano Tucci | 4f9b6d7 | 2017-12-05 20:59:16 +0000 | [diff] [blame] | 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. |
Primiano Tucci | 3a91887 | 2017-12-18 10:53:39 +0100 | [diff] [blame] | 266 | EXPECT_STREQ("\xD3\x81\x80\x00", reinterpret_cast<char*>(root_msg_size)); |
Primiano Tucci | 4f9b6d7 | 2017-12-05 20:59:16 +0000 | [diff] [blame] | 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 | |
Hector Dearman | aaa4c19 | 2018-02-19 11:57:35 +0000 | [diff] [blame] | 284 | TEST_F(MessageTest, StressTest) { |
| 285 | std::vector<Message*> nested_msgs; |
Primiano Tucci | 4f9b6d7 | 2017-12-05 20:59:16 +0000 | [diff] [blame] | 286 | |
Hector Dearman | aaa4c19 | 2018-02-19 11:57:35 +0000 | [diff] [blame] | 287 | Message* root_msg = NewMessage(); |
Primiano Tucci | acb6ca3 | 2020-08-19 13:27:52 +0200 | [diff] [blame] | 288 | BuildNestedMessages(root_msg, /*max_depth=*/10); |
Primiano Tucci | 4f9b6d7 | 2017-12-05 20:59:16 +0000 | [diff] [blame] | 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); |
Hector Dearman | f80401a | 2018-10-24 10:57:02 +0100 | [diff] [blame] | 297 | EXPECT_EQ(0xf9e32b65, buf_hash); |
Primiano Tucci | 4f9b6d7 | 2017-12-05 20:59:16 +0000 | [diff] [blame] | 298 | } |
| 299 | |
Primiano Tucci | acb6ca3 | 2020-08-19 13:27:52 +0200 | [diff] [blame] | 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 | |
Hector Dearman | aaa4c19 | 2018-02-19 11:57:35 +0000 | [diff] [blame] | 312 | TEST_F(MessageTest, DestructInvalidMessageHandle) { |
Florian Mayer | 8a8044f | 2018-01-11 16:03:09 +0000 | [diff] [blame] | 313 | FakeRootMessage* msg = NewMessage(); |
Primiano Tucci | acb6ca3 | 2020-08-19 13:27:52 +0200 | [diff] [blame] | 314 | EXPECT_DCHECK_DEATH({ |
| 315 | MessageHandle<FakeRootMessage> handle(msg); |
| 316 | ResetMessage(msg); |
| 317 | }); |
Florian Mayer | 8a8044f | 2018-01-11 16:03:09 +0000 | [diff] [blame] | 318 | } |
| 319 | |
Hector Dearman | aaa4c19 | 2018-02-19 11:57:35 +0000 | [diff] [blame] | 320 | TEST_F(MessageTest, MessageHandle) { |
Primiano Tucci | 4f9b6d7 | 2017-12-05 20:59:16 +0000 | [diff] [blame] | 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] = {}; |
Primiano Tucci | 3a91887 | 2017-12-18 10:53:39 +0100 | [diff] [blame] | 328 | msg1->set_size_field(&msg1_size[0]); |
| 329 | msg2->set_size_field(&msg2_size[0]); |
| 330 | msg3->set_size_field(&msg3_size[0]); |
Primiano Tucci | 4f9b6d7 | 2017-12-05 20:59:16 +0000 | [diff] [blame] | 331 | |
| 332 | // Test that the handle going out of scope causes the finalization of the |
| 333 | // target message and triggers the optional callback. |
Primiano Tucci | 4f9b6d7 | 2017-12-05 20:59:16 +0000 | [diff] [blame] | 334 | { |
Hector Dearman | aaa4c19 | 2018-02-19 11:57:35 +0000 | [diff] [blame] | 335 | MessageHandle<FakeRootMessage> handle1(msg1); |
Primiano Tucci | 4f9b6d7 | 2017-12-05 20:59:16 +0000 | [diff] [blame] | 336 | handle1->AppendBytes(1 /* field_id */, kTestBytes, 1 /* size */); |
| 337 | ASSERT_EQ(0u, msg1_size[0]); |
| 338 | } |
| 339 | ASSERT_EQ(0x83u, msg1_size[0]); |
Primiano Tucci | 4f9b6d7 | 2017-12-05 20:59:16 +0000 | [diff] [blame] | 340 | |
| 341 | // Test that the handle can be late initialized. |
Hector Dearman | aaa4c19 | 2018-02-19 11:57:35 +0000 | [diff] [blame] | 342 | MessageHandle<FakeRootMessage> handle2(ignored_msg); |
| 343 | handle2 = MessageHandle<FakeRootMessage>(msg2); |
Primiano Tucci | 4f9b6d7 | 2017-12-05 20:59:16 +0000 | [diff] [blame] | 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. |
Hector Dearman | aaa4c19 | 2018-02-19 11:57:35 +0000 | [diff] [blame] | 349 | MessageHandle<FakeRootMessage> handle_swp(ignored_msg); |
Primiano Tucci | 4f9b6d7 | 2017-12-05 20:59:16 +0000 | [diff] [blame] | 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 | |
Hector Dearman | aaa4c19 | 2018-02-19 11:57:35 +0000 | [diff] [blame] | 354 | MessageHandle<FakeRootMessage> handle3(msg3); |
Primiano Tucci | 4f9b6d7 | 2017-12-05 20:59:16 +0000 | [diff] [blame] | 355 | handle3->AppendBytes(1 /* field_id */, kTestBytes, 4 /* size */); |
| 356 | ASSERT_EQ(0u, msg3_size[0]); // msg2 should be NOT finalized yet. |
Primiano Tucci | 4f9b6d7 | 2017-12-05 20:59:16 +0000 | [diff] [blame] | 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 */); |
Hector Dearman | aaa4c19 | 2018-02-19 11:57:35 +0000 | [diff] [blame] | 366 | MessageHandle<FakeRootMessage> another_handle(ignored_msg); |
Primiano Tucci | 4f9b6d7 | 2017-12-05 20:59:16 +0000 | [diff] [blame] | 367 | handle_swp = std::move(another_handle); |
| 368 | ASSERT_EQ(0x90u, msg3_size[0]); // |msg3| should be finalized at this point. |
Primiano Tucci | 4f9b6d7 | 2017-12-05 20:59:16 +0000 | [diff] [blame] | 369 | |
Florian Mayer | 8a8044f | 2018-01-11 16:03:09 +0000 | [diff] [blame] | 370 | #if PERFETTO_DCHECK_IS_ON() |
Primiano Tucci | 4f9b6d7 | 2017-12-05 20:59:16 +0000 | [diff] [blame] | 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(); |
Hector Dearman | aaa4c19 | 2018-02-19 11:57:35 +0000 | [diff] [blame] | 374 | MessageHandle<FakeRootMessage> handle4(msg4); |
Primiano Tucci | 4f9b6d7 | 2017-12-05 20:59:16 +0000 | [diff] [blame] | 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 | |
Primiano Tucci | 3a91887 | 2017-12-18 10:53:39 +0100 | [diff] [blame] | 382 | uint8_t* size_msg_2; |
Primiano Tucci | 4f9b6d7 | 2017-12-05 20:59:16 +0000 | [diff] [blame] | 383 | { |
| 384 | auto* nested_msg_1 = NewMessage()->BeginNestedMessage<FakeChildMessage>(3); |
Hector Dearman | aaa4c19 | 2018-02-19 11:57:35 +0000 | [diff] [blame] | 385 | MessageHandle<FakeChildMessage> child_handle_1(nested_msg_1); |
Primiano Tucci | 3a91887 | 2017-12-18 10:53:39 +0100 | [diff] [blame] | 386 | uint8_t* size_msg_1 = nested_msg_1->size_field(); |
| 387 | memset(size_msg_1, 0, proto_utils::kMessageLengthFieldSize); |
Primiano Tucci | 4f9b6d7 | 2017-12-05 20:59:16 +0000 | [diff] [blame] | 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(); |
Primiano Tucci | 3a91887 | 2017-12-18 10:53:39 +0100 | [diff] [blame] | 392 | memset(size_msg_2, 0, proto_utils::kMessageLengthFieldSize); |
Hector Dearman | aaa4c19 | 2018-02-19 11:57:35 +0000 | [diff] [blame] | 393 | MessageHandle<FakeChildMessage> child_handle_2(nested_msg_2); |
Primiano Tucci | 4f9b6d7 | 2017-12-05 20:59:16 +0000 | [diff] [blame] | 394 | child_handle_2->AppendVarInt(2, 0xFF); |
| 395 | |
| 396 | // |nested_msg_1| should not be finalized yet. |
Primiano Tucci | 3a91887 | 2017-12-18 10:53:39 +0100 | [diff] [blame] | 397 | ASSERT_EQ(0u, size_msg_1[0]); |
Primiano Tucci | 4f9b6d7 | 2017-12-05 20:59:16 +0000 | [diff] [blame] | 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); |
Primiano Tucci | 3a91887 | 2017-12-18 10:53:39 +0100 | [diff] [blame] | 402 | ASSERT_EQ(0x82u, size_msg_1[0]); |
| 403 | ASSERT_EQ(0u, size_msg_2[0]); |
Primiano Tucci | 4f9b6d7 | 2017-12-05 20:59:16 +0000 | [diff] [blame] | 404 | } |
Primiano Tucci | 3a91887 | 2017-12-18 10:53:39 +0100 | [diff] [blame] | 405 | ASSERT_EQ(0x83u, size_msg_2[0]); |
Primiano Tucci | 4f9b6d7 | 2017-12-05 20:59:16 +0000 | [diff] [blame] | 406 | } |
| 407 | |
Hector Dearman | aaa4c19 | 2018-02-19 11:57:35 +0000 | [diff] [blame] | 408 | TEST_F(MessageTest, MoveMessageHandle) { |
Primiano Tucci | 4f9b6d7 | 2017-12-05 20:59:16 +0000 | [diff] [blame] | 409 | FakeRootMessage* msg = NewMessage(); |
| 410 | uint8_t msg_size[proto_utils::kMessageLengthFieldSize] = {}; |
Primiano Tucci | 3a91887 | 2017-12-18 10:53:39 +0100 | [diff] [blame] | 411 | msg->set_size_field(&msg_size[0]); |
Primiano Tucci | 4f9b6d7 | 2017-12-05 20:59:16 +0000 | [diff] [blame] | 412 | |
| 413 | // Test that the handle going out of scope causes the finalization of the |
| 414 | // target message. |
| 415 | { |
Hector Dearman | aaa4c19 | 2018-02-19 11:57:35 +0000 | [diff] [blame] | 416 | MessageHandle<FakeRootMessage> handle1(msg); |
| 417 | MessageHandle<FakeRootMessage> handle2{}; |
Primiano Tucci | 4f9b6d7 | 2017-12-05 20:59:16 +0000 | [diff] [blame] | 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 |