[M120 Migration][VD] Enable direct rendering for TVPlus
[platform/framework/web/chromium-efl.git] / components / metrics / call_stack_profile_metadata_unittest.cc
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.
4
5 #include "components/metrics/call_stack_profile_metadata.h"
6
7 #include <tuple>
8 #include <utility>
9
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"
15
16 namespace metrics {
17
18 namespace {
19
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>&
26         samples,
27     int sample_index,
28     int metadata_index,
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) -
35       name_hashes.begin();
36   ASSERT_NE(name_hash_index, name_hashes.size()) << index_info;
37
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;
43
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;
48 }
49
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>&
56         samples,
57     int sample_index,
58     int metadata_index,
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) -
65       name_hashes.begin();
66   ASSERT_NE(name_hash_index, name_hashes.size()) << index_info;
67
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;
73
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;
78 }
79
80 }  // namespace
81
82 TEST(CallStackProfileMetadataTest, MetadataRecorder_NoItems) {
83   base::MetadataRecorder metadata_recorder;
84   CallStackProfileMetadata metadata;
85   google::protobuf::RepeatedField<uint64_t> name_hashes;
86
87   metadata.RecordMetadata(base::MetadataRecorder::MetadataProvider(
88       &metadata_recorder, base::PlatformThread::CurrentId()));
89
90   google::protobuf::RepeatedPtrField<CallStackProfile::MetadataItem> items =
91       metadata.CreateSampleMetadata(&name_hashes);
92
93   ASSERT_EQ(0, name_hashes.size());
94   ASSERT_EQ(0, items.size());
95 }
96
97 TEST(CallStackProfileMetadataTest, MetadataRecorder_SetItem) {
98   base::MetadataRecorder metadata_recorder;
99   CallStackProfileMetadata metadata;
100   google::protobuf::RepeatedField<uint64_t> name_hashes;
101
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);
107
108   ASSERT_EQ(1, name_hashes.size());
109   EXPECT_EQ(100u, name_hashes[0]);
110
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());
115 }
116
117 TEST(CallStackProfileMetadataTest, MetadataRecorder_SetKeyedItem) {
118   base::MetadataRecorder metadata_recorder;
119   CallStackProfileMetadata metadata;
120   google::protobuf::RepeatedField<uint64_t> name_hashes;
121
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);
127
128   ASSERT_EQ(1, name_hashes.size());
129   EXPECT_EQ(100u, name_hashes[0]);
130
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());
136 }
137
138 TEST(CallStackProfileMetadataTest, MetadataRecorder_SetThreadItem) {
139   base::MetadataRecorder metadata_recorder;
140   CallStackProfileMetadata metadata;
141   google::protobuf::RepeatedField<uint64_t> name_hashes;
142
143   metadata_recorder.Set(100, absl::nullopt, base::PlatformThread::CurrentId(),
144                         10);
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);
150
151   ASSERT_EQ(1, name_hashes.size());
152   EXPECT_EQ(100u, name_hashes[0]);
153
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());
158 }
159
160 TEST(CallStackProfileMetadataTest, MetadataRecorder_RepeatItem) {
161   base::MetadataRecorder metadata_recorder;
162   CallStackProfileMetadata metadata;
163   google::protobuf::RepeatedField<uint64_t> name_hashes;
164
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);
169
170   metadata.RecordMetadata(base::MetadataRecorder::MetadataProvider(
171       &metadata_recorder, base::PlatformThread::CurrentId()));
172   google::protobuf::RepeatedPtrField<CallStackProfile::MetadataItem> items =
173       metadata.CreateSampleMetadata(&name_hashes);
174
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());
179 }
180
181 TEST(CallStackProfileMetadataTest, MetadataRecorder_RepeatKeyedItem) {
182   base::MetadataRecorder metadata_recorder;
183   CallStackProfileMetadata metadata;
184   google::protobuf::RepeatedField<uint64_t> name_hashes;
185
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);
190
191   metadata.RecordMetadata(base::MetadataRecorder::MetadataProvider(
192       &metadata_recorder, base::PlatformThread::CurrentId()));
193   google::protobuf::RepeatedPtrField<CallStackProfile::MetadataItem> items =
194       metadata.CreateSampleMetadata(&name_hashes);
195
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());
200 }
201
202 TEST(CallStackProfileMetadataTest, MetadataRecorder_ModifiedItem) {
203   base::MetadataRecorder metadata_recorder;
204   CallStackProfileMetadata metadata;
205   google::protobuf::RepeatedField<uint64_t> name_hashes;
206
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);
211
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);
217
218   EXPECT_EQ(1, name_hashes.size());
219
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());
224 }
225
226 TEST(CallStackProfileMetadataTest, MetadataRecorder_ModifiedKeyedItem) {
227   base::MetadataRecorder metadata_recorder;
228   CallStackProfileMetadata metadata;
229   google::protobuf::RepeatedField<uint64_t> name_hashes;
230
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);
235
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);
241
242   EXPECT_EQ(1, name_hashes.size());
243
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());
249 }
250
251 TEST(CallStackProfileMetadataTest, MetadataRecorder_NewItem) {
252   base::MetadataRecorder metadata_recorder;
253   CallStackProfileMetadata metadata;
254   google::protobuf::RepeatedField<uint64_t> name_hashes;
255
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);
260
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);
266
267   ASSERT_EQ(2, name_hashes.size());
268   EXPECT_EQ(101u, name_hashes[1]);
269
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());
274 }
275
276 TEST(CallStackProfileMetadataTest, MetadataRecorder_NewKeyedItem) {
277   base::MetadataRecorder metadata_recorder;
278   CallStackProfileMetadata metadata;
279   google::protobuf::RepeatedField<uint64_t> name_hashes;
280
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);
285
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);
291
292   ASSERT_EQ(2, name_hashes.size());
293   EXPECT_EQ(101u, name_hashes[1]);
294
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());
300 }
301
302 TEST(CallStackProfileMetadataTest, MetadataRecorder_RemovedItem) {
303   base::MetadataRecorder metadata_recorder;
304   CallStackProfileMetadata metadata;
305   google::protobuf::RepeatedField<uint64_t> name_hashes;
306
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);
311
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);
317
318   EXPECT_EQ(1, name_hashes.size());
319
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());
324 }
325
326 TEST(CallStackProfileMetadataTest, MetadataRecorder_RemovedKeyedItem) {
327   base::MetadataRecorder metadata_recorder;
328   CallStackProfileMetadata metadata;
329   google::protobuf::RepeatedField<uint64_t> name_hashes;
330
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);
335
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);
341
342   EXPECT_EQ(1, name_hashes.size());
343
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());
349 }
350
351 TEST(CallStackProfileMetadataTest, MetadataRecorder_RemovedThreadItem) {
352   base::MetadataRecorder metadata_recorder;
353   CallStackProfileMetadata metadata;
354   google::protobuf::RepeatedField<uint64_t> name_hashes;
355
356   metadata_recorder.Set(100, absl::nullopt, base::PlatformThread::CurrentId(),
357                         10);
358   metadata.RecordMetadata(base::MetadataRecorder::MetadataProvider(
359       &metadata_recorder, base::PlatformThread::CurrentId()));
360   (void)metadata.CreateSampleMetadata(&name_hashes);
361
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);
368
369   EXPECT_EQ(1, name_hashes.size());
370
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());
375 }
376
377 TEST(CallStackProfileMetadataTest,
378      MetadataRecorder_SetMixedUnkeyedAndKeyedItems) {
379   base::MetadataRecorder metadata_recorder;
380   CallStackProfileMetadata metadata;
381   google::protobuf::RepeatedField<uint64_t> name_hashes;
382
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);
389
390   ASSERT_EQ(2, items.size());
391
392   EXPECT_EQ(0, items[0].name_hash_index());
393   EXPECT_FALSE(items[0].has_key());
394   EXPECT_EQ(20, items[0].value());
395
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());
400 }
401
402 TEST(CallStackProfileMetadataTest,
403      MetadataRecorder_RemoveMixedUnkeyedAndKeyedItems) {
404   base::MetadataRecorder metadata_recorder;
405   CallStackProfileMetadata metadata;
406   google::protobuf::RepeatedField<uint64_t> name_hashes;
407
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);
413
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);
419
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());
424 }
425
426 // Checks that applying metadata results in the expected application and removal
427 // of the metadata.
428 TEST(CallStackProfileMetadataTest, ApplyMetadata_Basic) {
429   CallStackProfileMetadata metadata;
430   google::protobuf::RepeatedPtrField<CallStackProfile::StackSample>
431       stack_samples;
432   google::protobuf::RepeatedField<uint64_t> name_hashes;
433
434   for (int i = 0; i < 5; i++)
435     stack_samples.Add();
436
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,
440                          &name_hashes);
441
442   ASSERT_EQ(1, name_hashes.size());
443   EXPECT_EQ(3u, name_hashes[0]);
444
445   EXPECT_EQ(0, stack_samples[0].metadata_size());
446
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);
450
451   EXPECT_EQ(0, stack_samples[2].metadata_size());
452   EXPECT_EQ(0, stack_samples[3].metadata_size());
453
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);
457 }
458
459 // Checks that metadata items with different name hashes are applied
460 // independently.
461 TEST(CallStackProfileMetadataTest, ApplyMetadata_DifferentNameHashes) {
462   CallStackProfileMetadata metadata;
463   google::protobuf::RepeatedPtrField<CallStackProfile::StackSample>
464       stack_samples;
465   google::protobuf::RepeatedField<uint64_t> name_hashes;
466
467   for (int i = 0; i < 5; i++)
468     stack_samples.Add();
469
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,
474                          &name_hashes);
475   metadata.ApplyMetadata(item2, stack_samples.begin() + 1,
476                          stack_samples.begin() + 4, &stack_samples,
477                          &name_hashes);
478
479   ASSERT_EQ(2, name_hashes.size());
480   EXPECT_EQ(3u, name_hashes[0]);
481   EXPECT_EQ(4u, name_hashes[1]);
482
483   EXPECT_EQ(0, stack_samples[0].metadata_size());
484
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);
488
489   EXPECT_EQ(0, stack_samples[2].metadata_size());
490   EXPECT_EQ(0, stack_samples[3].metadata_size());
491
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);
495 }
496
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>
501       stack_samples;
502   google::protobuf::RepeatedField<uint64_t> name_hashes;
503
504   for (int i = 0; i < 5; i++)
505     stack_samples.Add();
506
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,
510                                            300);
511   metadata.ApplyMetadata(item1, stack_samples.begin() + 1,
512                          stack_samples.begin() + 4, &stack_samples,
513                          &name_hashes);
514   metadata.ApplyMetadata(item2, stack_samples.begin() + 1,
515                          stack_samples.begin() + 4, &stack_samples,
516                          &name_hashes);
517   metadata.ApplyMetadata(item3, stack_samples.begin() + 1,
518                          stack_samples.begin() + 4, &stack_samples,
519                          &name_hashes);
520
521   ASSERT_EQ(1, name_hashes.size());
522   EXPECT_EQ(3u, name_hashes[0]);
523
524   EXPECT_EQ(0, stack_samples[0].metadata_size());
525
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);
530
531   EXPECT_EQ(0, stack_samples[2].metadata_size());
532   EXPECT_EQ(0, stack_samples[3].metadata_size());
533
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);
538 }
539
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>
544       stack_samples;
545   google::protobuf::RepeatedField<uint64_t> name_hashes;
546
547   for (int i = 0; i < 5; i++)
548     stack_samples.Add();
549
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,
553                          &name_hashes);
554
555   EXPECT_EQ(0, name_hashes.size());
556
557   for (int i = 0; i < 5; i++)
558     EXPECT_EQ(0, stack_samples[i].metadata_size());
559 }
560
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>
566       stack_samples;
567   google::protobuf::RepeatedField<uint64_t> name_hashes;
568
569   for (int i = 0; i < 5; i++)
570     stack_samples.Add();
571
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);
575
576   ASSERT_EQ(1, name_hashes.size());
577   EXPECT_EQ(3u, name_hashes[0]);
578
579   EXPECT_EQ(0, stack_samples[0].metadata_size());
580
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);
584
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());
588
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);
594
595   // And the following sample should have the metadata unapplied.
596   ExpectMetadataUnapplied(item, stack_samples, 5, 0, name_hashes);
597 }
598
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>
605       stack_samples;
606   google::protobuf::RepeatedField<uint64_t> name_hashes;
607
608   const base::MetadataRecorder::Item item1(3, 30, absl::nullopt, 300);
609   const base::MetadataRecorder::Item item2(5, 50, absl::nullopt, 500);
610
611   stack_samples.Add();
612
613   // Apply then remove item1.
614   metadata_recorder.Set(item1.name_hash, *item1.key, item1.thread_id,
615                         item1.value);
616   metadata.RecordMetadata(base::MetadataRecorder::MetadataProvider(
617       &metadata_recorder, base::PlatformThread::CurrentId()));
618   *stack_samples.Add()->mutable_metadata() =
619       metadata.CreateSampleMetadata(&name_hashes);
620
621   metadata.RecordMetadata(base::MetadataRecorder::MetadataProvider(
622       &metadata_recorder, base::PlatformThread::CurrentId()));
623   *stack_samples.Add()->mutable_metadata() =
624       metadata.CreateSampleMetadata(&name_hashes);
625
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);
631
632   stack_samples.Add();
633
634   ASSERT_EQ(5, stack_samples.size());
635
636   // Apply item2.
637   metadata.ApplyMetadata(item2, stack_samples.begin() + 1,
638                          stack_samples.begin() + 4, &stack_samples,
639                          &name_hashes);
640
641   ASSERT_EQ(2, name_hashes.size());
642   EXPECT_EQ(3u, name_hashes[0]);
643   EXPECT_EQ(5u, name_hashes[1]);
644
645   EXPECT_EQ(0, stack_samples[0].metadata_size());
646
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);
651
652   EXPECT_EQ(0, stack_samples[2].metadata_size());
653
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);
657
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);
661 }
662
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>
669       stack_samples;
670   google::protobuf::RepeatedField<uint64_t> name_hashes;
671
672   const base::MetadataRecorder::Item item1(3, 30, absl::nullopt, 300);
673   const base::MetadataRecorder::Item item2(3, 30, absl::nullopt, 400);
674
675   metadata.RecordMetadata(base::MetadataRecorder::MetadataProvider(
676       &metadata_recorder, base::PlatformThread::CurrentId()));
677   *stack_samples.Add()->mutable_metadata() =
678       metadata.CreateSampleMetadata(&name_hashes);
679
680   // Record item1 on an ongoing basis via RecordMetadata.
681   metadata_recorder.Set(item1.name_hash, *item1.key, item1.thread_id,
682                         item1.value);
683   metadata.RecordMetadata(base::MetadataRecorder::MetadataProvider(
684       &metadata_recorder, base::PlatformThread::CurrentId()));
685   *stack_samples.Add()->mutable_metadata() =
686       metadata.CreateSampleMetadata(&name_hashes);
687
688   metadata.RecordMetadata(base::MetadataRecorder::MetadataProvider(
689       &metadata_recorder, base::PlatformThread::CurrentId()));
690   *stack_samples.Add()->mutable_metadata() =
691       metadata.CreateSampleMetadata(&name_hashes);
692
693   ASSERT_EQ(3, stack_samples.size());
694
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);
698
699   ASSERT_EQ(1, name_hashes.size());
700   EXPECT_EQ(3u, name_hashes[0]);
701
702   EXPECT_EQ(1, stack_samples[0].metadata_size());
703   ExpectMetadataApplied(item2, stack_samples, 0, 0, name_hashes);
704
705   EXPECT_EQ(0, stack_samples[1].metadata_size());
706   EXPECT_EQ(0, stack_samples[2].metadata_size());
707
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);
713
714   EXPECT_EQ(1, stack_samples[3].metadata_size());
715   ExpectMetadataApplied(item1, stack_samples, 3, 0, name_hashes);
716 }
717
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>
722       stack_samples;
723   google::protobuf::RepeatedField<uint64_t> name_hashes;
724
725   for (int i = 0; i < 5; i++)
726     stack_samples.Add();
727
728   const base::MetadataRecorder::Item item(3, 30, absl::nullopt, 300);
729
730   // Apply metadata over two non-overlapping ranges.
731   metadata.ApplyMetadata(item, stack_samples.begin(), stack_samples.begin() + 2,
732                          &stack_samples, &name_hashes);
733
734   metadata.ApplyMetadata(item, stack_samples.begin() + 3,
735                          stack_samples.begin() + 4, &stack_samples,
736                          &name_hashes);
737
738   ASSERT_EQ(1, name_hashes.size());
739   EXPECT_EQ(3u, name_hashes[0]);
740
741   EXPECT_EQ(1, stack_samples[0].metadata_size());
742   ExpectMetadataApplied(item, stack_samples, 0, 0, name_hashes);
743
744   EXPECT_EQ(0, stack_samples[1].metadata_size());
745
746   EXPECT_EQ(1, stack_samples[2].metadata_size());
747   ExpectMetadataUnapplied(item, stack_samples, 2, 0, name_hashes);
748
749   EXPECT_EQ(1, stack_samples[3].metadata_size());
750   ExpectMetadataApplied(item, stack_samples, 3, 0, name_hashes);
751
752   EXPECT_EQ(1, stack_samples[4].metadata_size());
753   ExpectMetadataUnapplied(item, stack_samples, 4, 0, name_hashes);
754 }
755
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>
761       stack_samples;
762   google::protobuf::RepeatedField<uint64_t> name_hashes;
763
764   for (int i = 0; i < 5; i++)
765     stack_samples.Add();
766
767   const base::MetadataRecorder::Item item(3, 30, absl::nullopt, 300);
768
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);
773
774   metadata.ApplyMetadata(item, stack_samples.begin() + 2,
775                          stack_samples.begin() + 4, &stack_samples,
776                          &name_hashes);
777
778   ASSERT_EQ(1, name_hashes.size());
779   EXPECT_EQ(3u, name_hashes[0]);
780
781   EXPECT_EQ(1, stack_samples[0].metadata_size());
782   ExpectMetadataApplied(item, stack_samples, 0, 0, name_hashes);
783
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());
787
788   EXPECT_EQ(1, stack_samples[4].metadata_size());
789   ExpectMetadataUnapplied(item, stack_samples, 4, 0, name_hashes);
790 }
791
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>
798       stack_samples;
799   google::protobuf::RepeatedField<uint64_t> name_hashes;
800
801   for (int i = 0; i < 5; i++)
802     stack_samples.Add();
803
804   const base::MetadataRecorder::Item item1(3, 30, absl::nullopt, 300);
805   const base::MetadataRecorder::Item item2(3, 30, absl::nullopt, 400);
806
807   metadata.ApplyMetadata(item1, stack_samples.begin(),
808                          stack_samples.begin() + 2, &stack_samples,
809                          &name_hashes);
810
811   metadata.ApplyMetadata(item2, stack_samples.begin() + 2,
812                          stack_samples.begin() + 4, &stack_samples,
813                          &name_hashes);
814
815   ASSERT_EQ(1, name_hashes.size());
816   EXPECT_EQ(3u, name_hashes[0]);
817
818   EXPECT_EQ(1, stack_samples[0].metadata_size());
819   ExpectMetadataApplied(item1, stack_samples, 0, 0, name_hashes);
820
821   EXPECT_EQ(0, stack_samples[1].metadata_size());
822
823   EXPECT_EQ(1, stack_samples[2].metadata_size());
824   ExpectMetadataApplied(item2, stack_samples, 2, 0, name_hashes);
825
826   EXPECT_EQ(0, stack_samples[3].metadata_size());
827
828   EXPECT_EQ(1, stack_samples[4].metadata_size());
829   ExpectMetadataUnapplied(item2, stack_samples, 4, 0, name_hashes);
830 }
831
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>
838       stack_samples;
839   google::protobuf::RepeatedField<uint64_t> name_hashes;
840
841   for (int i = 0; i < 5; i++)
842     stack_samples.Add();
843
844   const base::MetadataRecorder::Item item(3, 30, absl::nullopt, 300);
845
846   metadata.ApplyMetadata(item, stack_samples.begin(), stack_samples.begin() + 4,
847                          &stack_samples, &name_hashes);
848
849   metadata.ApplyMetadata(item, stack_samples.begin() + 1,
850                          stack_samples.begin() + 3, &stack_samples,
851                          &name_hashes);
852
853   ASSERT_EQ(1, name_hashes.size());
854   EXPECT_EQ(3u, name_hashes[0]);
855
856   EXPECT_EQ(1, stack_samples[0].metadata_size());
857   ExpectMetadataApplied(item, stack_samples, 0, 0, name_hashes);
858
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());
862
863   EXPECT_EQ(1, stack_samples[4].metadata_size());
864   ExpectMetadataUnapplied(item, stack_samples, 4, 0, name_hashes);
865 }
866
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>
874       stack_samples;
875   google::protobuf::RepeatedField<uint64_t> name_hashes;
876
877   for (int i = 0; i < 5; i++)
878     stack_samples.Add();
879
880   const base::MetadataRecorder::Item item1(3, 30, absl::nullopt, 300);
881   const base::MetadataRecorder::Item item2(3, 30, absl::nullopt, 400);
882
883   // Apply metadata over a range, then over a range fully enclosed within the
884   // first one.
885   metadata.ApplyMetadata(item1, stack_samples.begin(),
886                          stack_samples.begin() + 4, &stack_samples,
887                          &name_hashes);
888
889   metadata.ApplyMetadata(item2, stack_samples.begin() + 1,
890                          stack_samples.begin() + 3, &stack_samples,
891                          &name_hashes);
892
893   ASSERT_EQ(1, name_hashes.size());
894   EXPECT_EQ(3u, name_hashes[0]);
895
896   EXPECT_EQ(1, stack_samples[0].metadata_size());
897   ExpectMetadataApplied(item1, stack_samples, 0, 0, name_hashes);
898
899   EXPECT_EQ(1, stack_samples[1].metadata_size());
900   ExpectMetadataApplied(item2, stack_samples, 1, 0, name_hashes);
901
902   EXPECT_EQ(0, stack_samples[2].metadata_size());
903
904   EXPECT_EQ(1, stack_samples[3].metadata_size());
905   ExpectMetadataApplied(item1, stack_samples, 3, 0, name_hashes);
906
907   EXPECT_EQ(1, stack_samples[4].metadata_size());
908   ExpectMetadataUnapplied(item1, stack_samples, 4, 0, name_hashes);
909 }
910
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>
917       stack_samples;
918   google::protobuf::RepeatedField<uint64_t> name_hashes;
919
920   for (int i = 0; i < 5; i++)
921     stack_samples.Add();
922
923   const base::MetadataRecorder::Item item(3, 30, absl::nullopt, 300);
924
925   // Apply metadata over a range, then over a range that fully encloses the
926   // first one.
927   metadata.ApplyMetadata(item, stack_samples.begin() + 1,
928                          stack_samples.begin() + 3, &stack_samples,
929                          &name_hashes);
930
931   metadata.ApplyMetadata(item, stack_samples.begin(), stack_samples.begin() + 4,
932                          &stack_samples, &name_hashes);
933
934   ASSERT_EQ(1, name_hashes.size());
935   EXPECT_EQ(3u, name_hashes[0]);
936
937   EXPECT_EQ(1, stack_samples[0].metadata_size());
938   ExpectMetadataApplied(item, stack_samples, 0, 0, name_hashes);
939
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());
943
944   EXPECT_EQ(1, stack_samples[4].metadata_size());
945   ExpectMetadataUnapplied(item, stack_samples, 4, 0, name_hashes);
946 }
947
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
950 // recorded.
951 TEST(CallStackProfileMetadataTest,
952      ApplyMetadata_UpdateEnclosesExistingRangeWithDifferentValues) {
953   CallStackProfileMetadata metadata;
954   google::protobuf::RepeatedPtrField<CallStackProfile::StackSample>
955       stack_samples;
956   google::protobuf::RepeatedField<uint64_t> name_hashes;
957
958   for (int i = 0; i < 5; i++)
959     stack_samples.Add();
960
961   const base::MetadataRecorder::Item item1(3, 30, absl::nullopt, 300);
962   const base::MetadataRecorder::Item item2(3, 30, absl::nullopt, 400);
963
964   // Apply metadata over a range, then over a range that fully encloses the
965   // first one.
966   metadata.ApplyMetadata(item1, stack_samples.begin() + 1,
967                          stack_samples.begin() + 3, &stack_samples,
968                          &name_hashes);
969
970   metadata.ApplyMetadata(item2, stack_samples.begin(),
971                          stack_samples.begin() + 4, &stack_samples,
972                          &name_hashes);
973
974   ASSERT_EQ(1, name_hashes.size());
975   EXPECT_EQ(3u, name_hashes[0]);
976
977   EXPECT_EQ(1, stack_samples[0].metadata_size());
978   ExpectMetadataApplied(item2, stack_samples, 0, 0, name_hashes);
979
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());
983
984   EXPECT_EQ(1, stack_samples[4].metadata_size());
985   ExpectMetadataUnapplied(item2, stack_samples, 4, 0, name_hashes);
986 }
987
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>
994       stack_samples;
995   google::protobuf::RepeatedField<uint64_t> name_hashes;
996
997   for (int i = 0; i < 5; i++)
998     stack_samples.Add();
999
1000   const base::MetadataRecorder::Item item(3, 30, absl::nullopt, 300);
1001
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,
1006                          &name_hashes);
1007
1008   metadata.ApplyMetadata(item, stack_samples.begin(), stack_samples.begin() + 2,
1009                          &stack_samples, &name_hashes);
1010
1011   ASSERT_EQ(1, name_hashes.size());
1012   EXPECT_EQ(3u, name_hashes[0]);
1013
1014   EXPECT_EQ(1, stack_samples[0].metadata_size());
1015   ExpectMetadataApplied(item, stack_samples, 0, 0, name_hashes);
1016
1017   EXPECT_EQ(0, stack_samples[1].metadata_size());
1018   EXPECT_EQ(0, stack_samples[2].metadata_size());
1019
1020   EXPECT_EQ(1, stack_samples[3].metadata_size());
1021   ExpectMetadataUnapplied(item, stack_samples, 3, 0, name_hashes);
1022
1023   EXPECT_EQ(0, stack_samples[4].metadata_size());
1024 }
1025
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>
1033       stack_samples;
1034   google::protobuf::RepeatedField<uint64_t> name_hashes;
1035
1036   for (int i = 0; i < 5; i++)
1037     stack_samples.Add();
1038
1039   const base::MetadataRecorder::Item item1(3, 30, absl::nullopt, 300);
1040   const base::MetadataRecorder::Item item2(3, 30, absl::nullopt, 400);
1041
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,
1046                          &name_hashes);
1047
1048   metadata.ApplyMetadata(item2, stack_samples.begin(),
1049                          stack_samples.begin() + 2, &stack_samples,
1050                          &name_hashes);
1051
1052   ASSERT_EQ(1, name_hashes.size());
1053   EXPECT_EQ(3u, name_hashes[0]);
1054
1055   EXPECT_EQ(1, stack_samples[0].metadata_size());
1056   ExpectMetadataApplied(item2, stack_samples, 0, 0, name_hashes);
1057
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);
1061
1062   EXPECT_EQ(1, stack_samples[3].metadata_size());
1063   ExpectMetadataUnapplied(item1, stack_samples, 3, 0, name_hashes);
1064
1065   EXPECT_EQ(0, stack_samples[4].metadata_size());
1066 }
1067
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>
1074       stack_samples;
1075   google::protobuf::RepeatedField<uint64_t> name_hashes;
1076
1077   for (int i = 0; i < 5; i++)
1078     stack_samples.Add();
1079
1080   const base::MetadataRecorder::Item item(3, 30, absl::nullopt, 300);
1081
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);
1086
1087   metadata.ApplyMetadata(item, stack_samples.begin() + 1,
1088                          stack_samples.begin() + 4, &stack_samples,
1089                          &name_hashes);
1090
1091   ASSERT_EQ(1, name_hashes.size());
1092   EXPECT_EQ(3u, name_hashes[0]);
1093
1094   EXPECT_EQ(1, stack_samples[0].metadata_size());
1095   ExpectMetadataApplied(item, stack_samples, 0, 0, name_hashes);
1096
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());
1100
1101   EXPECT_EQ(1, stack_samples[4].metadata_size());
1102   ExpectMetadataUnapplied(item, stack_samples, 4, 0, name_hashes);
1103 }
1104
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>
1112       stack_samples;
1113   google::protobuf::RepeatedField<uint64_t> name_hashes;
1114
1115   for (int i = 0; i < 5; i++)
1116     stack_samples.Add();
1117
1118   const base::MetadataRecorder::Item item1(3, 30, absl::nullopt, 300);
1119   const base::MetadataRecorder::Item item2(3, 30, absl::nullopt, 400);
1120
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,
1125                          &name_hashes);
1126
1127   metadata.ApplyMetadata(item2, stack_samples.begin() + 1,
1128                          stack_samples.begin() + 4, &stack_samples,
1129                          &name_hashes);
1130
1131   ASSERT_EQ(1, name_hashes.size());
1132   EXPECT_EQ(3u, name_hashes[0]);
1133
1134   EXPECT_EQ(1, stack_samples[0].metadata_size());
1135   ExpectMetadataApplied(item1, stack_samples, 0, 0, name_hashes);
1136
1137   EXPECT_EQ(1, stack_samples[1].metadata_size());
1138   ExpectMetadataApplied(item2, stack_samples, 1, 0, name_hashes);
1139
1140   EXPECT_EQ(0, stack_samples[2].metadata_size());
1141   EXPECT_EQ(0, stack_samples[3].metadata_size());
1142
1143   EXPECT_EQ(1, stack_samples[4].metadata_size());
1144   ExpectMetadataUnapplied(item2, stack_samples, 4, 0, name_hashes);
1145 }
1146
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>
1152       stack_samples;
1153   google::protobuf::RepeatedField<uint64_t> name_hashes;
1154
1155   for (int i = 0; i < 5; i++)
1156     stack_samples.Add();
1157
1158   const base::MetadataRecorder::Item item(3, 30, absl::nullopt, 300);
1159
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,
1163                          &name_hashes);
1164
1165   metadata.ApplyMetadata(item, stack_samples.begin() + 1,
1166                          stack_samples.begin() + 4, &stack_samples,
1167                          &name_hashes);
1168
1169   ASSERT_EQ(1, name_hashes.size());
1170   EXPECT_EQ(3u, name_hashes[0]);
1171
1172   EXPECT_EQ(0, stack_samples[0].metadata_size());
1173
1174   EXPECT_EQ(1, stack_samples[1].metadata_size());
1175   ExpectMetadataApplied(item, stack_samples, 1, 0, name_hashes);
1176
1177   EXPECT_EQ(0, stack_samples[2].metadata_size());
1178   EXPECT_EQ(0, stack_samples[3].metadata_size());
1179
1180   EXPECT_EQ(1, stack_samples[4].metadata_size());
1181   ExpectMetadataUnapplied(item, stack_samples, 4, 0, name_hashes);
1182 }
1183
1184 // Checks that applying to the same range with a different value overwrites the
1185 // initial value.
1186 TEST(CallStackProfileMetadataTest, ApplyMetadata_UpdateWithDifferentValues) {
1187   CallStackProfileMetadata metadata;
1188   google::protobuf::RepeatedPtrField<CallStackProfile::StackSample>
1189       stack_samples;
1190   google::protobuf::RepeatedField<uint64_t> name_hashes;
1191
1192   for (int i = 0; i < 5; i++)
1193     stack_samples.Add();
1194
1195   const base::MetadataRecorder::Item item1(3, 30, absl::nullopt, 300);
1196   const base::MetadataRecorder::Item item2(3, 30, absl::nullopt, 400);
1197
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,
1201                          &name_hashes);
1202
1203   metadata.ApplyMetadata(item2, stack_samples.begin() + 1,
1204                          stack_samples.begin() + 4, &stack_samples,
1205                          &name_hashes);
1206
1207   ASSERT_EQ(1, name_hashes.size());
1208   EXPECT_EQ(3u, name_hashes[0]);
1209
1210   EXPECT_EQ(0, stack_samples[0].metadata_size());
1211
1212   EXPECT_EQ(1, stack_samples[1].metadata_size());
1213   ExpectMetadataApplied(item2, stack_samples, 1, 0, name_hashes);
1214
1215   EXPECT_EQ(0, stack_samples[2].metadata_size());
1216   EXPECT_EQ(0, stack_samples[3].metadata_size());
1217
1218   EXPECT_EQ(1, stack_samples[4].metadata_size());
1219   ExpectMetadataUnapplied(item2, stack_samples, 4, 0, name_hashes);
1220 }
1221
1222 }  // namespace metrics