1 // Copyright 2018 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "components/metrics/call_stack_profile_metadata.h"
10 #include "base/ranges/algorithm.h"
11 #include "base/strings/strcat.h"
12 #include "base/strings/string_number_conversions.h"
13 #include "testing/gtest/include/gtest/gtest.h"
14 #include "third_party/metrics_proto/sampled_profile.pb.h"
20 // Expects that |expected_item| was applied to |samples| at |sample_index| and
21 // |metadata_index|. Because of the "edge-triggered" metadata encoding, this
22 // expectation will be valid for the first sample seeing the item only.
23 void ExpectMetadataApplied(
24 const base::MetadataRecorder::Item& expected_item,
25 const google::protobuf::RepeatedPtrField<CallStackProfile::StackSample>&
29 const google::protobuf::RepeatedField<uint64_t>& name_hashes) {
30 const std::string index_info =
31 base::StrCat({"at sample_index ", base::NumberToString(sample_index),
32 ", metadata_index ", base::NumberToString(metadata_index)});
33 const int name_hash_index =
34 base::ranges::find(name_hashes, expected_item.name_hash) -
36 ASSERT_NE(name_hash_index, name_hashes.size()) << index_info;
38 ASSERT_LT(sample_index, samples.size()) << index_info;
39 const CallStackProfile::StackSample& sample = samples[sample_index];
40 ASSERT_LT(metadata_index, sample.metadata_size()) << index_info;
41 const CallStackProfile::MetadataItem& item = sample.metadata(metadata_index);
42 EXPECT_EQ(name_hash_index, item.name_hash_index()) << index_info;
44 EXPECT_EQ(expected_item.key.has_value(), item.has_key()) << index_info;
45 if (expected_item.key.has_value())
46 EXPECT_EQ(*expected_item.key, item.key()) << index_info;
47 EXPECT_EQ(expected_item.value, item.value()) << index_info;
50 // Expects that the |item| was unapplied at |sample|. Because of the
51 // "edge-triggered" metadata encoding, this expectation will be valid for the
52 // sample following the last sample with the item only.
53 void ExpectMetadataUnapplied(
54 const base::MetadataRecorder::Item& expected_item,
55 const google::protobuf::RepeatedPtrField<CallStackProfile::StackSample>&
59 const google::protobuf::RepeatedField<uint64_t>& name_hashes) {
60 const std::string index_info =
61 base::StrCat({"at sample_index ", base::NumberToString(sample_index),
62 ", metadata_index ", base::NumberToString(metadata_index)});
63 const int name_hash_index =
64 base::ranges::find(name_hashes, expected_item.name_hash) -
66 ASSERT_NE(name_hash_index, name_hashes.size()) << index_info;
68 ASSERT_LT(sample_index, samples.size()) << index_info;
69 const CallStackProfile::StackSample& sample = samples[sample_index];
70 ASSERT_LT(metadata_index, sample.metadata_size()) << index_info;
71 const CallStackProfile::MetadataItem& item = sample.metadata(metadata_index);
72 EXPECT_EQ(name_hash_index, item.name_hash_index()) << index_info;
74 EXPECT_EQ(expected_item.key.has_value(), item.has_key()) << index_info;
75 if (expected_item.key.has_value())
76 EXPECT_EQ(*expected_item.key, item.key()) << index_info;
77 EXPECT_FALSE(item.has_value()) << index_info;
82 TEST(CallStackProfileMetadataTest, MetadataRecorder_NoItems) {
83 base::MetadataRecorder metadata_recorder;
84 CallStackProfileMetadata metadata;
85 google::protobuf::RepeatedField<uint64_t> name_hashes;
87 metadata.RecordMetadata(base::MetadataRecorder::MetadataProvider(
88 &metadata_recorder, base::PlatformThread::CurrentId()));
90 google::protobuf::RepeatedPtrField<CallStackProfile::MetadataItem> items =
91 metadata.CreateSampleMetadata(&name_hashes);
93 ASSERT_EQ(0, name_hashes.size());
94 ASSERT_EQ(0, items.size());
97 TEST(CallStackProfileMetadataTest, MetadataRecorder_SetItem) {
98 base::MetadataRecorder metadata_recorder;
99 CallStackProfileMetadata metadata;
100 google::protobuf::RepeatedField<uint64_t> name_hashes;
102 metadata_recorder.Set(100, absl::nullopt, absl::nullopt, 10);
103 metadata.RecordMetadata(base::MetadataRecorder::MetadataProvider(
104 &metadata_recorder, base::PlatformThread::CurrentId()));
105 google::protobuf::RepeatedPtrField<CallStackProfile::MetadataItem> items =
106 metadata.CreateSampleMetadata(&name_hashes);
108 ASSERT_EQ(1, name_hashes.size());
109 EXPECT_EQ(100u, name_hashes[0]);
111 ASSERT_EQ(1, items.size());
112 EXPECT_EQ(0, items[0].name_hash_index());
113 EXPECT_FALSE(items[0].has_key());
114 EXPECT_EQ(10, items[0].value());
117 TEST(CallStackProfileMetadataTest, MetadataRecorder_SetKeyedItem) {
118 base::MetadataRecorder metadata_recorder;
119 CallStackProfileMetadata metadata;
120 google::protobuf::RepeatedField<uint64_t> name_hashes;
122 metadata_recorder.Set(100, 50, absl::nullopt, 10);
123 metadata.RecordMetadata(base::MetadataRecorder::MetadataProvider(
124 &metadata_recorder, base::PlatformThread::CurrentId()));
125 google::protobuf::RepeatedPtrField<CallStackProfile::MetadataItem> items =
126 metadata.CreateSampleMetadata(&name_hashes);
128 ASSERT_EQ(1, name_hashes.size());
129 EXPECT_EQ(100u, name_hashes[0]);
131 ASSERT_EQ(1, items.size());
132 EXPECT_EQ(0, items[0].name_hash_index());
133 EXPECT_TRUE(items[0].has_key());
134 EXPECT_EQ(50, items[0].key());
135 EXPECT_EQ(10, items[0].value());
138 TEST(CallStackProfileMetadataTest, MetadataRecorder_SetThreadItem) {
139 base::MetadataRecorder metadata_recorder;
140 CallStackProfileMetadata metadata;
141 google::protobuf::RepeatedField<uint64_t> name_hashes;
143 metadata_recorder.Set(100, absl::nullopt, base::PlatformThread::CurrentId(),
145 metadata_recorder.Set(100, absl::nullopt, base::kInvalidThreadId, 20);
146 metadata.RecordMetadata(base::MetadataRecorder::MetadataProvider(
147 &metadata_recorder, base::PlatformThread::CurrentId()));
148 google::protobuf::RepeatedPtrField<CallStackProfile::MetadataItem> items =
149 metadata.CreateSampleMetadata(&name_hashes);
151 ASSERT_EQ(1, name_hashes.size());
152 EXPECT_EQ(100u, name_hashes[0]);
154 ASSERT_EQ(1, items.size());
155 EXPECT_EQ(0, items[0].name_hash_index());
156 EXPECT_FALSE(items[0].has_key());
157 EXPECT_EQ(10, items[0].value());
160 TEST(CallStackProfileMetadataTest, MetadataRecorder_RepeatItem) {
161 base::MetadataRecorder metadata_recorder;
162 CallStackProfileMetadata metadata;
163 google::protobuf::RepeatedField<uint64_t> name_hashes;
165 metadata_recorder.Set(100, absl::nullopt, absl::nullopt, 10);
166 metadata.RecordMetadata(base::MetadataRecorder::MetadataProvider(
167 &metadata_recorder, base::PlatformThread::CurrentId()));
168 std::ignore = metadata.CreateSampleMetadata(&name_hashes);
170 metadata.RecordMetadata(base::MetadataRecorder::MetadataProvider(
171 &metadata_recorder, base::PlatformThread::CurrentId()));
172 google::protobuf::RepeatedPtrField<CallStackProfile::MetadataItem> items =
173 metadata.CreateSampleMetadata(&name_hashes);
175 // The second sample shouldn't have any metadata because it's all the same
176 // as the last sample.
177 EXPECT_EQ(1, name_hashes.size());
178 EXPECT_TRUE(items.empty());
181 TEST(CallStackProfileMetadataTest, MetadataRecorder_RepeatKeyedItem) {
182 base::MetadataRecorder metadata_recorder;
183 CallStackProfileMetadata metadata;
184 google::protobuf::RepeatedField<uint64_t> name_hashes;
186 metadata_recorder.Set(100, 50, absl::nullopt, 10);
187 metadata.RecordMetadata(base::MetadataRecorder::MetadataProvider(
188 &metadata_recorder, base::PlatformThread::CurrentId()));
189 std::ignore = metadata.CreateSampleMetadata(&name_hashes);
191 metadata.RecordMetadata(base::MetadataRecorder::MetadataProvider(
192 &metadata_recorder, base::PlatformThread::CurrentId()));
193 google::protobuf::RepeatedPtrField<CallStackProfile::MetadataItem> items =
194 metadata.CreateSampleMetadata(&name_hashes);
196 // The second sample shouldn't have any metadata because it's all the same
197 // as the last sample.
198 EXPECT_EQ(1, name_hashes.size());
199 EXPECT_TRUE(items.empty());
202 TEST(CallStackProfileMetadataTest, MetadataRecorder_ModifiedItem) {
203 base::MetadataRecorder metadata_recorder;
204 CallStackProfileMetadata metadata;
205 google::protobuf::RepeatedField<uint64_t> name_hashes;
207 metadata_recorder.Set(100, absl::nullopt, absl::nullopt, 10);
208 metadata.RecordMetadata(base::MetadataRecorder::MetadataProvider(
209 &metadata_recorder, base::PlatformThread::CurrentId()));
210 std::ignore = metadata.CreateSampleMetadata(&name_hashes);
212 metadata_recorder.Set(100, absl::nullopt, absl::nullopt, 11);
213 metadata.RecordMetadata(base::MetadataRecorder::MetadataProvider(
214 &metadata_recorder, base::PlatformThread::CurrentId()));
215 google::protobuf::RepeatedPtrField<CallStackProfile::MetadataItem> items =
216 metadata.CreateSampleMetadata(&name_hashes);
218 EXPECT_EQ(1, name_hashes.size());
220 ASSERT_EQ(1, items.size());
221 EXPECT_EQ(0, items[0].name_hash_index());
222 EXPECT_FALSE(items[0].has_key());
223 EXPECT_EQ(11, items[0].value());
226 TEST(CallStackProfileMetadataTest, MetadataRecorder_ModifiedKeyedItem) {
227 base::MetadataRecorder metadata_recorder;
228 CallStackProfileMetadata metadata;
229 google::protobuf::RepeatedField<uint64_t> name_hashes;
231 metadata_recorder.Set(100, 50, absl::nullopt, 10);
232 metadata.RecordMetadata(base::MetadataRecorder::MetadataProvider(
233 &metadata_recorder, base::PlatformThread::CurrentId()));
234 std::ignore = metadata.CreateSampleMetadata(&name_hashes);
236 metadata_recorder.Set(100, 50, absl::nullopt, 11);
237 metadata.RecordMetadata(base::MetadataRecorder::MetadataProvider(
238 &metadata_recorder, base::PlatformThread::CurrentId()));
239 google::protobuf::RepeatedPtrField<CallStackProfile::MetadataItem> items =
240 metadata.CreateSampleMetadata(&name_hashes);
242 EXPECT_EQ(1, name_hashes.size());
244 ASSERT_EQ(1, items.size());
245 EXPECT_EQ(0, items[0].name_hash_index());
246 EXPECT_TRUE(items[0].has_key());
247 EXPECT_EQ(50, items[0].key());
248 EXPECT_EQ(11, items[0].value());
251 TEST(CallStackProfileMetadataTest, MetadataRecorder_NewItem) {
252 base::MetadataRecorder metadata_recorder;
253 CallStackProfileMetadata metadata;
254 google::protobuf::RepeatedField<uint64_t> name_hashes;
256 metadata_recorder.Set(100, absl::nullopt, absl::nullopt, 10);
257 metadata.RecordMetadata(base::MetadataRecorder::MetadataProvider(
258 &metadata_recorder, base::PlatformThread::CurrentId()));
259 std::ignore = metadata.CreateSampleMetadata(&name_hashes);
261 metadata_recorder.Set(101, absl::nullopt, absl::nullopt, 11);
262 metadata.RecordMetadata(base::MetadataRecorder::MetadataProvider(
263 &metadata_recorder, base::PlatformThread::CurrentId()));
264 google::protobuf::RepeatedPtrField<CallStackProfile::MetadataItem> items =
265 metadata.CreateSampleMetadata(&name_hashes);
267 ASSERT_EQ(2, name_hashes.size());
268 EXPECT_EQ(101u, name_hashes[1]);
270 ASSERT_EQ(1, items.size());
271 EXPECT_EQ(1, items[0].name_hash_index());
272 EXPECT_FALSE(items[0].has_key());
273 EXPECT_EQ(11, items[0].value());
276 TEST(CallStackProfileMetadataTest, MetadataRecorder_NewKeyedItem) {
277 base::MetadataRecorder metadata_recorder;
278 CallStackProfileMetadata metadata;
279 google::protobuf::RepeatedField<uint64_t> name_hashes;
281 metadata_recorder.Set(100, 50, absl::nullopt, 10);
282 metadata.RecordMetadata(base::MetadataRecorder::MetadataProvider(
283 &metadata_recorder, base::PlatformThread::CurrentId()));
284 std::ignore = metadata.CreateSampleMetadata(&name_hashes);
286 metadata_recorder.Set(101, 50, absl::nullopt, 11);
287 metadata.RecordMetadata(base::MetadataRecorder::MetadataProvider(
288 &metadata_recorder, base::PlatformThread::CurrentId()));
289 google::protobuf::RepeatedPtrField<CallStackProfile::MetadataItem> items =
290 metadata.CreateSampleMetadata(&name_hashes);
292 ASSERT_EQ(2, name_hashes.size());
293 EXPECT_EQ(101u, name_hashes[1]);
295 ASSERT_EQ(1, items.size());
296 EXPECT_EQ(1, items[0].name_hash_index());
297 EXPECT_TRUE(items[0].has_key());
298 EXPECT_EQ(50, items[0].key());
299 EXPECT_EQ(11, items[0].value());
302 TEST(CallStackProfileMetadataTest, MetadataRecorder_RemovedItem) {
303 base::MetadataRecorder metadata_recorder;
304 CallStackProfileMetadata metadata;
305 google::protobuf::RepeatedField<uint64_t> name_hashes;
307 metadata_recorder.Set(100, absl::nullopt, absl::nullopt, 10);
308 metadata.RecordMetadata(base::MetadataRecorder::MetadataProvider(
309 &metadata_recorder, base::PlatformThread::CurrentId()));
310 std::ignore = metadata.CreateSampleMetadata(&name_hashes);
312 metadata_recorder.Remove(100, absl::nullopt, absl::nullopt);
313 metadata.RecordMetadata(base::MetadataRecorder::MetadataProvider(
314 &metadata_recorder, base::PlatformThread::CurrentId()));
315 google::protobuf::RepeatedPtrField<CallStackProfile::MetadataItem> items =
316 metadata.CreateSampleMetadata(&name_hashes);
318 EXPECT_EQ(1, name_hashes.size());
320 ASSERT_EQ(1, items.size());
321 EXPECT_EQ(0, items[0].name_hash_index());
322 EXPECT_FALSE(items[0].has_key());
323 EXPECT_FALSE(items[0].has_value());
326 TEST(CallStackProfileMetadataTest, MetadataRecorder_RemovedKeyedItem) {
327 base::MetadataRecorder metadata_recorder;
328 CallStackProfileMetadata metadata;
329 google::protobuf::RepeatedField<uint64_t> name_hashes;
331 metadata_recorder.Set(100, 50, absl::nullopt, 10);
332 metadata.RecordMetadata(base::MetadataRecorder::MetadataProvider(
333 &metadata_recorder, base::PlatformThread::CurrentId()));
334 std::ignore = metadata.CreateSampleMetadata(&name_hashes);
336 metadata_recorder.Remove(100, 50, absl::nullopt);
337 metadata.RecordMetadata(base::MetadataRecorder::MetadataProvider(
338 &metadata_recorder, base::PlatformThread::CurrentId()));
339 google::protobuf::RepeatedPtrField<CallStackProfile::MetadataItem> items =
340 metadata.CreateSampleMetadata(&name_hashes);
342 EXPECT_EQ(1, name_hashes.size());
344 ASSERT_EQ(1, items.size());
345 EXPECT_EQ(0, items[0].name_hash_index());
346 EXPECT_TRUE(items[0].has_key());
347 EXPECT_EQ(50, items[0].key());
348 EXPECT_FALSE(items[0].has_value());
351 TEST(CallStackProfileMetadataTest, MetadataRecorder_RemovedThreadItem) {
352 base::MetadataRecorder metadata_recorder;
353 CallStackProfileMetadata metadata;
354 google::protobuf::RepeatedField<uint64_t> name_hashes;
356 metadata_recorder.Set(100, absl::nullopt, base::PlatformThread::CurrentId(),
358 metadata.RecordMetadata(base::MetadataRecorder::MetadataProvider(
359 &metadata_recorder, base::PlatformThread::CurrentId()));
360 (void)metadata.CreateSampleMetadata(&name_hashes);
362 metadata_recorder.Remove(100, absl::nullopt,
363 base::PlatformThread::CurrentId());
364 metadata.RecordMetadata(base::MetadataRecorder::MetadataProvider(
365 &metadata_recorder, base::PlatformThread::CurrentId()));
366 google::protobuf::RepeatedPtrField<CallStackProfile::MetadataItem> items =
367 metadata.CreateSampleMetadata(&name_hashes);
369 EXPECT_EQ(1, name_hashes.size());
371 ASSERT_EQ(1, items.size());
372 EXPECT_EQ(0, items[0].name_hash_index());
373 EXPECT_FALSE(items[0].has_key());
374 EXPECT_FALSE(items[0].has_value());
377 TEST(CallStackProfileMetadataTest,
378 MetadataRecorder_SetMixedUnkeyedAndKeyedItems) {
379 base::MetadataRecorder metadata_recorder;
380 CallStackProfileMetadata metadata;
381 google::protobuf::RepeatedField<uint64_t> name_hashes;
383 metadata_recorder.Set(100, absl::nullopt, absl::nullopt, 20);
384 metadata_recorder.Set(100, 50, absl::nullopt, 10);
385 metadata.RecordMetadata(base::MetadataRecorder::MetadataProvider(
386 &metadata_recorder, base::PlatformThread::CurrentId()));
387 google::protobuf::RepeatedPtrField<CallStackProfile::MetadataItem> items =
388 metadata.CreateSampleMetadata(&name_hashes);
390 ASSERT_EQ(2, items.size());
392 EXPECT_EQ(0, items[0].name_hash_index());
393 EXPECT_FALSE(items[0].has_key());
394 EXPECT_EQ(20, items[0].value());
396 EXPECT_EQ(0, items[1].name_hash_index());
397 EXPECT_TRUE(items[1].has_key());
398 EXPECT_EQ(50, items[1].key());
399 EXPECT_EQ(10, items[1].value());
402 TEST(CallStackProfileMetadataTest,
403 MetadataRecorder_RemoveMixedUnkeyedAndKeyedItems) {
404 base::MetadataRecorder metadata_recorder;
405 CallStackProfileMetadata metadata;
406 google::protobuf::RepeatedField<uint64_t> name_hashes;
408 metadata_recorder.Set(100, absl::nullopt, absl::nullopt, 20);
409 metadata_recorder.Set(100, 50, absl::nullopt, 10);
410 metadata.RecordMetadata(base::MetadataRecorder::MetadataProvider(
411 &metadata_recorder, base::PlatformThread::CurrentId()));
412 std::ignore = metadata.CreateSampleMetadata(&name_hashes);
414 metadata_recorder.Remove(100, absl::nullopt, absl::nullopt);
415 metadata.RecordMetadata(base::MetadataRecorder::MetadataProvider(
416 &metadata_recorder, base::PlatformThread::CurrentId()));
417 google::protobuf::RepeatedPtrField<CallStackProfile::MetadataItem> items =
418 metadata.CreateSampleMetadata(&name_hashes);
420 ASSERT_EQ(1, items.size());
421 EXPECT_EQ(0, items[0].name_hash_index());
422 EXPECT_FALSE(items[0].has_key());
423 EXPECT_FALSE(items[0].has_value());
426 // Checks that applying metadata results in the expected application and removal
428 TEST(CallStackProfileMetadataTest, ApplyMetadata_Basic) {
429 CallStackProfileMetadata metadata;
430 google::protobuf::RepeatedPtrField<CallStackProfile::StackSample>
432 google::protobuf::RepeatedField<uint64_t> name_hashes;
434 for (int i = 0; i < 5; i++)
437 const base::MetadataRecorder::Item item(3, 30, absl::nullopt, 300);
438 metadata.ApplyMetadata(item, stack_samples.begin() + 1,
439 stack_samples.begin() + 4, &stack_samples,
442 ASSERT_EQ(1, name_hashes.size());
443 EXPECT_EQ(3u, name_hashes[0]);
445 EXPECT_EQ(0, stack_samples[0].metadata_size());
447 // One metadata item should be recorded when the metadata starts.
448 EXPECT_EQ(1, stack_samples[1].metadata_size());
449 ExpectMetadataApplied(item, stack_samples, 1, 0, name_hashes);
451 EXPECT_EQ(0, stack_samples[2].metadata_size());
452 EXPECT_EQ(0, stack_samples[3].metadata_size());
454 // And one item should be recorded without value after the metadata ends.
455 EXPECT_EQ(1, stack_samples[4].metadata_size());
456 ExpectMetadataUnapplied(item, stack_samples, 4, 0, name_hashes);
459 // Checks that metadata items with different name hashes are applied
461 TEST(CallStackProfileMetadataTest, ApplyMetadata_DifferentNameHashes) {
462 CallStackProfileMetadata metadata;
463 google::protobuf::RepeatedPtrField<CallStackProfile::StackSample>
465 google::protobuf::RepeatedField<uint64_t> name_hashes;
467 for (int i = 0; i < 5; i++)
470 const base::MetadataRecorder::Item item1(3, 30, absl::nullopt, 300);
471 const base::MetadataRecorder::Item item2(4, 30, absl::nullopt, 300);
472 metadata.ApplyMetadata(item1, stack_samples.begin() + 1,
473 stack_samples.begin() + 4, &stack_samples,
475 metadata.ApplyMetadata(item2, stack_samples.begin() + 1,
476 stack_samples.begin() + 4, &stack_samples,
479 ASSERT_EQ(2, name_hashes.size());
480 EXPECT_EQ(3u, name_hashes[0]);
481 EXPECT_EQ(4u, name_hashes[1]);
483 EXPECT_EQ(0, stack_samples[0].metadata_size());
485 EXPECT_EQ(2, stack_samples[1].metadata_size());
486 ExpectMetadataApplied(item1, stack_samples, 1, 0, name_hashes);
487 ExpectMetadataApplied(item2, stack_samples, 1, 1, name_hashes);
489 EXPECT_EQ(0, stack_samples[2].metadata_size());
490 EXPECT_EQ(0, stack_samples[3].metadata_size());
492 EXPECT_EQ(2, stack_samples[4].metadata_size());
493 ExpectMetadataUnapplied(item1, stack_samples, 4, 0, name_hashes);
494 ExpectMetadataUnapplied(item2, stack_samples, 4, 1, name_hashes);
497 // Checks that metadata items with different keys are applied independently.
498 TEST(CallStackProfileMetadataTest, ApplyMetadata_DifferentKeys) {
499 CallStackProfileMetadata metadata;
500 google::protobuf::RepeatedPtrField<CallStackProfile::StackSample>
502 google::protobuf::RepeatedField<uint64_t> name_hashes;
504 for (int i = 0; i < 5; i++)
507 const base::MetadataRecorder::Item item1(3, 30, absl::nullopt, 300);
508 const base::MetadataRecorder::Item item2(3, 40, absl::nullopt, 300);
509 const base::MetadataRecorder::Item item3(3, absl::nullopt, absl::nullopt,
511 metadata.ApplyMetadata(item1, stack_samples.begin() + 1,
512 stack_samples.begin() + 4, &stack_samples,
514 metadata.ApplyMetadata(item2, stack_samples.begin() + 1,
515 stack_samples.begin() + 4, &stack_samples,
517 metadata.ApplyMetadata(item3, stack_samples.begin() + 1,
518 stack_samples.begin() + 4, &stack_samples,
521 ASSERT_EQ(1, name_hashes.size());
522 EXPECT_EQ(3u, name_hashes[0]);
524 EXPECT_EQ(0, stack_samples[0].metadata_size());
526 EXPECT_EQ(3, stack_samples[1].metadata_size());
527 ExpectMetadataApplied(item1, stack_samples, 1, 0, name_hashes);
528 ExpectMetadataApplied(item2, stack_samples, 1, 1, name_hashes);
529 ExpectMetadataApplied(item3, stack_samples, 1, 2, name_hashes);
531 EXPECT_EQ(0, stack_samples[2].metadata_size());
532 EXPECT_EQ(0, stack_samples[3].metadata_size());
534 EXPECT_EQ(3, stack_samples[4].metadata_size());
535 ExpectMetadataUnapplied(item1, stack_samples, 4, 0, name_hashes);
536 ExpectMetadataUnapplied(item2, stack_samples, 4, 1, name_hashes);
537 ExpectMetadataUnapplied(item3, stack_samples, 4, 2, name_hashes);
540 // Checks that applying to an empty range has no effect.
541 TEST(CallStackProfileMetadataTest, ApplyMetadata_EmptyRange) {
542 CallStackProfileMetadata metadata;
543 google::protobuf::RepeatedPtrField<CallStackProfile::StackSample>
545 google::protobuf::RepeatedField<uint64_t> name_hashes;
547 for (int i = 0; i < 5; i++)
550 const base::MetadataRecorder::Item item(3, 30, absl::nullopt, 300);
551 metadata.ApplyMetadata(item, stack_samples.begin() + 1,
552 stack_samples.begin() + 1, &stack_samples,
555 EXPECT_EQ(0, name_hashes.size());
557 for (int i = 0; i < 5; i++)
558 EXPECT_EQ(0, stack_samples[i].metadata_size());
561 // Checks that applying metadata through the end is recorded as unapplied on the
562 // next sample taken.
563 TEST(CallStackProfileMetadataTest, ApplyMetadata_ThroughEnd) {
564 CallStackProfileMetadata metadata;
565 google::protobuf::RepeatedPtrField<CallStackProfile::StackSample>
567 google::protobuf::RepeatedField<uint64_t> name_hashes;
569 for (int i = 0; i < 5; i++)
572 const base::MetadataRecorder::Item item(3, 30, absl::nullopt, 300);
573 metadata.ApplyMetadata(item, stack_samples.begin() + 1, stack_samples.end(),
574 &stack_samples, &name_hashes);
576 ASSERT_EQ(1, name_hashes.size());
577 EXPECT_EQ(3u, name_hashes[0]);
579 EXPECT_EQ(0, stack_samples[0].metadata_size());
581 // One metadata item should be recorded when the metadata starts.
582 EXPECT_EQ(1, stack_samples[1].metadata_size());
583 ExpectMetadataApplied(item, stack_samples, 1, 0, name_hashes);
585 EXPECT_EQ(0, stack_samples[2].metadata_size());
586 EXPECT_EQ(0, stack_samples[3].metadata_size());
587 EXPECT_EQ(0, stack_samples[4].metadata_size());
589 base::MetadataRecorder metadata_recorder;
590 metadata.RecordMetadata(base::MetadataRecorder::MetadataProvider(
591 &metadata_recorder, base::PlatformThread::CurrentId()));
592 *stack_samples.Add()->mutable_metadata() =
593 metadata.CreateSampleMetadata(&name_hashes);
595 // And the following sample should have the metadata unapplied.
596 ExpectMetadataUnapplied(item, stack_samples, 5, 0, name_hashes);
599 // Checks that metadata is properly applied when mixing RecordMetadata and
600 // ApplyMetadata over the same samples.
601 TEST(CallStackProfileMetadataTest, ApplyMetadata_WithRecordMetadata) {
602 base::MetadataRecorder metadata_recorder;
603 CallStackProfileMetadata metadata;
604 google::protobuf::RepeatedPtrField<CallStackProfile::StackSample>
606 google::protobuf::RepeatedField<uint64_t> name_hashes;
608 const base::MetadataRecorder::Item item1(3, 30, absl::nullopt, 300);
609 const base::MetadataRecorder::Item item2(5, 50, absl::nullopt, 500);
613 // Apply then remove item1.
614 metadata_recorder.Set(item1.name_hash, *item1.key, item1.thread_id,
616 metadata.RecordMetadata(base::MetadataRecorder::MetadataProvider(
617 &metadata_recorder, base::PlatformThread::CurrentId()));
618 *stack_samples.Add()->mutable_metadata() =
619 metadata.CreateSampleMetadata(&name_hashes);
621 metadata.RecordMetadata(base::MetadataRecorder::MetadataProvider(
622 &metadata_recorder, base::PlatformThread::CurrentId()));
623 *stack_samples.Add()->mutable_metadata() =
624 metadata.CreateSampleMetadata(&name_hashes);
626 metadata_recorder.Remove(item1.name_hash, *item1.key, item1.thread_id);
627 metadata.RecordMetadata(base::MetadataRecorder::MetadataProvider(
628 &metadata_recorder, base::PlatformThread::CurrentId()));
629 *stack_samples.Add()->mutable_metadata() =
630 metadata.CreateSampleMetadata(&name_hashes);
634 ASSERT_EQ(5, stack_samples.size());
637 metadata.ApplyMetadata(item2, stack_samples.begin() + 1,
638 stack_samples.begin() + 4, &stack_samples,
641 ASSERT_EQ(2, name_hashes.size());
642 EXPECT_EQ(3u, name_hashes[0]);
643 EXPECT_EQ(5u, name_hashes[1]);
645 EXPECT_EQ(0, stack_samples[0].metadata_size());
647 // Each of the two items should be recorded when their metadata starts.
648 ASSERT_EQ(2, stack_samples[1].metadata_size());
649 ExpectMetadataApplied(item1, stack_samples, 1, 0, name_hashes);
650 ExpectMetadataApplied(item2, stack_samples, 1, 1, name_hashes);
652 EXPECT_EQ(0, stack_samples[2].metadata_size());
654 // The original item should still be present.
655 EXPECT_EQ(1, stack_samples[3].metadata_size());
656 ExpectMetadataUnapplied(item1, stack_samples, 3, 0, name_hashes);
658 // And one item should be recorded without value after the metadata ends.
659 EXPECT_EQ(1, stack_samples[4].metadata_size());
660 ExpectMetadataUnapplied(item2, stack_samples, 4, 0, name_hashes);
663 // Checks that metadata is properly applied when using ApplyMetadata while
664 // a RecordMetadata-applied value is active.
665 TEST(CallStackProfileMetadataTest, ApplyMetadata_WithActiveMetadata) {
666 base::MetadataRecorder metadata_recorder;
667 CallStackProfileMetadata metadata;
668 google::protobuf::RepeatedPtrField<CallStackProfile::StackSample>
670 google::protobuf::RepeatedField<uint64_t> name_hashes;
672 const base::MetadataRecorder::Item item1(3, 30, absl::nullopt, 300);
673 const base::MetadataRecorder::Item item2(3, 30, absl::nullopt, 400);
675 metadata.RecordMetadata(base::MetadataRecorder::MetadataProvider(
676 &metadata_recorder, base::PlatformThread::CurrentId()));
677 *stack_samples.Add()->mutable_metadata() =
678 metadata.CreateSampleMetadata(&name_hashes);
680 // Record item1 on an ongoing basis via RecordMetadata.
681 metadata_recorder.Set(item1.name_hash, *item1.key, item1.thread_id,
683 metadata.RecordMetadata(base::MetadataRecorder::MetadataProvider(
684 &metadata_recorder, base::PlatformThread::CurrentId()));
685 *stack_samples.Add()->mutable_metadata() =
686 metadata.CreateSampleMetadata(&name_hashes);
688 metadata.RecordMetadata(base::MetadataRecorder::MetadataProvider(
689 &metadata_recorder, base::PlatformThread::CurrentId()));
690 *stack_samples.Add()->mutable_metadata() =
691 metadata.CreateSampleMetadata(&name_hashes);
693 ASSERT_EQ(3, stack_samples.size());
695 // Apply item2 via ApplyMetadata up to the last sample.
696 metadata.ApplyMetadata(item2, stack_samples.begin(), stack_samples.end(),
697 &stack_samples, &name_hashes);
699 ASSERT_EQ(1, name_hashes.size());
700 EXPECT_EQ(3u, name_hashes[0]);
702 EXPECT_EQ(1, stack_samples[0].metadata_size());
703 ExpectMetadataApplied(item2, stack_samples, 0, 0, name_hashes);
705 EXPECT_EQ(0, stack_samples[1].metadata_size());
706 EXPECT_EQ(0, stack_samples[2].metadata_size());
708 // The next recorded sample should have item1 applied since it's still active.
709 metadata.RecordMetadata(base::MetadataRecorder::MetadataProvider(
710 &metadata_recorder, base::PlatformThread::CurrentId()));
711 *stack_samples.Add()->mutable_metadata() =
712 metadata.CreateSampleMetadata(&name_hashes);
714 EXPECT_EQ(1, stack_samples[3].metadata_size());
715 ExpectMetadataApplied(item1, stack_samples, 3, 0, name_hashes);
718 // Checks application of the same item across non-overlapping ranges.
719 TEST(CallStackProfileMetadataTest, ApplyMetadata_IndependentRanges) {
720 CallStackProfileMetadata metadata;
721 google::protobuf::RepeatedPtrField<CallStackProfile::StackSample>
723 google::protobuf::RepeatedField<uint64_t> name_hashes;
725 for (int i = 0; i < 5; i++)
728 const base::MetadataRecorder::Item item(3, 30, absl::nullopt, 300);
730 // Apply metadata over two non-overlapping ranges.
731 metadata.ApplyMetadata(item, stack_samples.begin(), stack_samples.begin() + 2,
732 &stack_samples, &name_hashes);
734 metadata.ApplyMetadata(item, stack_samples.begin() + 3,
735 stack_samples.begin() + 4, &stack_samples,
738 ASSERT_EQ(1, name_hashes.size());
739 EXPECT_EQ(3u, name_hashes[0]);
741 EXPECT_EQ(1, stack_samples[0].metadata_size());
742 ExpectMetadataApplied(item, stack_samples, 0, 0, name_hashes);
744 EXPECT_EQ(0, stack_samples[1].metadata_size());
746 EXPECT_EQ(1, stack_samples[2].metadata_size());
747 ExpectMetadataUnapplied(item, stack_samples, 2, 0, name_hashes);
749 EXPECT_EQ(1, stack_samples[3].metadata_size());
750 ExpectMetadataApplied(item, stack_samples, 3, 0, name_hashes);
752 EXPECT_EQ(1, stack_samples[4].metadata_size());
753 ExpectMetadataUnapplied(item, stack_samples, 4, 0, name_hashes);
756 // Checks application of the same item across back-to-back ranges. The common
757 // sample should not have a metadata item set because it's unnecessary.
758 TEST(CallStackProfileMetadataTest, ApplyMetadata_BackToBackRanges) {
759 CallStackProfileMetadata metadata;
760 google::protobuf::RepeatedPtrField<CallStackProfile::StackSample>
762 google::protobuf::RepeatedField<uint64_t> name_hashes;
764 for (int i = 0; i < 5; i++)
767 const base::MetadataRecorder::Item item(3, 30, absl::nullopt, 300);
769 // Apply metadata over two ranges where the second starts on the same sample
770 // that the first ends. This should result in one range covering both.
771 metadata.ApplyMetadata(item, stack_samples.begin(), stack_samples.begin() + 2,
772 &stack_samples, &name_hashes);
774 metadata.ApplyMetadata(item, stack_samples.begin() + 2,
775 stack_samples.begin() + 4, &stack_samples,
778 ASSERT_EQ(1, name_hashes.size());
779 EXPECT_EQ(3u, name_hashes[0]);
781 EXPECT_EQ(1, stack_samples[0].metadata_size());
782 ExpectMetadataApplied(item, stack_samples, 0, 0, name_hashes);
784 EXPECT_EQ(0, stack_samples[1].metadata_size());
785 EXPECT_EQ(0, stack_samples[2].metadata_size());
786 EXPECT_EQ(0, stack_samples[3].metadata_size());
788 EXPECT_EQ(1, stack_samples[4].metadata_size());
789 ExpectMetadataUnapplied(item, stack_samples, 4, 0, name_hashes);
792 // Checks application of different values across back-to-back ranges. The common
793 // sample must have the second metadata value set.
794 TEST(CallStackProfileMetadataTest,
795 ApplyMetadata_BackToBackRangesWithDifferentValues) {
796 CallStackProfileMetadata metadata;
797 google::protobuf::RepeatedPtrField<CallStackProfile::StackSample>
799 google::protobuf::RepeatedField<uint64_t> name_hashes;
801 for (int i = 0; i < 5; i++)
804 const base::MetadataRecorder::Item item1(3, 30, absl::nullopt, 300);
805 const base::MetadataRecorder::Item item2(3, 30, absl::nullopt, 400);
807 metadata.ApplyMetadata(item1, stack_samples.begin(),
808 stack_samples.begin() + 2, &stack_samples,
811 metadata.ApplyMetadata(item2, stack_samples.begin() + 2,
812 stack_samples.begin() + 4, &stack_samples,
815 ASSERT_EQ(1, name_hashes.size());
816 EXPECT_EQ(3u, name_hashes[0]);
818 EXPECT_EQ(1, stack_samples[0].metadata_size());
819 ExpectMetadataApplied(item1, stack_samples, 0, 0, name_hashes);
821 EXPECT_EQ(0, stack_samples[1].metadata_size());
823 EXPECT_EQ(1, stack_samples[2].metadata_size());
824 ExpectMetadataApplied(item2, stack_samples, 2, 0, name_hashes);
826 EXPECT_EQ(0, stack_samples[3].metadata_size());
828 EXPECT_EQ(1, stack_samples[4].metadata_size());
829 ExpectMetadataUnapplied(item2, stack_samples, 4, 0, name_hashes);
832 // Checks application of the same item over a range within a range where the
833 // item was already set. No metadata changes should be recorded on the interior
834 // range because they are unnecessary.
835 TEST(CallStackProfileMetadataTest, ApplyMetadata_UpdateWithinExistingRange) {
836 CallStackProfileMetadata metadata;
837 google::protobuf::RepeatedPtrField<CallStackProfile::StackSample>
839 google::protobuf::RepeatedField<uint64_t> name_hashes;
841 for (int i = 0; i < 5; i++)
844 const base::MetadataRecorder::Item item(3, 30, absl::nullopt, 300);
846 metadata.ApplyMetadata(item, stack_samples.begin(), stack_samples.begin() + 4,
847 &stack_samples, &name_hashes);
849 metadata.ApplyMetadata(item, stack_samples.begin() + 1,
850 stack_samples.begin() + 3, &stack_samples,
853 ASSERT_EQ(1, name_hashes.size());
854 EXPECT_EQ(3u, name_hashes[0]);
856 EXPECT_EQ(1, stack_samples[0].metadata_size());
857 ExpectMetadataApplied(item, stack_samples, 0, 0, name_hashes);
859 EXPECT_EQ(0, stack_samples[1].metadata_size());
860 EXPECT_EQ(0, stack_samples[2].metadata_size());
861 EXPECT_EQ(0, stack_samples[3].metadata_size());
863 EXPECT_EQ(1, stack_samples[4].metadata_size());
864 ExpectMetadataUnapplied(item, stack_samples, 4, 0, name_hashes);
867 // Checks application of a second value over a range within a range where the
868 // first value was already set. Metadata changes for the second value must be
869 // recorded on the interior range.
870 TEST(CallStackProfileMetadataTest,
871 ApplyMetadata_UpdateWithinExistingRangeWithDifferentValues) {
872 CallStackProfileMetadata metadata;
873 google::protobuf::RepeatedPtrField<CallStackProfile::StackSample>
875 google::protobuf::RepeatedField<uint64_t> name_hashes;
877 for (int i = 0; i < 5; i++)
880 const base::MetadataRecorder::Item item1(3, 30, absl::nullopt, 300);
881 const base::MetadataRecorder::Item item2(3, 30, absl::nullopt, 400);
883 // Apply metadata over a range, then over a range fully enclosed within the
885 metadata.ApplyMetadata(item1, stack_samples.begin(),
886 stack_samples.begin() + 4, &stack_samples,
889 metadata.ApplyMetadata(item2, stack_samples.begin() + 1,
890 stack_samples.begin() + 3, &stack_samples,
893 ASSERT_EQ(1, name_hashes.size());
894 EXPECT_EQ(3u, name_hashes[0]);
896 EXPECT_EQ(1, stack_samples[0].metadata_size());
897 ExpectMetadataApplied(item1, stack_samples, 0, 0, name_hashes);
899 EXPECT_EQ(1, stack_samples[1].metadata_size());
900 ExpectMetadataApplied(item2, stack_samples, 1, 0, name_hashes);
902 EXPECT_EQ(0, stack_samples[2].metadata_size());
904 EXPECT_EQ(1, stack_samples[3].metadata_size());
905 ExpectMetadataApplied(item1, stack_samples, 3, 0, name_hashes);
907 EXPECT_EQ(1, stack_samples[4].metadata_size());
908 ExpectMetadataUnapplied(item1, stack_samples, 4, 0, name_hashes);
911 // Checks application of the same item over a range enclosing a range where the
912 // item was already set. No metadata changes should be recorded on the interior
913 // range because they are unnecessary.
914 TEST(CallStackProfileMetadataTest, ApplyMetadata_UpdateEnclosesExistingRange) {
915 CallStackProfileMetadata metadata;
916 google::protobuf::RepeatedPtrField<CallStackProfile::StackSample>
918 google::protobuf::RepeatedField<uint64_t> name_hashes;
920 for (int i = 0; i < 5; i++)
923 const base::MetadataRecorder::Item item(3, 30, absl::nullopt, 300);
925 // Apply metadata over a range, then over a range that fully encloses the
927 metadata.ApplyMetadata(item, stack_samples.begin() + 1,
928 stack_samples.begin() + 3, &stack_samples,
931 metadata.ApplyMetadata(item, stack_samples.begin(), stack_samples.begin() + 4,
932 &stack_samples, &name_hashes);
934 ASSERT_EQ(1, name_hashes.size());
935 EXPECT_EQ(3u, name_hashes[0]);
937 EXPECT_EQ(1, stack_samples[0].metadata_size());
938 ExpectMetadataApplied(item, stack_samples, 0, 0, name_hashes);
940 EXPECT_EQ(0, stack_samples[1].metadata_size());
941 EXPECT_EQ(0, stack_samples[2].metadata_size());
942 EXPECT_EQ(0, stack_samples[3].metadata_size());
944 EXPECT_EQ(1, stack_samples[4].metadata_size());
945 ExpectMetadataUnapplied(item, stack_samples, 4, 0, name_hashes);
948 // Checks application of a second value over a range enclosing a range where the
949 // first value was already set. Metadata changes for both values must be
951 TEST(CallStackProfileMetadataTest,
952 ApplyMetadata_UpdateEnclosesExistingRangeWithDifferentValues) {
953 CallStackProfileMetadata metadata;
954 google::protobuf::RepeatedPtrField<CallStackProfile::StackSample>
956 google::protobuf::RepeatedField<uint64_t> name_hashes;
958 for (int i = 0; i < 5; i++)
961 const base::MetadataRecorder::Item item1(3, 30, absl::nullopt, 300);
962 const base::MetadataRecorder::Item item2(3, 30, absl::nullopt, 400);
964 // Apply metadata over a range, then over a range that fully encloses the
966 metadata.ApplyMetadata(item1, stack_samples.begin() + 1,
967 stack_samples.begin() + 3, &stack_samples,
970 metadata.ApplyMetadata(item2, stack_samples.begin(),
971 stack_samples.begin() + 4, &stack_samples,
974 ASSERT_EQ(1, name_hashes.size());
975 EXPECT_EQ(3u, name_hashes[0]);
977 EXPECT_EQ(1, stack_samples[0].metadata_size());
978 ExpectMetadataApplied(item2, stack_samples, 0, 0, name_hashes);
980 EXPECT_EQ(0, stack_samples[1].metadata_size());
981 EXPECT_EQ(0, stack_samples[2].metadata_size());
982 EXPECT_EQ(0, stack_samples[3].metadata_size());
984 EXPECT_EQ(1, stack_samples[4].metadata_size());
985 ExpectMetadataUnapplied(item2, stack_samples, 4, 0, name_hashes);
988 // Checks application of an item over a range overlapping the start (but not
989 // end) of a range where the item was already set. No metadata changes should be
990 // recorded on the interior application because it is unnecessary.
991 TEST(CallStackProfileMetadataTest, ApplyMetadata_UpdateOverlapsBegin) {
992 CallStackProfileMetadata metadata;
993 google::protobuf::RepeatedPtrField<CallStackProfile::StackSample>
995 google::protobuf::RepeatedField<uint64_t> name_hashes;
997 for (int i = 0; i < 5; i++)
1000 const base::MetadataRecorder::Item item(3, 30, absl::nullopt, 300);
1002 // Apply metadata over a range, then over a range that overlaps the beginning
1003 // (but not the end) of first one.
1004 metadata.ApplyMetadata(item, stack_samples.begin() + 1,
1005 stack_samples.begin() + 3, &stack_samples,
1008 metadata.ApplyMetadata(item, stack_samples.begin(), stack_samples.begin() + 2,
1009 &stack_samples, &name_hashes);
1011 ASSERT_EQ(1, name_hashes.size());
1012 EXPECT_EQ(3u, name_hashes[0]);
1014 EXPECT_EQ(1, stack_samples[0].metadata_size());
1015 ExpectMetadataApplied(item, stack_samples, 0, 0, name_hashes);
1017 EXPECT_EQ(0, stack_samples[1].metadata_size());
1018 EXPECT_EQ(0, stack_samples[2].metadata_size());
1020 EXPECT_EQ(1, stack_samples[3].metadata_size());
1021 ExpectMetadataUnapplied(item, stack_samples, 3, 0, name_hashes);
1023 EXPECT_EQ(0, stack_samples[4].metadata_size());
1026 // Checks application of a second different value over a range overlapping the
1027 // start (but not end) of a range where the first value was already
1028 // set. Metadata changes must be recorded on the interior application.
1029 TEST(CallStackProfileMetadataTest,
1030 ApplyMetadata_UpdateOverlapsBeginWithDifferentValues) {
1031 CallStackProfileMetadata metadata;
1032 google::protobuf::RepeatedPtrField<CallStackProfile::StackSample>
1034 google::protobuf::RepeatedField<uint64_t> name_hashes;
1036 for (int i = 0; i < 5; i++)
1037 stack_samples.Add();
1039 const base::MetadataRecorder::Item item1(3, 30, absl::nullopt, 300);
1040 const base::MetadataRecorder::Item item2(3, 30, absl::nullopt, 400);
1042 // Apply metadata over a range, then over a range that overlaps the beginning
1043 // (but not the end) of first one.
1044 metadata.ApplyMetadata(item1, stack_samples.begin() + 1,
1045 stack_samples.begin() + 3, &stack_samples,
1048 metadata.ApplyMetadata(item2, stack_samples.begin(),
1049 stack_samples.begin() + 2, &stack_samples,
1052 ASSERT_EQ(1, name_hashes.size());
1053 EXPECT_EQ(3u, name_hashes[0]);
1055 EXPECT_EQ(1, stack_samples[0].metadata_size());
1056 ExpectMetadataApplied(item2, stack_samples, 0, 0, name_hashes);
1058 EXPECT_EQ(0, stack_samples[1].metadata_size());
1059 EXPECT_EQ(1, stack_samples[2].metadata_size());
1060 ExpectMetadataApplied(item1, stack_samples, 2, 0, name_hashes);
1062 EXPECT_EQ(1, stack_samples[3].metadata_size());
1063 ExpectMetadataUnapplied(item1, stack_samples, 3, 0, name_hashes);
1065 EXPECT_EQ(0, stack_samples[4].metadata_size());
1068 // Checks application of an item over a range overlapping the end (but not
1069 // start) of a range where the item was already set. No metadata changes should
1070 // be recorded on the interior application because it is unnecessary.
1071 TEST(CallStackProfileMetadataTest, ApplyMetadata_UpdateOverlapsEnd) {
1072 CallStackProfileMetadata metadata;
1073 google::protobuf::RepeatedPtrField<CallStackProfile::StackSample>
1075 google::protobuf::RepeatedField<uint64_t> name_hashes;
1077 for (int i = 0; i < 5; i++)
1078 stack_samples.Add();
1080 const base::MetadataRecorder::Item item(3, 30, absl::nullopt, 300);
1082 // Apply metadata over a range, then over a range that overlaps the beginning
1083 // (but not the end) of first one.
1084 metadata.ApplyMetadata(item, stack_samples.begin(), stack_samples.begin() + 2,
1085 &stack_samples, &name_hashes);
1087 metadata.ApplyMetadata(item, stack_samples.begin() + 1,
1088 stack_samples.begin() + 4, &stack_samples,
1091 ASSERT_EQ(1, name_hashes.size());
1092 EXPECT_EQ(3u, name_hashes[0]);
1094 EXPECT_EQ(1, stack_samples[0].metadata_size());
1095 ExpectMetadataApplied(item, stack_samples, 0, 0, name_hashes);
1097 EXPECT_EQ(0, stack_samples[1].metadata_size());
1098 EXPECT_EQ(0, stack_samples[2].metadata_size());
1099 EXPECT_EQ(0, stack_samples[3].metadata_size());
1101 EXPECT_EQ(1, stack_samples[4].metadata_size());
1102 ExpectMetadataUnapplied(item, stack_samples, 4, 0, name_hashes);
1105 // Checks application of a second different value over a range overlapping the
1106 // end (but not start) of a range where the first value was already
1107 // set. Metadata changes must be recorded on the interior application.
1108 TEST(CallStackProfileMetadataTest,
1109 ApplyMetadata_UpdateOverlapsEndWithDifferentValues) {
1110 CallStackProfileMetadata metadata;
1111 google::protobuf::RepeatedPtrField<CallStackProfile::StackSample>
1113 google::protobuf::RepeatedField<uint64_t> name_hashes;
1115 for (int i = 0; i < 5; i++)
1116 stack_samples.Add();
1118 const base::MetadataRecorder::Item item1(3, 30, absl::nullopt, 300);
1119 const base::MetadataRecorder::Item item2(3, 30, absl::nullopt, 400);
1121 // Apply metadata over a range, then over a range that overlaps the beginning
1122 // (but not the end) of first one.
1123 metadata.ApplyMetadata(item1, stack_samples.begin(),
1124 stack_samples.begin() + 2, &stack_samples,
1127 metadata.ApplyMetadata(item2, stack_samples.begin() + 1,
1128 stack_samples.begin() + 4, &stack_samples,
1131 ASSERT_EQ(1, name_hashes.size());
1132 EXPECT_EQ(3u, name_hashes[0]);
1134 EXPECT_EQ(1, stack_samples[0].metadata_size());
1135 ExpectMetadataApplied(item1, stack_samples, 0, 0, name_hashes);
1137 EXPECT_EQ(1, stack_samples[1].metadata_size());
1138 ExpectMetadataApplied(item2, stack_samples, 1, 0, name_hashes);
1140 EXPECT_EQ(0, stack_samples[2].metadata_size());
1141 EXPECT_EQ(0, stack_samples[3].metadata_size());
1143 EXPECT_EQ(1, stack_samples[4].metadata_size());
1144 ExpectMetadataUnapplied(item2, stack_samples, 4, 0, name_hashes);
1147 // Checks that updating the same range multiple times with the same item
1148 // produces the same result as what we'd expect with just one update.
1149 TEST(CallStackProfileMetadataTest, ApplyMetadata_Update) {
1150 CallStackProfileMetadata metadata;
1151 google::protobuf::RepeatedPtrField<CallStackProfile::StackSample>
1153 google::protobuf::RepeatedField<uint64_t> name_hashes;
1155 for (int i = 0; i < 5; i++)
1156 stack_samples.Add();
1158 const base::MetadataRecorder::Item item(3, 30, absl::nullopt, 300);
1160 // Apply metadata over the same range with one value, then a different value.
1161 metadata.ApplyMetadata(item, stack_samples.begin() + 1,
1162 stack_samples.begin() + 4, &stack_samples,
1165 metadata.ApplyMetadata(item, stack_samples.begin() + 1,
1166 stack_samples.begin() + 4, &stack_samples,
1169 ASSERT_EQ(1, name_hashes.size());
1170 EXPECT_EQ(3u, name_hashes[0]);
1172 EXPECT_EQ(0, stack_samples[0].metadata_size());
1174 EXPECT_EQ(1, stack_samples[1].metadata_size());
1175 ExpectMetadataApplied(item, stack_samples, 1, 0, name_hashes);
1177 EXPECT_EQ(0, stack_samples[2].metadata_size());
1178 EXPECT_EQ(0, stack_samples[3].metadata_size());
1180 EXPECT_EQ(1, stack_samples[4].metadata_size());
1181 ExpectMetadataUnapplied(item, stack_samples, 4, 0, name_hashes);
1184 // Checks that applying to the same range with a different value overwrites the
1186 TEST(CallStackProfileMetadataTest, ApplyMetadata_UpdateWithDifferentValues) {
1187 CallStackProfileMetadata metadata;
1188 google::protobuf::RepeatedPtrField<CallStackProfile::StackSample>
1190 google::protobuf::RepeatedField<uint64_t> name_hashes;
1192 for (int i = 0; i < 5; i++)
1193 stack_samples.Add();
1195 const base::MetadataRecorder::Item item1(3, 30, absl::nullopt, 300);
1196 const base::MetadataRecorder::Item item2(3, 30, absl::nullopt, 400);
1198 // Apply metadata over the same range with one value, then a different value.
1199 metadata.ApplyMetadata(item1, stack_samples.begin() + 1,
1200 stack_samples.begin() + 4, &stack_samples,
1203 metadata.ApplyMetadata(item2, stack_samples.begin() + 1,
1204 stack_samples.begin() + 4, &stack_samples,
1207 ASSERT_EQ(1, name_hashes.size());
1208 EXPECT_EQ(3u, name_hashes[0]);
1210 EXPECT_EQ(0, stack_samples[0].metadata_size());
1212 EXPECT_EQ(1, stack_samples[1].metadata_size());
1213 ExpectMetadataApplied(item2, stack_samples, 1, 0, name_hashes);
1215 EXPECT_EQ(0, stack_samples[2].metadata_size());
1216 EXPECT_EQ(0, stack_samples[3].metadata_size());
1218 EXPECT_EQ(1, stack_samples[4].metadata_size());
1219 ExpectMetadataUnapplied(item2, stack_samples, 4, 0, name_hashes);
1222 } // namespace metrics