Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(737)

Side by Side Diff: components/tracing/core/proto_zero_message_unittest.cc

Issue 2158323005: tracing v2: Introduce handles for safe usage of ProtoZeroMessage (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: . Created 4 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2016 The Chromium Authors. All rights reserved. 1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "components/tracing/core/proto_zero_message.h" 5 #include "components/tracing/core/proto_zero_message.h"
6 6
7 #include <limits> 7 #include <limits>
8 #include <memory> 8 #include <memory>
9 #include <vector> 9 #include <vector>
10 10
11 #include "base/hash.h" 11 #include "base/hash.h"
12 #include "components/tracing/core/proto_utils.h" 12 #include "components/tracing/core/proto_utils.h"
13 #include "components/tracing/core/proto_zero_message_handle.h"
13 #include "components/tracing/test/fake_scattered_buffer.h" 14 #include "components/tracing/test/fake_scattered_buffer.h"
14 #include "testing/gtest/include/gtest/gtest.h" 15 #include "testing/gtest/include/gtest/gtest.h"
15 16
16 namespace tracing { 17 namespace tracing {
17 namespace v2 { 18 namespace v2 {
18 19
19 const size_t kChunkSize = 16; 20 const size_t kChunkSize = 16;
20 const uint8_t kTestBytes[] = {0, 0, 0, 0, 0x42, 1, 0x42, 0xff, 0x42, 0}; 21 const uint8_t kTestBytes[] = {0, 0, 0, 0, 0x42, 1, 0x42, 0xff, 0x42, 0};
21 const char kStartWatermark[] = {'a', 'b', 'c', 'd', '1', '2', '3', '\0'}; 22 const char kStartWatermark[] = {'a', 'b', 'c', 'd', '1', '2', '3', '\0'};
22 const char kEndWatermark[] = {'9', '8', '7', '6', 'z', 'w', 'y', '\0'}; 23 const char kEndWatermark[] = {'9', '8', '7', '6', 'z', 'w', 'y', '\0'};
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
69 return buffer_->chunks().size() * kChunkSize - 70 return buffer_->chunks().size() * kChunkSize -
70 stream_writer_->bytes_available(); 71 stream_writer_->bytes_available();
71 } 72 }
72 73
73 std::string GetNextSerializedBytes(size_t num_bytes) { 74 std::string GetNextSerializedBytes(size_t num_bytes) {
74 size_t old_readback_pos = readback_pos_; 75 size_t old_readback_pos = readback_pos_;
75 readback_pos_ += num_bytes; 76 readback_pos_ += num_bytes;
76 return buffer_->GetBytesAsString(old_readback_pos, num_bytes); 77 return buffer_->GetBytesAsString(old_readback_pos, num_bytes);
77 } 78 }
78 79
80 std::string GetSerializedBytes(size_t start, size_t num_bytes) {
81 return buffer_->GetBytesAsString(start, num_bytes);
82 }
83
79 static void BuildNestedMessages(uint32_t depth, ProtoZeroMessage* msg) { 84 static void BuildNestedMessages(uint32_t depth, ProtoZeroMessage* msg) {
80 for (uint32_t i = 1; i <= 128; ++i) 85 for (uint32_t i = 1; i <= 128; ++i)
81 msg->AppendBytes(i, kTestBytes, sizeof(kTestBytes)); 86 msg->AppendBytes(i, kTestBytes, sizeof(kTestBytes));
82 87
83 if (depth < ProtoZeroMessage::kMaxNestingDepth) { 88 if (depth < ProtoZeroMessage::kMaxNestingDepth) {
84 auto* child_msg = msg->BeginNestedMessage<FakeMessage>(1 + depth * 10); 89 auto* child_msg = msg->BeginNestedMessage<FakeMessage>(1 + depth * 10);
85 BuildNestedMessages(depth + 1, child_msg); 90 BuildNestedMessages(depth + 1, child_msg);
86 } 91 }
87 92
88 for (uint32_t i = 129; i <= 256; ++i) 93 for (uint32_t i = 129; i <= 256; ++i)
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after
163 ASSERT_EQ("8A0882808000", GetNextSerializedBytes(6)); 168 ASSERT_EQ("8A0882808000", GetNextSerializedBytes(6));
164 ASSERT_EQ("2002", GetNextSerializedBytes(2)); 169 ASSERT_EQ("2002", GetNextSerializedBytes(2));
165 170
166 ASSERT_EQ("2803", GetNextSerializedBytes(2)); 171 ASSERT_EQ("2803", GetNextSerializedBytes(2));
167 } 172 }
168 173
169 // Checks that the size field of root and nested messages is properly written 174 // Checks that the size field of root and nested messages is properly written
170 // on finalization. 175 // on finalization.
171 TEST_F(ProtoZeroMessageTest, BackfillSizeOnFinalization) { 176 TEST_F(ProtoZeroMessageTest, BackfillSizeOnFinalization) {
172 ProtoZeroMessage* root_msg = NewMessage(); 177 ProtoZeroMessage* root_msg = NewMessage();
173 uint8_t root_msg_size[proto::kMessageLengthFieldSize]; 178 uint8_t root_msg_size[proto::kMessageLengthFieldSize] = {};
174 root_msg->set_size_field( 179 root_msg->set_size_field(
175 {&root_msg_size[0], &root_msg_size[proto::kMessageLengthFieldSize]}); 180 {&root_msg_size[0], &root_msg_size[proto::kMessageLengthFieldSize]});
176 root_msg->AppendVarIntU32(1, 0x42); 181 root_msg->AppendVarIntU32(1, 0x42);
177 182
178 FakeMessage* nested_msg_1 = root_msg->BeginNestedMessage<FakeMessage>(2); 183 FakeMessage* nested_msg_1 = root_msg->BeginNestedMessage<FakeMessage>(2);
179 nested_msg_1->AppendVarIntU32(3, 0x43); 184 nested_msg_1->AppendVarIntU32(3, 0x43);
180 185
181 FakeMessage* nested_msg_2 = nested_msg_1->BeginNestedMessage<FakeMessage>(4); 186 FakeMessage* nested_msg_2 = nested_msg_1->BeginNestedMessage<FakeMessage>(4);
182 uint8_t buf200[200]; 187 uint8_t buf200[200];
183 memset(buf200, 0x42, sizeof(buf200)); 188 memset(buf200, 0x42, sizeof(buf200));
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
219 224
220 // The main point of this test is to stress the code paths and test for 225 // The main point of this test is to stress the code paths and test for
221 // unexpected crashes of the production code. The actual serialization is 226 // unexpected crashes of the production code. The actual serialization is
222 // already covered in the other text fixtures. Keeping just a final smoke test 227 // already covered in the other text fixtures. Keeping just a final smoke test
223 // here on the full buffer hash. 228 // here on the full buffer hash.
224 std::string full_buf = GetNextSerializedBytes(GetNumSerializedBytes()); 229 std::string full_buf = GetNextSerializedBytes(GetNumSerializedBytes());
225 uint32_t buf_hash = base::SuperFastHash(full_buf.data(), full_buf.size()); 230 uint32_t buf_hash = base::SuperFastHash(full_buf.data(), full_buf.size());
226 EXPECT_EQ(0x14BC1BA3u, buf_hash); 231 EXPECT_EQ(0x14BC1BA3u, buf_hash);
227 } 232 }
228 233
234 TEST_F(ProtoZeroMessageTest, MessageHandle) {
235 ProtoZeroMessage* msg1 = NewMessage();
236 ProtoZeroMessage* msg2 = NewMessage();
237 ProtoZeroMessage* msg3 = NewMessage();
238 ProtoZeroMessage* ignored_msg = NewMessage();
239 uint8_t msg1_size[proto::kMessageLengthFieldSize] = {};
240 uint8_t msg2_size[proto::kMessageLengthFieldSize] = {};
241 uint8_t msg3_size[proto::kMessageLengthFieldSize] = {};
242 msg1->set_size_field(
243 {&msg1_size[0], &msg1_size[proto::kMessageLengthFieldSize]});
244 msg2->set_size_field(
245 {&msg2_size[0], &msg2_size[proto::kMessageLengthFieldSize]});
246 msg3->set_size_field(
247 {&msg3_size[0], &msg3_size[proto::kMessageLengthFieldSize]});
248
249 // Test that the handle going out of scope causes the finalization of the
250 // target message.
251 {
252 ProtoZeroMessageHandleBase handle1(msg1);
253 handle1->AppendBytes(1 /* field_id */, kTestBytes, 1 /* size */);
254 ASSERT_EQ(0u, msg1_size[0]);
255 }
256 ASSERT_EQ(0x83u, msg1_size[0]);
257
258 // Test that the handle can be late initialized.
259 ProtoZeroMessageHandleBase handle2(ignored_msg);
260 handle2 = ProtoZeroMessageHandleBase(msg2);
261 handle2->AppendBytes(1 /* field_id */, kTestBytes, 2 /* size */);
262 ASSERT_EQ(0u, msg2_size[0]); // |msg2| should not be finalized yet.
263
264 // Test that std::move works and does NOT cause finalization of the moved
265 // message.
266 ProtoZeroMessageHandleBase handle_swp(ignored_msg);
267 handle_swp = std::move(handle2);
268 ASSERT_EQ(0u, msg2_size[0]); // msg2 should be NOT finalized yet.
269 handle_swp->AppendBytes(2 /* field_id */, kTestBytes, 3 /* size */);
270
271 ProtoZeroMessageHandleBase handle3(msg3);
272 handle3->AppendBytes(1 /* field_id */, kTestBytes, 4 /* size */);
273 ASSERT_EQ(0u, msg3_size[0]); // msg2 should be NOT finalized yet.
274
275 // Both |handle3| and |handle_swp| point to a valid message (respectively,
276 // |msg3| and |msg2|). Now move |handle3| into |handle_swp|.
277 handle_swp = std::move(handle3);
278 ASSERT_EQ(0x89u, msg2_size[0]); // |msg2| should be finalized at this point.
279
280 // At this point writing into handle_swp should actually write into |msg3|.
281 ASSERT_EQ(msg3, &*handle_swp);
282 handle_swp->AppendBytes(2 /* field_id */, kTestBytes, 8 /* size */);
283 ProtoZeroMessageHandleBase another_handle(ignored_msg);
284 handle_swp = std::move(another_handle);
285 ASSERT_EQ(0x90u, msg3_size[0]); // |msg3| should be finalized at this point.
286
287 #if DCHECK_IS_ON()
288 // In developer builds w/ DCHECK on a finalized message should invalidate the
289 // handle, in order to early catch bugs in the client code.
290 ProtoZeroMessage* msg4 = NewMessage();
291 ProtoZeroMessageHandleBase handle4(msg4);
292 ASSERT_EQ(msg4, &*handle4);
293 msg4->Finalize();
294 ASSERT_EQ(nullptr, &*handle4);
295 #endif
296
297 // Test also the behavior of handle with non-root (nested) messages.
298
299 ContiguousMemoryRange size_msg_2;
300 {
301 auto* child_msg_1 = NewMessage()->BeginNestedMessage<FakeMessage>(3);
302 ProtoZeroMessageHandle<FakeMessage> child_handle_1(child_msg_1);
303 ContiguousMemoryRange size_msg_1 = child_msg_1->size_field();
304 memset(size_msg_1.begin, 0, size_msg_1.size());
305 child_handle_1->AppendVarIntU32(1, 0x11);
306
307 auto* child_msg_2 = NewMessage()->BeginNestedMessage<FakeMessage>(2);
308 size_msg_2 = child_msg_2->size_field();
309 memset(size_msg_2.begin, 0, size_msg_2.size());
310 ProtoZeroMessageHandle<FakeMessage> child_handle_2(child_msg_2);
311 child_handle_2->AppendVarIntU32(2, 0xFF);
312
313 // |child_msg_1| should not be finalized yet.
314 ASSERT_EQ(0u, size_msg_1.begin[0]);
315
316 // should stay NOT finalized, until end of the current scope.
317 child_handle_1 = std::move(child_handle_2);
318 // This move should cause |child_msg_1| to be finalized, while |child_msg_2|
alph 2016/07/20 18:35:00 s/while/but not/
Primiano Tucci (use gerrit) 2016/07/21 10:50:03 Oh I must have accidentally swapped the lines. Thi
319 ASSERT_EQ(0x82u, size_msg_1.begin[0]);
320 ASSERT_EQ(0u, size_msg_2.begin[0]);
321 }
322 ASSERT_EQ(0x83u, size_msg_2.begin[0]);
323 }
324
229 } // namespace v2 325 } // namespace v2
230 } // namespace tracing 326 } // namespace tracing
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698