1 // Copyright 2015 The Chromium Authors. All rights reserved.
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_metrics_provider.h"
7 #include "base/metrics/field_trial.h"
8 #include "base/profiler/stack_sampling_profiler.h"
9 #include "base/run_loop.h"
10 #include "base/strings/string_number_conversions.h"
11 #include "components/metrics/proto/chrome_user_metrics_extension.pb.h"
12 #include "components/variations/entropy_provider.h"
13 #include "testing/gtest/include/gtest/gtest.h"
15 using base::StackSamplingProfiler
;
16 using Frame
= StackSamplingProfiler::Frame
;
17 using Module
= StackSamplingProfiler::Module
;
18 using Profile
= StackSamplingProfiler::CallStackProfile
;
19 using Profiles
= StackSamplingProfiler::CallStackProfiles
;
20 using Sample
= StackSamplingProfiler::Sample
;
24 using Params
= CallStackProfileMetricsProvider::Params
;
26 // This test fixture enables the field trial that
27 // CallStackProfileMetricsProvider depends on to report profiles.
28 class CallStackProfileMetricsProviderTest
: public testing::Test
{
30 CallStackProfileMetricsProviderTest()
31 : field_trial_list_(nullptr) {
32 base::FieldTrialList::CreateFieldTrial(
33 TestState::kFieldTrialName
,
34 TestState::kReportProfilesGroupName
);
35 TestState::ResetStaticStateForTesting();
38 ~CallStackProfileMetricsProviderTest() override
{}
40 // Utility function to append profiles to the metrics provider.
41 void AppendProfiles(const Params
& params
, const Profiles
& profiles
) {
42 CallStackProfileMetricsProvider::GetProfilerCallback(params
).Run(profiles
);
46 // Exposes field trial/group names from the CallStackProfileMetricsProvider.
47 class TestState
: public CallStackProfileMetricsProvider
{
49 using CallStackProfileMetricsProvider::kFieldTrialName
;
50 using CallStackProfileMetricsProvider::kReportProfilesGroupName
;
51 using CallStackProfileMetricsProvider::ResetStaticStateForTesting
;
54 base::FieldTrialList field_trial_list_
;
56 DISALLOW_COPY_AND_ASSIGN(CallStackProfileMetricsProviderTest
);
59 // Checks that all properties from multiple profiles are filled as expected.
60 TEST_F(CallStackProfileMetricsProviderTest
, MultipleProfiles
) {
61 const uintptr_t module1_base_address
= 0x1000;
62 const uintptr_t module2_base_address
= 0x2000;
63 const uintptr_t module3_base_address
= 0x3000;
65 const Module profile_modules
[][2] = {
68 reinterpret_cast<const void*>(module1_base_address
),
71 base::FilePath(L
"c:\\some\\path\\to\\chrome.exe")
73 base::FilePath("/some/path/to/chrome")
77 reinterpret_cast<const void*>(module2_base_address
),
80 base::FilePath(L
"c:\\some\\path\\to\\third_party.dll")
82 base::FilePath("/some/path/to/third_party.so")
88 reinterpret_cast<const void*>(module3_base_address
),
91 base::FilePath(L
"c:\\some\\path\\to\\third_party2.dll")
93 base::FilePath("/some/path/to/third_party2.so")
96 Module( // Repeated from the first profile.
97 reinterpret_cast<const void*>(module1_base_address
),
100 base::FilePath(L
"c:\\some\\path\\to\\chrome.exe")
102 base::FilePath("/some/path/to/chrome")
108 // Values for Windows generated with:
109 // perl -MDigest::MD5=md5 -MEncode=encode
110 // -e 'for(@ARGV){printf "%x\n", unpack "Q>", md5 encode "UTF-16LE", $_}'
111 // chrome.exe third_party.dll third_party2.dll
113 // Values for Linux generated with:
114 // perl -MDigest::MD5=md5
115 // -e 'for(@ARGV){printf "%x\n", unpack "Q>", md5 $_}'
116 // chrome third_party.so third_party2.so
117 const uint64 profile_expected_name_md5_prefixes
[][2] = {
120 0x46c3e4166659ac02ULL
,
121 0x7e2b8bfddeae1abaULL
123 0x554838a8451ac36cUL
,
129 0x87b66f4573a4d5caULL
,
130 0x46c3e4166659ac02ULL
132 0xb4647e539fa6ec9eUL
,
138 // Represents two stack samples for each of two profiles, where each stack
139 // contains three frames. Each frame contains an instruction pointer and a
140 // module index corresponding to the module for the profile in
143 // So, the first stack sample below has its top frame in module 0 at an offset
144 // of 0x10 from the module's base address, the next-to-top frame in module 1
145 // at an offset of 0x20 from the module's base address, and the bottom frame
146 // in module 0 at an offset of 0x30 from the module's base address
147 const Frame profile_sample_frames
[][2][3] = {
150 Frame(reinterpret_cast<const void*>(module1_base_address
+ 0x10), 0),
151 Frame(reinterpret_cast<const void*>(module2_base_address
+ 0x20), 1),
152 Frame(reinterpret_cast<const void*>(module1_base_address
+ 0x30), 0)
155 Frame(reinterpret_cast<const void*>(module2_base_address
+ 0x10), 1),
156 Frame(reinterpret_cast<const void*>(module1_base_address
+ 0x20), 0),
157 Frame(reinterpret_cast<const void*>(module2_base_address
+ 0x30), 1)
162 Frame(reinterpret_cast<const void*>(module3_base_address
+ 0x10), 0),
163 Frame(reinterpret_cast<const void*>(module1_base_address
+ 0x20), 1),
164 Frame(reinterpret_cast<const void*>(module3_base_address
+ 0x30), 0)
167 Frame(reinterpret_cast<const void*>(module1_base_address
+ 0x10), 1),
168 Frame(reinterpret_cast<const void*>(module3_base_address
+ 0x20), 0),
169 Frame(reinterpret_cast<const void*>(module1_base_address
+ 0x30), 1)
174 base::TimeDelta profile_durations
[2] = {
175 base::TimeDelta::FromMilliseconds(100),
176 base::TimeDelta::FromMilliseconds(200)
179 base::TimeDelta profile_sampling_periods
[2] = {
180 base::TimeDelta::FromMilliseconds(10),
181 base::TimeDelta::FromMilliseconds(20)
184 std::vector
<Profile
> profiles
;
185 for (size_t i
= 0; i
< arraysize(profile_sample_frames
); ++i
) {
187 profile
.modules
.insert(
188 profile
.modules
.end(), &profile_modules
[i
][0],
189 &profile_modules
[i
][0] + arraysize(profile_modules
[i
]));
191 for (size_t j
= 0; j
< arraysize(profile_sample_frames
[i
]); ++j
) {
192 profile
.samples
.push_back(Sample());
193 Sample
& sample
= profile
.samples
.back();
194 sample
.insert(sample
.end(), &profile_sample_frames
[i
][j
][0],
195 &profile_sample_frames
[i
][j
][0] +
196 arraysize(profile_sample_frames
[i
][j
]));
199 profile
.profile_duration
= profile_durations
[i
];
200 profile
.sampling_period
= profile_sampling_periods
[i
];
202 profiles
.push_back(profile
);
205 CallStackProfileMetricsProvider provider
;
206 provider
.OnRecordingEnabled();
208 Params(CallStackProfileMetricsProvider::PROCESS_STARTUP
, false),
210 ChromeUserMetricsExtension uma_proto
;
211 provider
.ProvideGeneralMetrics(&uma_proto
);
213 ASSERT_EQ(static_cast<int>(arraysize(profile_sample_frames
)),
214 uma_proto
.sampled_profile().size());
215 for (size_t i
= 0; i
< arraysize(profile_sample_frames
); ++i
) {
216 SCOPED_TRACE("profile " + base::IntToString(i
));
217 const SampledProfile
& sampled_profile
= uma_proto
.sampled_profile().Get(i
);
218 ASSERT_TRUE(sampled_profile
.has_call_stack_profile());
219 const CallStackProfile
& call_stack_profile
=
220 sampled_profile
.call_stack_profile();
222 ASSERT_EQ(static_cast<int>(arraysize(profile_sample_frames
[i
])),
223 call_stack_profile
.sample().size());
224 for (size_t j
= 0; j
< arraysize(profile_sample_frames
[i
]); ++j
) {
225 SCOPED_TRACE("sample " + base::IntToString(j
));
226 const CallStackProfile::Sample
& proto_sample
=
227 call_stack_profile
.sample().Get(j
);
228 ASSERT_EQ(static_cast<int>(arraysize(profile_sample_frames
[i
][j
])),
229 proto_sample
.entry().size());
230 ASSERT_TRUE(proto_sample
.has_count());
231 EXPECT_EQ(1u, proto_sample
.count());
232 for (size_t k
= 0; k
< arraysize(profile_sample_frames
[i
][j
]); ++k
) {
233 SCOPED_TRACE("frame " + base::IntToString(k
));
234 const CallStackProfile::Entry
& entry
= proto_sample
.entry().Get(k
);
235 ASSERT_TRUE(entry
.has_address());
236 const char* instruction_pointer
= reinterpret_cast<const char*>(
237 profile_sample_frames
[i
][j
][k
].instruction_pointer
);
238 const char* module_base_address
= reinterpret_cast<const char*>(
239 profile_modules
[i
][profile_sample_frames
[i
][j
][k
].module_index
]
241 EXPECT_EQ(static_cast<uint64
>(instruction_pointer
-
242 module_base_address
), entry
.address());
243 ASSERT_TRUE(entry
.has_module_id_index());
244 EXPECT_EQ(profile_sample_frames
[i
][j
][k
].module_index
,
245 static_cast<size_t>(entry
.module_id_index()));
249 ASSERT_EQ(static_cast<int>(arraysize(profile_modules
[i
])),
250 call_stack_profile
.module_id().size());
251 for (size_t j
= 0; j
< arraysize(profile_modules
[i
]); ++j
) {
252 SCOPED_TRACE("module " + base::IntToString(j
));
253 const CallStackProfile::ModuleIdentifier
& module_identifier
=
254 call_stack_profile
.module_id().Get(j
);
255 ASSERT_TRUE(module_identifier
.has_build_id());
256 EXPECT_EQ(profile_modules
[i
][j
].id
, module_identifier
.build_id());
257 ASSERT_TRUE(module_identifier
.has_name_md5_prefix());
258 EXPECT_EQ(profile_expected_name_md5_prefixes
[i
][j
],
259 module_identifier
.name_md5_prefix());
262 ASSERT_TRUE(call_stack_profile
.has_profile_duration_ms());
263 EXPECT_EQ(profile_durations
[i
].InMilliseconds(),
264 call_stack_profile
.profile_duration_ms());
265 ASSERT_TRUE(call_stack_profile
.has_sampling_period_ms());
266 EXPECT_EQ(profile_sampling_periods
[i
].InMilliseconds(),
267 call_stack_profile
.sampling_period_ms());
268 ASSERT_TRUE(sampled_profile
.has_trigger_event());
269 EXPECT_EQ(SampledProfile::PROCESS_STARTUP
, sampled_profile
.trigger_event());
273 // Checks that all duplicate samples are collapsed with
274 // preserve_sample_ordering = false.
275 TEST_F(CallStackProfileMetricsProviderTest
, RepeatedStacksUnordered
) {
276 const uintptr_t module_base_address
= 0x1000;
278 const Module modules
[] = {
280 reinterpret_cast<const void*>(module_base_address
),
283 base::FilePath(L
"c:\\some\\path\\to\\chrome.exe")
285 base::FilePath("/some/path/to/chrome")
290 // Duplicate samples in slots 0, 2, and 3.
291 const Frame sample_frames
[][1] = {
292 { Frame(reinterpret_cast<const void*>(module_base_address
+ 0x10), 0), },
293 { Frame(reinterpret_cast<const void*>(module_base_address
+ 0x20), 0), },
294 { Frame(reinterpret_cast<const void*>(module_base_address
+ 0x10), 0), },
295 { Frame(reinterpret_cast<const void*>(module_base_address
+ 0x10), 0) }
299 profile
.modules
.insert(profile
.modules
.end(), &modules
[0],
300 &modules
[0] + arraysize(modules
));
302 for (size_t i
= 0; i
< arraysize(sample_frames
); ++i
) {
303 profile
.samples
.push_back(Sample());
304 Sample
& sample
= profile
.samples
.back();
305 sample
.insert(sample
.end(), &sample_frames
[i
][0],
306 &sample_frames
[i
][0] + arraysize(sample_frames
[i
]));
309 profile
.profile_duration
= base::TimeDelta::FromMilliseconds(100);
310 profile
.sampling_period
= base::TimeDelta::FromMilliseconds(10);
312 CallStackProfileMetricsProvider provider
;
313 provider
.OnRecordingEnabled();
315 Params(CallStackProfileMetricsProvider::PROCESS_STARTUP
, false),
316 std::vector
<Profile
>(1, profile
));
317 ChromeUserMetricsExtension uma_proto
;
318 provider
.ProvideGeneralMetrics(&uma_proto
);
320 ASSERT_EQ(1, uma_proto
.sampled_profile().size());
321 const SampledProfile
& sampled_profile
= uma_proto
.sampled_profile().Get(0);
322 ASSERT_TRUE(sampled_profile
.has_call_stack_profile());
323 const CallStackProfile
& call_stack_profile
=
324 sampled_profile
.call_stack_profile();
326 ASSERT_EQ(2, call_stack_profile
.sample().size());
327 for (int i
= 0; i
< 2; ++i
) {
328 SCOPED_TRACE("sample " + base::IntToString(i
));
329 const CallStackProfile::Sample
& proto_sample
=
330 call_stack_profile
.sample().Get(i
);
331 ASSERT_EQ(static_cast<int>(arraysize(sample_frames
[i
])),
332 proto_sample
.entry().size());
333 ASSERT_TRUE(proto_sample
.has_count());
334 EXPECT_EQ(i
== 0 ? 3u : 1u, proto_sample
.count());
335 for (size_t j
= 0; j
< arraysize(sample_frames
[i
]); ++j
) {
336 SCOPED_TRACE("frame " + base::IntToString(j
));
337 const CallStackProfile::Entry
& entry
= proto_sample
.entry().Get(j
);
338 ASSERT_TRUE(entry
.has_address());
339 const char* instruction_pointer
= reinterpret_cast<const char*>(
340 sample_frames
[i
][j
].instruction_pointer
);
341 const char* module_base_address
= reinterpret_cast<const char*>(
342 modules
[sample_frames
[i
][j
].module_index
].base_address
);
343 EXPECT_EQ(static_cast<uint64
>(instruction_pointer
- module_base_address
),
345 ASSERT_TRUE(entry
.has_module_id_index());
346 EXPECT_EQ(sample_frames
[i
][j
].module_index
,
347 static_cast<size_t>(entry
.module_id_index()));
352 // Checks that only contiguous duplicate samples are collapsed with
353 // preserve_sample_ordering = true.
354 TEST_F(CallStackProfileMetricsProviderTest
, RepeatedStacksOrdered
) {
355 const uintptr_t module_base_address
= 0x1000;
357 const Module modules
[] = {
359 reinterpret_cast<const void*>(module_base_address
),
362 base::FilePath(L
"c:\\some\\path\\to\\chrome.exe")
364 base::FilePath("/some/path/to/chrome")
369 // Duplicate samples in slots 0, 2, and 3.
370 const Frame sample_frames
[][1] = {
371 { Frame(reinterpret_cast<const void*>(module_base_address
+ 0x10), 0), },
372 { Frame(reinterpret_cast<const void*>(module_base_address
+ 0x20), 0), },
373 { Frame(reinterpret_cast<const void*>(module_base_address
+ 0x10), 0), },
374 { Frame(reinterpret_cast<const void*>(module_base_address
+ 0x10), 0) }
378 profile
.modules
.insert(profile
.modules
.end(), &modules
[0],
379 &modules
[0] + arraysize(modules
));
381 for (size_t i
= 0; i
< arraysize(sample_frames
); ++i
) {
382 profile
.samples
.push_back(Sample());
383 Sample
& sample
= profile
.samples
.back();
384 sample
.insert(sample
.end(), &sample_frames
[i
][0],
385 &sample_frames
[i
][0] + arraysize(sample_frames
[i
]));
388 profile
.profile_duration
= base::TimeDelta::FromMilliseconds(100);
389 profile
.sampling_period
= base::TimeDelta::FromMilliseconds(10);
391 CallStackProfileMetricsProvider provider
;
392 provider
.OnRecordingEnabled();
394 Params(CallStackProfileMetricsProvider::PROCESS_STARTUP
, true),
395 std::vector
<Profile
>(1, profile
));
396 ChromeUserMetricsExtension uma_proto
;
397 provider
.ProvideGeneralMetrics(&uma_proto
);
399 ASSERT_EQ(1, uma_proto
.sampled_profile().size());
400 const SampledProfile
& sampled_profile
= uma_proto
.sampled_profile().Get(0);
401 ASSERT_TRUE(sampled_profile
.has_call_stack_profile());
402 const CallStackProfile
& call_stack_profile
=
403 sampled_profile
.call_stack_profile();
405 ASSERT_EQ(3, call_stack_profile
.sample().size());
406 for (int i
= 0; i
< 3; ++i
) {
407 SCOPED_TRACE("sample " + base::IntToString(i
));
408 const CallStackProfile::Sample
& proto_sample
=
409 call_stack_profile
.sample().Get(i
);
410 ASSERT_EQ(static_cast<int>(arraysize(sample_frames
[i
])),
411 proto_sample
.entry().size());
412 ASSERT_TRUE(proto_sample
.has_count());
413 EXPECT_EQ(i
== 2 ? 2u : 1u, proto_sample
.count());
414 for (size_t j
= 0; j
< arraysize(sample_frames
[i
]); ++j
) {
415 SCOPED_TRACE("frame " + base::IntToString(j
));
416 const CallStackProfile::Entry
& entry
= proto_sample
.entry().Get(j
);
417 ASSERT_TRUE(entry
.has_address());
418 const char* instruction_pointer
= reinterpret_cast<const char*>(
419 sample_frames
[i
][j
].instruction_pointer
);
420 const char* module_base_address
= reinterpret_cast<const char*>(
421 modules
[sample_frames
[i
][j
].module_index
].base_address
);
422 EXPECT_EQ(static_cast<uint64
>(instruction_pointer
- module_base_address
),
424 ASSERT_TRUE(entry
.has_module_id_index());
425 EXPECT_EQ(sample_frames
[i
][j
].module_index
,
426 static_cast<size_t>(entry
.module_id_index()));
431 // Checks that unknown modules produce an empty Entry.
432 TEST_F(CallStackProfileMetricsProviderTest
, UnknownModule
) {
433 const Frame
frame(reinterpret_cast<const void*>(0x1000),
434 Frame::kUnknownModuleIndex
);
438 profile
.samples
.push_back(Sample(1, frame
));
440 profile
.profile_duration
= base::TimeDelta::FromMilliseconds(100);
441 profile
.sampling_period
= base::TimeDelta::FromMilliseconds(10);
443 CallStackProfileMetricsProvider provider
;
444 provider
.OnRecordingEnabled();
446 Params(CallStackProfileMetricsProvider::PROCESS_STARTUP
, false),
447 std::vector
<Profile
>(1, profile
));
448 ChromeUserMetricsExtension uma_proto
;
449 provider
.ProvideGeneralMetrics(&uma_proto
);
451 ASSERT_EQ(1, uma_proto
.sampled_profile().size());
452 const SampledProfile
& sampled_profile
= uma_proto
.sampled_profile().Get(0);
453 ASSERT_TRUE(sampled_profile
.has_call_stack_profile());
454 const CallStackProfile
& call_stack_profile
=
455 sampled_profile
.call_stack_profile();
457 ASSERT_EQ(1, call_stack_profile
.sample().size());
458 const CallStackProfile::Sample
& proto_sample
=
459 call_stack_profile
.sample().Get(0);
460 ASSERT_EQ(1, proto_sample
.entry().size());
461 ASSERT_TRUE(proto_sample
.has_count());
462 EXPECT_EQ(1u, proto_sample
.count());
463 const CallStackProfile::Entry
& entry
= proto_sample
.entry().Get(0);
464 EXPECT_FALSE(entry
.has_address());
465 EXPECT_FALSE(entry
.has_module_id_index());
468 // Checks that pending profiles are only passed back to ProvideGeneralMetrics
470 TEST_F(CallStackProfileMetricsProviderTest
, ProfilesProvidedOnlyOnce
) {
471 CallStackProfileMetricsProvider provider
;
472 for (int i
= 0; i
< 2; ++i
) {
474 profile
.samples
.push_back(Sample(1, Frame(
475 reinterpret_cast<const void*>(0x1000), Frame::kUnknownModuleIndex
)));
477 profile
.profile_duration
= base::TimeDelta::FromMilliseconds(100);
478 // Use the sampling period to distinguish the two profiles.
479 profile
.sampling_period
= base::TimeDelta::FromMilliseconds(i
);
481 provider
.OnRecordingEnabled();
483 Params(CallStackProfileMetricsProvider::PROCESS_STARTUP
, false),
484 std::vector
<Profile
>(1, profile
));
485 ChromeUserMetricsExtension uma_proto
;
486 provider
.ProvideGeneralMetrics(&uma_proto
);
488 ASSERT_EQ(1, uma_proto
.sampled_profile().size());
489 const SampledProfile
& sampled_profile
= uma_proto
.sampled_profile().Get(0);
490 ASSERT_TRUE(sampled_profile
.has_call_stack_profile());
491 const CallStackProfile
& call_stack_profile
=
492 sampled_profile
.call_stack_profile();
493 ASSERT_TRUE(call_stack_profile
.has_sampling_period_ms());
494 EXPECT_EQ(i
, call_stack_profile
.sampling_period_ms());
498 // Checks that pending profiles are provided to ProvideGeneralMetrics
499 // when collected before CallStackProfileMetricsProvider is instantiated.
500 TEST_F(CallStackProfileMetricsProviderTest
,
501 ProfilesProvidedWhenCollectedBeforeInstantiation
) {
503 profile
.samples
.push_back(Sample(1, Frame(
504 reinterpret_cast<const void*>(0x1000), Frame::kUnknownModuleIndex
)));
506 profile
.profile_duration
= base::TimeDelta::FromMilliseconds(100);
507 profile
.sampling_period
= base::TimeDelta::FromMilliseconds(10);
510 Params(CallStackProfileMetricsProvider::PROCESS_STARTUP
, false),
511 std::vector
<Profile
>(1, profile
));
513 CallStackProfileMetricsProvider provider
;
514 provider
.OnRecordingEnabled();
515 ChromeUserMetricsExtension uma_proto
;
516 provider
.ProvideGeneralMetrics(&uma_proto
);
518 EXPECT_EQ(1, uma_proto
.sampled_profile_size());
521 // Checks that pending profiles are not provided to ProvideGeneralMetrics
522 // while recording is disabled.
523 TEST_F(CallStackProfileMetricsProviderTest
, ProfilesNotProvidedWhileDisabled
) {
525 profile
.samples
.push_back(Sample(1, Frame(
526 reinterpret_cast<const void*>(0x1000), Frame::kUnknownModuleIndex
)));
528 profile
.profile_duration
= base::TimeDelta::FromMilliseconds(100);
529 profile
.sampling_period
= base::TimeDelta::FromMilliseconds(10);
531 CallStackProfileMetricsProvider provider
;
532 provider
.OnRecordingDisabled();
534 Params(CallStackProfileMetricsProvider::PROCESS_STARTUP
, false),
535 std::vector
<Profile
>(1, profile
));
536 ChromeUserMetricsExtension uma_proto
;
537 provider
.ProvideGeneralMetrics(&uma_proto
);
539 EXPECT_EQ(0, uma_proto
.sampled_profile_size());
542 // Checks that pending profiles are not provided to ProvideGeneralMetrics
543 // if recording is disabled while profiling.
544 TEST_F(CallStackProfileMetricsProviderTest
,
545 ProfilesNotProvidedAfterChangeToDisabled
) {
547 profile
.samples
.push_back(Sample(1, Frame(
548 reinterpret_cast<const void*>(0x1000), Frame::kUnknownModuleIndex
)));
550 profile
.profile_duration
= base::TimeDelta::FromMilliseconds(100);
551 profile
.sampling_period
= base::TimeDelta::FromMilliseconds(10);
553 CallStackProfileMetricsProvider provider
;
554 provider
.OnRecordingEnabled();
555 base::StackSamplingProfiler::CompletedCallback callback
=
556 CallStackProfileMetricsProvider::GetProfilerCallback(
557 Params(CallStackProfileMetricsProvider::PROCESS_STARTUP
, false));
559 provider
.OnRecordingDisabled();
560 callback
.Run(std::vector
<Profile
>(1, profile
));
561 ChromeUserMetricsExtension uma_proto
;
562 provider
.ProvideGeneralMetrics(&uma_proto
);
564 EXPECT_EQ(0, uma_proto
.sampled_profile_size());
567 // Checks that pending profiles are not provided to ProvideGeneralMetrics if
568 // recording is enabled, but then disabled and reenabled while profiling.
569 TEST_F(CallStackProfileMetricsProviderTest
,
570 ProfilesNotProvidedAfterChangeToDisabledThenEnabled
) {
572 profile
.samples
.push_back(Sample(1, Frame(
573 reinterpret_cast<const void*>(0x1000), Frame::kUnknownModuleIndex
)));
575 profile
.profile_duration
= base::TimeDelta::FromMilliseconds(100);
576 profile
.sampling_period
= base::TimeDelta::FromMilliseconds(10);
578 CallStackProfileMetricsProvider provider
;
579 provider
.OnRecordingEnabled();
580 base::StackSamplingProfiler::CompletedCallback callback
=
581 CallStackProfileMetricsProvider::GetProfilerCallback(
582 Params(CallStackProfileMetricsProvider::PROCESS_STARTUP
, false));
584 provider
.OnRecordingDisabled();
585 provider
.OnRecordingEnabled();
586 callback
.Run(std::vector
<Profile
>(1, profile
));
587 ChromeUserMetricsExtension uma_proto
;
588 provider
.ProvideGeneralMetrics(&uma_proto
);
590 EXPECT_EQ(0, uma_proto
.sampled_profile_size());
593 // Checks that pending profiles are not provided to ProvideGeneralMetrics
594 // if recording is disabled, but then enabled while profiling.
595 TEST_F(CallStackProfileMetricsProviderTest
,
596 ProfilesNotProvidedAfterChangeFromDisabled
) {
598 profile
.samples
.push_back(Sample(1, Frame(
599 reinterpret_cast<const void*>(0x1000), Frame::kUnknownModuleIndex
)));
601 profile
.profile_duration
= base::TimeDelta::FromMilliseconds(100);
602 profile
.sampling_period
= base::TimeDelta::FromMilliseconds(10);
604 CallStackProfileMetricsProvider provider
;
605 provider
.OnRecordingDisabled();
606 base::StackSamplingProfiler::CompletedCallback callback
=
607 CallStackProfileMetricsProvider::GetProfilerCallback(
608 Params(CallStackProfileMetricsProvider::PROCESS_STARTUP
, false));
610 provider
.OnRecordingEnabled();
611 callback
.Run(std::vector
<Profile
>(1, profile
));
612 ChromeUserMetricsExtension uma_proto
;
613 provider
.ProvideGeneralMetrics(&uma_proto
);
615 EXPECT_EQ(0, uma_proto
.sampled_profile_size());
618 } // namespace metrics