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

Side by Side Diff: components/metrics/call_stack_profile_metrics_provider_unittest.cc

Issue 2444143002: Add process lifetime annotations to stack samples. (Closed)
Patch Set: fixed non-windows constant Created 4 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2015 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "components/metrics/call_stack_profile_metrics_provider.h" 5 #include "components/metrics/call_stack_profile_metrics_provider.h"
6 6
7 #include <stddef.h> 7 #include <stddef.h>
8 #include <stdint.h> 8 #include <stdint.h>
9 9
10 #include <utility> 10 #include <utility>
11 11
12 #include "base/macros.h" 12 #include "base/macros.h"
13 #include "base/metrics/field_trial.h" 13 #include "base/metrics/field_trial.h"
14 #include "base/profiler/stack_sampling_profiler.h" 14 #include "base/profiler/stack_sampling_profiler.h"
15 #include "base/run_loop.h" 15 #include "base/run_loop.h"
16 #include "base/strings/string_number_conversions.h" 16 #include "base/strings/string_number_conversions.h"
17 #include "build/build_config.h" 17 #include "build/build_config.h"
18 #include "components/metrics/call_stack_profile_params.h" 18 #include "components/metrics/call_stack_profile_params.h"
19 #include "components/metrics/proto/chrome_user_metrics_extension.pb.h" 19 #include "components/metrics/proto/chrome_user_metrics_extension.pb.h"
20 #include "components/variations/entropy_provider.h" 20 #include "components/variations/entropy_provider.h"
21 #include "testing/gtest/include/gtest/gtest.h" 21 #include "testing/gtest/include/gtest/gtest.h"
22 22
23 using base::StackSamplingProfiler; 23 using base::StackSamplingProfiler;
24 using Frame = StackSamplingProfiler::Frame; 24 using Frame = StackSamplingProfiler::Frame;
25 using Module = StackSamplingProfiler::Module; 25 using Module = StackSamplingProfiler::Module;
26 using Profile = StackSamplingProfiler::CallStackProfile; 26 using Profile = StackSamplingProfiler::CallStackProfile;
27 using Profiles = StackSamplingProfiler::CallStackProfiles; 27 using Profiles = StackSamplingProfiler::CallStackProfiles;
28 using Sample = StackSamplingProfiler::Sample; 28 using Sample = StackSamplingProfiler::Sample;
29 29
30 namespace {
31
32 using ProfilesGenerator = uint64_t;
33
34 enum : ProfilesGenerator {
35 kEndOfGenerator,
36 kAddPhase,
37 kBeginActivity,
38 kEndActivity,
39 kNewProfile,
40 kNewSample,
41 kNextFrame,
42 kDefineModule,
43 };
44
45 struct ExpectedProtoModule {
46 const char* build_id;
47 uint64_t name_md5;
48 uint64_t base_address;
49 };
50
51 struct ExpectedProtoEntry {
52 int32_t module_index;
53 uint64_t address;
54 };
55
56 struct ExpectedProtoSample {
57 uint32_t process_phases; // Bit-field of expected phases.
58 uint32_t activities_begun; // Bit-field of expected activities begun.
59 uint32_t activities_ended; // Bit-field of expected activities ended.
60 const ExpectedProtoEntry* entries;
61 int entry_count;
62 int64_t entry_repeats;
63 };
64
65 struct ExpectedProtoProfile {
66 int32_t duration_ms;
67 int32_t period_ms;
68 const ExpectedProtoModule* modules;
69 int module_count;
70 const ExpectedProtoSample* samples;
71 int sample_count;
72 };
73
74 } // namespace
75
76 #define GEN_ADD_PHASE(phase) kAddPhase, phase
Alexei Svitkine (slow) 2016/11/07 23:22:07 What is this for? I don't see it being used.
bcwhite 2016/11/08 01:02:36 It's not... yet. It'll be needed when the remaini
77 #define GEN_BEGIN_ACTIVITY(activity) kBeginActivity, activity
78 #define GEN_END_ACTIVITY(activity) kEndActivity activity
79 #define GEN_NEW_PROFILE(duration_ms, interval_ms) \
80 kNewProfile, duration_ms, interval_ms
81 #define GEN_NEW_SAMPLE() kNewSample
82 #define GEN_FRAME(module, offset) kNextFrame, module, offset
83 #define GEN_DEFINE_MODULE(name, path, base) \
84 kDefineModule, reinterpret_cast<uintptr_t>(name), \
85 reinterpret_cast<uintptr_t>(&path), base
86 #define GEN_END() kEndOfGenerator
87
30 namespace metrics { 88 namespace metrics {
31 89
32 // This test fixture enables the field trial that 90 // This test fixture enables the field trial that
33 // CallStackProfileMetricsProvider depends on to report profiles. 91 // CallStackProfileMetricsProvider depends on to report profiles.
34 class CallStackProfileMetricsProviderTest : public testing::Test { 92 class CallStackProfileMetricsProviderTest : public testing::Test {
35 public: 93 public:
36 CallStackProfileMetricsProviderTest() 94 CallStackProfileMetricsProviderTest()
37 : field_trial_list_(nullptr) { 95 : field_trial_list_(nullptr) {
38 base::FieldTrialList::CreateFieldTrial( 96 base::FieldTrialList::CreateFieldTrial(
39 TestState::kFieldTrialName, 97 TestState::kFieldTrialName,
40 TestState::kReportProfilesGroupName); 98 TestState::kReportProfilesGroupName);
41 TestState::ResetStaticStateForTesting(); 99 TestState::ResetStaticStateForTesting();
42 } 100 }
43 101
44 ~CallStackProfileMetricsProviderTest() override {} 102 ~CallStackProfileMetricsProviderTest() override {}
45 103
46 // Utility function to append profiles to the metrics provider. 104 // Utility function to append profiles to the metrics provider.
47 void AppendProfiles(const CallStackProfileParams& params, Profiles profiles) { 105 void AppendProfiles(const CallStackProfileParams& params, Profiles profiles) {
48 CallStackProfileMetricsProvider::GetProfilerCallback(params).Run( 106 CallStackProfileMetricsProvider::GetProfilerCallback(params).Run(
49 std::move(profiles)); 107 std::move(profiles));
50 } 108 }
51 109
110 // Utility to create a Profiles list from a generator constant.
111 void GenerateProfiles(std::vector<Profile>* profiles,
112 const ProfilesGenerator* generator);
113
114 void VerifyProfileProto(const SampledProfile& proto,
115 const ExpectedProtoProfile& expected);
116
52 private: 117 private:
53 // Exposes field trial/group names from the CallStackProfileMetricsProvider. 118 // Exposes field trial/group names from the CallStackProfileMetricsProvider.
54 class TestState : public CallStackProfileMetricsProvider { 119 class TestState : public CallStackProfileMetricsProvider {
55 public: 120 public:
56 using CallStackProfileMetricsProvider::kFieldTrialName; 121 using CallStackProfileMetricsProvider::kFieldTrialName;
57 using CallStackProfileMetricsProvider::kReportProfilesGroupName; 122 using CallStackProfileMetricsProvider::kReportProfilesGroupName;
58 using CallStackProfileMetricsProvider::ResetStaticStateForTesting; 123 using CallStackProfileMetricsProvider::ResetStaticStateForTesting;
59 }; 124 };
60 125
61 base::FieldTrialList field_trial_list_; 126 base::FieldTrialList field_trial_list_;
62 127
63 DISALLOW_COPY_AND_ASSIGN(CallStackProfileMetricsProviderTest); 128 DISALLOW_COPY_AND_ASSIGN(CallStackProfileMetricsProviderTest);
64 }; 129 };
65 130
131 void CallStackProfileMetricsProviderTest::GenerateProfiles(
132 std::vector<Profile>* profiles,
133 const ProfilesGenerator* generator) {
134 uint32_t process_phases = 0;
135 uint32_t current_activities = 0;
136 Profile* profile = nullptr;
137
138 while (true) {
139 switch (*generator++) {
140 case kEndOfGenerator:
141 return;
142 case kAddPhase:
143 process_phases |= 1 << *generator++;
144 break;
145 case kBeginActivity:
146 current_activities |= 1 << *generator++;
147 break;
148 case kEndActivity:
149 current_activities &= ~(1 << *generator++);
150 break;
151 case kNewProfile:
152 profiles->push_back(Profile());
153 profile = &profiles->back();
154 profile->profile_duration =
155 base::TimeDelta::FromMilliseconds(*generator++);
156 profile->sampling_period =
157 base::TimeDelta::FromMilliseconds(*generator++);
158 break;
159 case kNewSample:
160 profile->samples.push_back(Sample());
161 break;
162 case kNextFrame: {
163 size_t index = static_cast<size_t>(*generator++);
164 uintptr_t address = static_cast<uintptr_t>(*generator++);
165 profile->samples.back().frames.push_back(Frame(address, index));
166 } break;
167 case kDefineModule: {
168 const char* name =
169 reinterpret_cast<const char*>(static_cast<uintptr_t>(*generator++));
170 const base::FilePath* path = reinterpret_cast<const base::FilePath*>(
171 static_cast<uintptr_t>(*generator++));
172 uintptr_t base = static_cast<uintptr_t>(*generator++);
173 profile->modules.push_back(Module(base, name, *path));
174 } break;
175 default:
176 NOTREACHED();
177 };
178 }
179 }
180
181 void CallStackProfileMetricsProviderTest::VerifyProfileProto(
182 const SampledProfile& proto,
183 const ExpectedProtoProfile& expected) {
184 ASSERT_TRUE(proto.has_call_stack_profile());
185 const CallStackProfile& stack = proto.call_stack_profile();
186
187 ASSERT_TRUE(stack.has_profile_duration_ms());
188 EXPECT_EQ(expected.duration_ms, stack.profile_duration_ms());
189 ASSERT_TRUE(stack.has_sampling_period_ms());
190 EXPECT_EQ(expected.period_ms, stack.sampling_period_ms());
191
192 ASSERT_EQ(expected.module_count, stack.module_id().size());
193 for (int m = 0; m < expected.module_count; ++m) {
194 SCOPED_TRACE("module " + base::IntToString(m));
195 const CallStackProfile::ModuleIdentifier& module_id =
196 stack.module_id().Get(m);
197 ASSERT_TRUE(module_id.has_build_id());
198 EXPECT_EQ(expected.modules[m].build_id, module_id.build_id());
199 ASSERT_TRUE(module_id.has_name_md5_prefix());
200 EXPECT_EQ(expected.modules[m].name_md5, module_id.name_md5_prefix());
201 }
202
203 ASSERT_EQ(expected.sample_count, stack.sample().size());
204 for (int s = 0; s < expected.sample_count; ++s) {
205 SCOPED_TRACE("sample " + base::IntToString(s));
206 const CallStackProfile::Sample& proto_sample = stack.sample().Get(s);
207
208 uint32_t process_phases = 0;
209 uint32_t activities_begun = 0;
210 uint32_t activities_ended = 0;
211 for (int i = 0; i < proto_sample.process_phase().size(); ++i)
212 process_phases |= 1U << proto_sample.process_phase().Get(i);
213 for (int i = 0; i < proto_sample.activity_begun().size(); ++i)
214 activities_begun |= 1U << proto_sample.activity_begun().Get(i);
215 for (int i = 0; i < proto_sample.activity_ended().size(); ++i)
216 activities_ended |= 1U << proto_sample.activity_ended().Get(i);
217 EXPECT_EQ(expected.samples[s].process_phases, process_phases);
218 EXPECT_EQ(expected.samples[s].activities_begun, activities_begun);
219 EXPECT_EQ(expected.samples[s].activities_ended, activities_ended);
220
221 ASSERT_EQ(expected.samples[s].entry_count, proto_sample.entry().size());
222 ASSERT_TRUE(proto_sample.has_count());
223 EXPECT_EQ(expected.samples[s].entry_repeats, proto_sample.count());
224 for (int e = 0; e < expected.samples[s].entry_count; ++e) {
225 SCOPED_TRACE("entry " + base::SizeTToString(e));
226 const CallStackProfile::Entry& entry = proto_sample.entry().Get(e);
227 ASSERT_TRUE(entry.has_module_id_index());
228 EXPECT_EQ(expected.samples[s].entries[e].module_index,
229 entry.module_id_index());
230 ASSERT_TRUE(entry.has_address());
231 EXPECT_EQ(expected.samples[s].entries[e].address, entry.address());
232 }
233 }
234 }
235
66 // Checks that all properties from multiple profiles are filled as expected. 236 // Checks that all properties from multiple profiles are filled as expected.
67 TEST_F(CallStackProfileMetricsProviderTest, MultipleProfiles) { 237 TEST_F(CallStackProfileMetricsProviderTest, MultipleProfiles) {
68 const uintptr_t module1_base_address = 0x1000; 238 const size_t profiles_count = 2;
69 const uintptr_t module2_base_address = 0x2000; 239 const uintptr_t moduleA_base_address = 0x1000;
70 const uintptr_t module3_base_address = 0x3000; 240 const uintptr_t moduleB_base_address = 0x2000;
71 241 const uintptr_t moduleC_base_address = 0x3000;
72 const Module profile_modules[][2] = { 242 const char* moduleA_name = "ABCD";
73 { 243 const char* moduleB_name = "EFGH";
74 Module( 244 const char* moduleC_name = "MNOP";
75 module1_base_address,
76 "ABCD",
77 #if defined(OS_WIN)
78 base::FilePath(L"c:\\some\\path\\to\\chrome.exe")
79 #else
80 base::FilePath("/some/path/to/chrome")
81 #endif
82 ),
83 Module(
84 module2_base_address,
85 "EFGH",
86 #if defined(OS_WIN)
87 base::FilePath(L"c:\\some\\path\\to\\third_party.dll")
88 #else
89 base::FilePath("/some/path/to/third_party.so")
90 #endif
91 ),
92 },
93 {
94 Module(
95 module3_base_address,
96 "MNOP",
97 #if defined(OS_WIN)
98 base::FilePath(L"c:\\some\\path\\to\\third_party2.dll")
99 #else
100 base::FilePath("/some/path/to/third_party2.so")
101 #endif
102 ),
103 Module( // Repeated from the first profile.
104 module1_base_address,
105 "ABCD",
106 #if defined(OS_WIN)
107 base::FilePath(L"c:\\some\\path\\to\\chrome.exe")
108 #else
109 base::FilePath("/some/path/to/chrome")
110 #endif
111 )
112 }
113 };
114 245
115 // Values for Windows generated with: 246 // Values for Windows generated with:
116 // perl -MDigest::MD5=md5 -MEncode=encode 247 // perl -MDigest::MD5=md5 -MEncode=encode
117 // -e 'for(@ARGV){printf "%x\n", unpack "Q>", md5 encode "UTF-16LE", $_}' 248 // -e 'for(@ARGV){printf "%x\n", unpack "Q>", md5 encode "UTF-16LE", $_}'
118 // chrome.exe third_party.dll third_party2.dll 249 // chrome.exe third_party.dll third_party2.dll
119 // 250 //
120 // Values for Linux generated with: 251 // Values for Linux generated with:
121 // perl -MDigest::MD5=md5 252 // perl -MDigest::MD5=md5
122 // -e 'for(@ARGV){printf "%x\n", unpack "Q>", md5 $_}' 253 // -e 'for(@ARGV){printf "%x\n", unpack "Q>", md5 $_}'
123 // chrome third_party.so third_party2.so 254 // chrome third_party.so third_party2.so
124 const uint64_t profile_expected_name_md5_prefixes[][2] = {
125 {
126 #if defined(OS_WIN) 255 #if defined(OS_WIN)
127 0x46c3e4166659ac02ULL, 0x7e2b8bfddeae1abaULL 256 uint64_t moduleA_md5 = 0x46C3E4166659AC02ULL;
257 uint64_t moduleB_md5 = 0x7E2B8BFDDEAE1ABAULL;
258 uint64_t moduleC_md5 = 0x87B66F4573A4D5CAULL;
259 base::FilePath moduleA_path(L"c:\\some\\path\\to\\chrome.exe");
260 base::FilePath moduleB_path(L"c:\\some\\path\\to\\third_party.dll");
261 base::FilePath moduleC_path(L"c:\\some\\path\\to\\third_party2.dll");
128 #else 262 #else
129 0x554838a8451ac36cUL, 0x843661148659c9f8UL 263 uint64_t moduleA_md5 = 0x554838A8451AC36CULL;
264 uint64_t moduleB_md5 = 0x843661148659C9F8ULL;
265 uint64_t moduleC_md5 = 0xB4647E539FA6EC9EULL;
266 base::FilePath moduleA_path("/some/path/to/chrome");
267 base::FilePath moduleB_path("/some/path/to/third_party.so");
268 base::FilePath moduleC_path("/some/path/to/third_party2.so");
130 #endif 269 #endif
131 },
132 {
133 #if defined(OS_WIN)
134 0x87b66f4573a4d5caULL, 0x46c3e4166659ac02ULL
135 #else
136 0xb4647e539fa6ec9eUL, 0x554838a8451ac36cUL
137 #endif
138 }};
139 270
140 // Represents two stack samples for each of two profiles, where each stack 271 // Represents two stack samples for each of two profiles, where each stack
141 // contains three frames. Each frame contains an instruction pointer and a 272 // contains three frames. Each frame contains an instruction pointer and a
142 // module index corresponding to the module for the profile in 273 // module index corresponding to the module for the profile in
143 // profile_modules. 274 // profile_modules.
144 // 275 //
145 // So, the first stack sample below has its top frame in module 0 at an offset 276 // So, the first stack sample below has its top frame in module 0 at an offset
146 // of 0x10 from the module's base address, the next-to-top frame in module 1 277 // of 0x10 from the module's base address, the next-to-top frame in module 1
147 // at an offset of 0x20 from the module's base address, and the bottom frame 278 // at an offset of 0x20 from the module's base address, and the bottom frame
148 // in module 0 at an offset of 0x30 from the module's base address 279 // in module 0 at an offset of 0x30 from the module's base address
149 const Frame profile_sample_frames[][2][3] = { 280 const ProfilesGenerator test_profiles_generator[] = {
150 { 281 GEN_NEW_PROFILE(100, 10),
282 GEN_DEFINE_MODULE(moduleA_name, moduleA_path, moduleA_base_address),
283 GEN_DEFINE_MODULE(moduleB_name, moduleB_path, moduleB_base_address),
284
285 GEN_NEW_SAMPLE(),
286 GEN_FRAME(0, moduleA_base_address + 0x10),
287 GEN_FRAME(1, moduleB_base_address + 0x20),
288 GEN_FRAME(0, moduleA_base_address + 0x30),
289 GEN_NEW_SAMPLE(),
290 GEN_FRAME(1, moduleB_base_address + 0x10),
291 GEN_FRAME(0, moduleA_base_address + 0x20),
292 GEN_FRAME(1, moduleB_base_address + 0x30),
293
294 GEN_NEW_PROFILE(200, 20),
295 GEN_DEFINE_MODULE(moduleC_name, moduleC_path, moduleC_base_address),
296 GEN_DEFINE_MODULE(moduleA_name, moduleA_path, moduleA_base_address),
297
298 GEN_NEW_SAMPLE(),
299 GEN_FRAME(0, moduleC_base_address + 0x10),
300 GEN_FRAME(1, moduleA_base_address + 0x20),
301 GEN_FRAME(0, moduleC_base_address + 0x30),
302 GEN_NEW_SAMPLE(),
303 GEN_FRAME(1, moduleA_base_address + 0x10),
304 GEN_FRAME(0, moduleC_base_address + 0x20),
305 GEN_FRAME(1, moduleA_base_address + 0x30),
306
307 GEN_END(),
308 };
309
310 const ExpectedProtoModule expected_proto_modules1[] = {
311 { moduleA_name, moduleA_md5, moduleA_base_address },
312 { moduleB_name, moduleB_md5, moduleB_base_address }
313 };
314
315 const ExpectedProtoEntry expected_proto_entries11[] = {
316 {0, 0x10},
317 {1, 0x20},
318 {0, 0x30},
319 };
320 const ExpectedProtoEntry expected_proto_entries12[] = {
321 {1, 0x10},
322 {0, 0x20},
323 {1, 0x30},
324 };
325 const ExpectedProtoSample expected_proto_samples1[] = {
151 { 326 {
152 Frame(module1_base_address + 0x10, 0), 327 0, 0, 0,
153 Frame(module2_base_address + 0x20, 1), 328 expected_proto_entries11, arraysize(expected_proto_entries11), 1,
154 Frame(module1_base_address + 0x30, 0)
155 }, 329 },
156 { 330 {
157 Frame(module2_base_address + 0x10, 1), 331 0, 0, 0,
158 Frame(module1_base_address + 0x20, 0), 332 expected_proto_entries12, arraysize(expected_proto_entries12), 1,
159 Frame(module2_base_address + 0x30, 1) 333 },
160 } 334 };
161 }, 335
162 { 336 const ExpectedProtoModule expected_proto_modules2[] = {
337 { moduleC_name, moduleC_md5, moduleC_base_address },
338 { moduleA_name, moduleA_md5, moduleA_base_address }
339 };
340
341 const ExpectedProtoEntry expected_proto_entries21[] = {
342 {0, 0x10},
343 {1, 0x20},
344 {0, 0x30},
345 };
346 const ExpectedProtoEntry expected_proto_entries22[] = {
347 {1, 0x10},
348 {0, 0x20},
349 {1, 0x30},
350 };
351 const ExpectedProtoSample expected_proto_samples2[] = {
163 { 352 {
164 Frame(module3_base_address + 0x10, 0), 353 0, 0, 0,
165 Frame(module1_base_address + 0x20, 1), 354 expected_proto_entries11, arraysize(expected_proto_entries21), 1,
166 Frame(module3_base_address + 0x30, 0)
167 }, 355 },
168 { 356 {
169 Frame(module1_base_address + 0x10, 1), 357 0, 0, 0,
170 Frame(module3_base_address + 0x20, 0), 358 expected_proto_entries12, arraysize(expected_proto_entries22), 1,
171 Frame(module1_base_address + 0x30, 1) 359 },
172 }
173 }
174 }; 360 };
175 361
176 base::TimeDelta profile_durations[2] = { 362 const ExpectedProtoProfile expected_proto_profiles[] = {
177 base::TimeDelta::FromMilliseconds(100), 363 {
178 base::TimeDelta::FromMilliseconds(200) 364 100, 10,
179 }; 365 expected_proto_modules1, arraysize(expected_proto_modules1),
180 366 expected_proto_samples1, arraysize(expected_proto_samples1),
181 base::TimeDelta profile_sampling_periods[2] = { 367 },
182 base::TimeDelta::FromMilliseconds(10), 368 {
183 base::TimeDelta::FromMilliseconds(20) 369 200, 20,
370 expected_proto_modules2, arraysize(expected_proto_modules2),
371 expected_proto_samples2, arraysize(expected_proto_samples2),
372 },
184 }; 373 };
185 374
186 std::vector<Profile> profiles; 375 std::vector<Profile> profiles;
187 for (size_t i = 0; i < arraysize(profile_sample_frames); ++i) { 376 GenerateProfiles(&profiles, test_profiles_generator);
188 Profile profile; 377 ASSERT_EQ(profiles_count, profiles.size());
189 profile.modules.insert(
190 profile.modules.end(), &profile_modules[i][0],
191 &profile_modules[i][0] + arraysize(profile_modules[i]));
192
193 for (size_t j = 0; j < arraysize(profile_sample_frames[i]); ++j) {
194 profile.samples.push_back(Sample());
195 Sample& sample = profile.samples.back();
196 sample.insert(sample.end(), &profile_sample_frames[i][j][0],
197 &profile_sample_frames[i][j][0] +
198 arraysize(profile_sample_frames[i][j]));
199 }
200
201 profile.profile_duration = profile_durations[i];
202 profile.sampling_period = profile_sampling_periods[i];
203
204 profiles.push_back(std::move(profile));
205 }
206 378
207 CallStackProfileMetricsProvider provider; 379 CallStackProfileMetricsProvider provider;
208 provider.OnRecordingEnabled(); 380 provider.OnRecordingEnabled();
209 AppendProfiles( 381 AppendProfiles(
210 CallStackProfileParams(CallStackProfileParams::BROWSER_PROCESS, 382 CallStackProfileParams(CallStackProfileParams::BROWSER_PROCESS,
211 CallStackProfileParams::UI_THREAD, 383 CallStackProfileParams::UI_THREAD,
212 CallStackProfileParams::PROCESS_STARTUP, 384 CallStackProfileParams::PROCESS_STARTUP,
213 CallStackProfileParams::MAY_SHUFFLE), 385 CallStackProfileParams::MAY_SHUFFLE),
214 std::move(profiles)); 386 std::move(profiles));
215 ChromeUserMetricsExtension uma_proto; 387 ChromeUserMetricsExtension uma_proto;
216 provider.ProvideGeneralMetrics(&uma_proto); 388 provider.ProvideGeneralMetrics(&uma_proto);
217 389
218 ASSERT_EQ(static_cast<int>(arraysize(profile_sample_frames)), 390 ASSERT_EQ(static_cast<int>(profiles_count),
219 uma_proto.sampled_profile().size()); 391 uma_proto.sampled_profile().size());
220 for (size_t i = 0; i < arraysize(profile_sample_frames); ++i) { 392 for (size_t p = 0; p < profiles_count; ++p) {
221 SCOPED_TRACE("profile " + base::SizeTToString(i)); 393 SCOPED_TRACE("profile " + base::SizeTToString(p));
222 const SampledProfile& sampled_profile = uma_proto.sampled_profile().Get(i); 394 VerifyProfileProto(uma_proto.sampled_profile().Get(p),
223 ASSERT_TRUE(sampled_profile.has_call_stack_profile()); 395 expected_proto_profiles[p]);
224 const CallStackProfile& call_stack_profile =
225 sampled_profile.call_stack_profile();
226
227 ASSERT_EQ(static_cast<int>(arraysize(profile_sample_frames[i])),
228 call_stack_profile.sample().size());
229 for (size_t j = 0; j < arraysize(profile_sample_frames[i]); ++j) {
230 SCOPED_TRACE("sample " + base::SizeTToString(j));
231 const CallStackProfile::Sample& proto_sample =
232 call_stack_profile.sample().Get(j);
233 ASSERT_EQ(static_cast<int>(arraysize(profile_sample_frames[i][j])),
234 proto_sample.entry().size());
235 ASSERT_TRUE(proto_sample.has_count());
236 EXPECT_EQ(1u, proto_sample.count());
237 for (size_t k = 0; k < arraysize(profile_sample_frames[i][j]); ++k) {
238 SCOPED_TRACE("frame " + base::SizeTToString(k));
239 const CallStackProfile::Entry& entry = proto_sample.entry().Get(k);
240 ASSERT_TRUE(entry.has_address());
241 const char* instruction_pointer = reinterpret_cast<const char*>(
242 profile_sample_frames[i][j][k].instruction_pointer);
243 const char* module_base_address = reinterpret_cast<const char*>(
244 profile_modules[i][profile_sample_frames[i][j][k].module_index]
245 .base_address);
246 EXPECT_EQ(
247 static_cast<uint64_t>(instruction_pointer - module_base_address),
248 entry.address());
249 ASSERT_TRUE(entry.has_module_id_index());
250 EXPECT_EQ(profile_sample_frames[i][j][k].module_index,
251 static_cast<size_t>(entry.module_id_index()));
252 }
253 }
254
255 ASSERT_EQ(static_cast<int>(arraysize(profile_modules[i])),
256 call_stack_profile.module_id().size());
257 for (size_t j = 0; j < arraysize(profile_modules[i]); ++j) {
258 SCOPED_TRACE("module " + base::SizeTToString(j));
259 const CallStackProfile::ModuleIdentifier& module_identifier =
260 call_stack_profile.module_id().Get(j);
261 ASSERT_TRUE(module_identifier.has_build_id());
262 EXPECT_EQ(profile_modules[i][j].id, module_identifier.build_id());
263 ASSERT_TRUE(module_identifier.has_name_md5_prefix());
264 EXPECT_EQ(profile_expected_name_md5_prefixes[i][j],
265 module_identifier.name_md5_prefix());
266 }
267
268 ASSERT_TRUE(call_stack_profile.has_profile_duration_ms());
269 EXPECT_EQ(profile_durations[i].InMilliseconds(),
270 call_stack_profile.profile_duration_ms());
271 ASSERT_TRUE(call_stack_profile.has_sampling_period_ms());
272 EXPECT_EQ(profile_sampling_periods[i].InMilliseconds(),
273 call_stack_profile.sampling_period_ms());
274 ASSERT_TRUE(sampled_profile.has_process());
275 EXPECT_EQ(BROWSER_PROCESS, sampled_profile.process());
276 ASSERT_TRUE(sampled_profile.has_thread());
277 EXPECT_EQ(UI_THREAD, sampled_profile.thread());
278 ASSERT_TRUE(sampled_profile.has_trigger_event());
279 EXPECT_EQ(SampledProfile::PROCESS_STARTUP, sampled_profile.trigger_event());
280 } 396 }
281 } 397 }
282 398
283 // Checks that all duplicate samples are collapsed with 399 // Checks that all duplicate samples are collapsed with
284 // preserve_sample_ordering = false. 400 // preserve_sample_ordering = false.
285 TEST_F(CallStackProfileMetricsProviderTest, RepeatedStacksUnordered) { 401 TEST_F(CallStackProfileMetricsProviderTest, RepeatedStacksUnordered) {
286 const uintptr_t module_base_address = 0x1000; 402 const uintptr_t module_base_address = 0x1000;
287 403
288 const Module modules[] = { 404 const Module modules[] = {
289 Module( 405 Module(
290 module_base_address, 406 module_base_address,
291 "ABCD", 407 "ABCD",
292 #if defined(OS_WIN) 408 #if defined(OS_WIN)
293 base::FilePath(L"c:\\some\\path\\to\\chrome.exe") 409 base::FilePath(L"c:\\some\\path\\to\\chrome.exe")
294 #else 410 #else
295 base::FilePath("/some/path/to/chrome") 411 base::FilePath("/some/path/to/chrome")
296 #endif 412 #endif
297 ) 413 )
298 }; 414 };
299 415
300 // Duplicate samples in slots 0, 2, and 3. 416 // Samples are unique only if the phase, activity, and frame all match.
417 const uint32_t profile_phases_and_activities[][2] = {
418 { 1, 0 },
419 { 1, 0 },
420 { 3, 0 },
421 { 3, 0 },
422 { 3, 1 },
423 // Unique above, duplicates below.
424 { 1, 0 },
425 { 1, 0 },
426 { 3, 0 },
427 };
301 const Frame sample_frames[][1] = { 428 const Frame sample_frames[][1] = {
302 { Frame(module_base_address + 0x10, 0), }, 429 { Frame(module_base_address + 0x10, 0), },
303 { Frame(module_base_address + 0x20, 0), }, 430 { Frame(module_base_address + 0x20, 0), },
304 { Frame(module_base_address + 0x10, 0), }, 431 { Frame(module_base_address + 0x10, 0), },
305 { Frame(module_base_address + 0x10, 0) } 432 { Frame(module_base_address + 0x20, 0), },
433 { Frame(module_base_address + 0x10, 0), },
434 // Unique above, duplicates below.
435 { Frame(module_base_address + 0x10, 0), },
436 { Frame(module_base_address + 0x10, 0), },
437 { Frame(module_base_address + 0x10, 0), },
438 };
439
440 const int duplicate_counts[] = {
441 3, 1, 2, 1, 1,
306 }; 442 };
307 443
308 Profile profile; 444 Profile profile;
309 profile.modules.insert(profile.modules.end(), &modules[0], 445 profile.modules.insert(profile.modules.end(), &modules[0],
310 &modules[0] + arraysize(modules)); 446 &modules[0] + arraysize(modules));
311 447
312 for (size_t i = 0; i < arraysize(sample_frames); ++i) { 448 for (size_t i = 0; i < arraysize(sample_frames); ++i) {
313 profile.samples.push_back(Sample()); 449 profile.samples.push_back(Sample());
314 Sample& sample = profile.samples.back(); 450 Sample& sample = profile.samples.back();
315 sample.insert(sample.end(), &sample_frames[i][0], 451 sample.process_phases = profile_phases_and_activities[i][0];
316 &sample_frames[i][0] + arraysize(sample_frames[i])); 452 sample.current_activities = profile_phases_and_activities[i][1];
453 sample.frames.insert(sample.frames.end(), &sample_frames[i][0],
454 &sample_frames[i][0] + arraysize(sample_frames[i]));
317 } 455 }
318 456
319 profile.profile_duration = base::TimeDelta::FromMilliseconds(100); 457 profile.profile_duration = base::TimeDelta::FromMilliseconds(100);
320 profile.sampling_period = base::TimeDelta::FromMilliseconds(10); 458 profile.sampling_period = base::TimeDelta::FromMilliseconds(10);
321 Profiles profiles; 459 Profiles profiles;
322 profiles.push_back(std::move(profile)); 460 profiles.push_back(std::move(profile));
323 461
324 CallStackProfileMetricsProvider provider; 462 CallStackProfileMetricsProvider provider;
325 provider.OnRecordingEnabled(); 463 provider.OnRecordingEnabled();
326 AppendProfiles( 464 AppendProfiles(
327 CallStackProfileParams(CallStackProfileParams::BROWSER_PROCESS, 465 CallStackProfileParams(CallStackProfileParams::BROWSER_PROCESS,
328 CallStackProfileParams::UI_THREAD, 466 CallStackProfileParams::UI_THREAD,
329 CallStackProfileParams::PROCESS_STARTUP, 467 CallStackProfileParams::PROCESS_STARTUP,
330 CallStackProfileParams::MAY_SHUFFLE), 468 CallStackProfileParams::MAY_SHUFFLE),
331 std::move(profiles)); 469 std::move(profiles));
332 ChromeUserMetricsExtension uma_proto; 470 ChromeUserMetricsExtension uma_proto;
333 provider.ProvideGeneralMetrics(&uma_proto); 471 provider.ProvideGeneralMetrics(&uma_proto);
334 472
335 ASSERT_EQ(1, uma_proto.sampled_profile().size()); 473 ASSERT_EQ(1, uma_proto.sampled_profile().size());
336 const SampledProfile& sampled_profile = uma_proto.sampled_profile().Get(0); 474 const SampledProfile& sampled_profile = uma_proto.sampled_profile().Get(0);
337 ASSERT_TRUE(sampled_profile.has_call_stack_profile()); 475 ASSERT_TRUE(sampled_profile.has_call_stack_profile());
338 const CallStackProfile& call_stack_profile = 476 const CallStackProfile& call_stack_profile =
339 sampled_profile.call_stack_profile(); 477 sampled_profile.call_stack_profile();
340 478
341 ASSERT_EQ(2, call_stack_profile.sample().size()); 479 ASSERT_EQ(static_cast<int>(arraysize(duplicate_counts)),
342 for (int i = 0; i < 2; ++i) { 480 call_stack_profile.sample().size());
343 SCOPED_TRACE("sample " + base::IntToString(i)); 481 for (size_t i = 0; i < arraysize(duplicate_counts); ++i) {
482 SCOPED_TRACE("sample " + base::SizeTToString(i));
344 const CallStackProfile::Sample& proto_sample = 483 const CallStackProfile::Sample& proto_sample =
345 call_stack_profile.sample().Get(i); 484 call_stack_profile.sample().Get(i);
485
486 // For MAY_SHUFFLE, these are reset with every sample.
487 uint32_t process_phase = 0;
488 uint32_t current_activities = 0;
489
346 ASSERT_EQ(static_cast<int>(arraysize(sample_frames[i])), 490 ASSERT_EQ(static_cast<int>(arraysize(sample_frames[i])),
347 proto_sample.entry().size()); 491 proto_sample.entry().size());
348 ASSERT_TRUE(proto_sample.has_count()); 492 ASSERT_TRUE(proto_sample.has_count());
349 EXPECT_EQ(i == 0 ? 3u : 1u, proto_sample.count()); 493 EXPECT_EQ(duplicate_counts[i], proto_sample.count());
350 for (size_t j = 0; j < arraysize(sample_frames[i]); ++j) { 494 for (size_t j = 0; j < arraysize(sample_frames[i]); ++j) {
351 SCOPED_TRACE("frame " + base::SizeTToString(j)); 495 SCOPED_TRACE("frame " + base::SizeTToString(j));
352 const CallStackProfile::Entry& entry = proto_sample.entry().Get(j); 496 const CallStackProfile::Entry& entry = proto_sample.entry().Get(j);
353 ASSERT_TRUE(entry.has_address()); 497 ASSERT_TRUE(entry.has_address());
354 const char* instruction_pointer = reinterpret_cast<const char*>( 498 const char* instruction_pointer = reinterpret_cast<const char*>(
355 sample_frames[i][j].instruction_pointer); 499 sample_frames[i][j].instruction_pointer);
356 const char* module_base_address = reinterpret_cast<const char*>( 500 const char* module_base_address = reinterpret_cast<const char*>(
357 modules[sample_frames[i][j].module_index].base_address); 501 modules[sample_frames[i][j].module_index].base_address);
358 EXPECT_EQ( 502 EXPECT_EQ(
359 static_cast<uint64_t>(instruction_pointer - module_base_address), 503 static_cast<uint64_t>(instruction_pointer - module_base_address),
360 entry.address()); 504 entry.address());
361 ASSERT_TRUE(entry.has_module_id_index()); 505 ASSERT_TRUE(entry.has_module_id_index());
362 EXPECT_EQ(sample_frames[i][j].module_index, 506 EXPECT_EQ(sample_frames[i][j].module_index,
363 static_cast<size_t>(entry.module_id_index())); 507 static_cast<size_t>(entry.module_id_index()));
364 } 508 }
509
510 for (int x = 0; x < proto_sample.process_phase_size(); ++x) {
511 process_phase |= 1 << proto_sample.process_phase(x);
512 }
513 EXPECT_EQ(profile_phases_and_activities[i][0], process_phase);
514
515 for (int x = 0; x < proto_sample.activity_begun_size(); ++x) {
516 current_activities |= 1 << proto_sample.activity_begun(x);
517 }
518 for (int x = 0; x < proto_sample.activity_ended_size(); ++x) {
519 current_activities &= ~(1 << proto_sample.activity_ended(x));
520 }
521 EXPECT_EQ(profile_phases_and_activities[i][1], current_activities);
365 } 522 }
366 } 523 }
367 524
368 // Checks that only contiguous duplicate samples are collapsed with 525 // Checks that only contiguous duplicate samples are collapsed with
369 // preserve_sample_ordering = true. 526 // preserve_sample_ordering = true.
370 TEST_F(CallStackProfileMetricsProviderTest, RepeatedStacksOrdered) { 527 TEST_F(CallStackProfileMetricsProviderTest, RepeatedStacksOrdered) {
371 const uintptr_t module_base_address = 0x1000; 528 const uintptr_t module_base_address = 0x1000;
372 529
373 const Module modules[] = { 530 const Module modules[] = {
374 Module( 531 Module(
375 module_base_address, 532 module_base_address,
376 "ABCD", 533 "ABCD",
377 #if defined(OS_WIN) 534 #if defined(OS_WIN)
378 base::FilePath(L"c:\\some\\path\\to\\chrome.exe") 535 base::FilePath(L"c:\\some\\path\\to\\chrome.exe")
379 #else 536 #else
380 base::FilePath("/some/path/to/chrome") 537 base::FilePath("/some/path/to/chrome")
381 #endif 538 #endif
382 ) 539 )
383 }; 540 };
384 541
385 // Duplicate samples in slots 0, 2, and 3. 542 // Samples are unique only if the phase, activity, and frame all match.
543 const uint32_t profile_phases_and_activities[][2] = {
544 { 1, 0 },
545 { 1, 0 },
546 { 1, 0 },
547 { 1, 0 },
548
549 { 3, 0 },
550 { 3, 1 },
551 { 3, 0 },
552 { 3, 0 },
553 };
386 const Frame sample_frames[][1] = { 554 const Frame sample_frames[][1] = {
387 { Frame(module_base_address + 0x10, 0), }, 555 { Frame(module_base_address + 0x10, 0), },
388 { Frame(module_base_address + 0x20, 0), }, 556 { Frame(module_base_address + 0x20, 0), },
389 { Frame(module_base_address + 0x10, 0), }, 557 { Frame(module_base_address + 0x10, 0), },
390 { Frame(module_base_address + 0x10, 0) } 558 { Frame(module_base_address + 0x10, 0), },
559
560 { Frame(module_base_address + 0x10, 0), },
561 { Frame(module_base_address + 0x20, 0), },
562 { Frame(module_base_address + 0x10, 0), },
563 { Frame(module_base_address + 0x10, 0), },
564 };
565
566 const int duplicate_counts[] = {
567 1, 1, 2, 1, 1, 2
391 }; 568 };
392 569
393 Profile profile; 570 Profile profile;
394 profile.modules.insert(profile.modules.end(), &modules[0], 571 profile.modules.insert(profile.modules.end(), &modules[0],
395 &modules[0] + arraysize(modules)); 572 &modules[0] + arraysize(modules));
396 573
397 for (size_t i = 0; i < arraysize(sample_frames); ++i) { 574 for (size_t i = 0; i < arraysize(sample_frames); ++i) {
398 profile.samples.push_back(Sample()); 575 profile.samples.push_back(Sample());
399 Sample& sample = profile.samples.back(); 576 Sample& sample = profile.samples.back();
400 sample.insert(sample.end(), &sample_frames[i][0], 577 sample.process_phases = profile_phases_and_activities[i][0];
401 &sample_frames[i][0] + arraysize(sample_frames[i])); 578 sample.current_activities = profile_phases_and_activities[i][1];
579 sample.frames.insert(sample.frames.end(), &sample_frames[i][0],
580 &sample_frames[i][0] + arraysize(sample_frames[i]));
402 } 581 }
403 582
404 profile.profile_duration = base::TimeDelta::FromMilliseconds(100); 583 profile.profile_duration = base::TimeDelta::FromMilliseconds(100);
405 profile.sampling_period = base::TimeDelta::FromMilliseconds(10); 584 profile.sampling_period = base::TimeDelta::FromMilliseconds(10);
406 Profiles profiles; 585 Profiles profiles;
407 profiles.push_back(std::move(profile)); 586 profiles.push_back(std::move(profile));
408 587
409 CallStackProfileMetricsProvider provider; 588 CallStackProfileMetricsProvider provider;
410 provider.OnRecordingEnabled(); 589 provider.OnRecordingEnabled();
411 AppendProfiles(CallStackProfileParams(CallStackProfileParams::BROWSER_PROCESS, 590 AppendProfiles(CallStackProfileParams(CallStackProfileParams::BROWSER_PROCESS,
412 CallStackProfileParams::UI_THREAD, 591 CallStackProfileParams::UI_THREAD,
413 CallStackProfileParams::PROCESS_STARTUP, 592 CallStackProfileParams::PROCESS_STARTUP,
414 CallStackProfileParams::PRESERVE_ORDER), 593 CallStackProfileParams::PRESERVE_ORDER),
415 std::move(profiles)); 594 std::move(profiles));
416 ChromeUserMetricsExtension uma_proto; 595 ChromeUserMetricsExtension uma_proto;
417 provider.ProvideGeneralMetrics(&uma_proto); 596 provider.ProvideGeneralMetrics(&uma_proto);
418 597
419 ASSERT_EQ(1, uma_proto.sampled_profile().size()); 598 ASSERT_EQ(1, uma_proto.sampled_profile().size());
420 const SampledProfile& sampled_profile = uma_proto.sampled_profile().Get(0); 599 const SampledProfile& sampled_profile = uma_proto.sampled_profile().Get(0);
421 ASSERT_TRUE(sampled_profile.has_call_stack_profile()); 600 ASSERT_TRUE(sampled_profile.has_call_stack_profile());
422 const CallStackProfile& call_stack_profile = 601 const CallStackProfile& call_stack_profile =
423 sampled_profile.call_stack_profile(); 602 sampled_profile.call_stack_profile();
424 603
425 ASSERT_EQ(3, call_stack_profile.sample().size()); 604 // For PRESERVE_ORDER, these are reset with every profile.
426 for (int i = 0; i < 3; ++i) { 605 uint32_t process_phase = 0;
427 SCOPED_TRACE("sample " + base::IntToString(i)); 606 uint32_t current_activities = 0;
607
608 ASSERT_EQ(static_cast<int>(arraysize(duplicate_counts)),
609 call_stack_profile.sample().size());
610 for (size_t i = 0, d = 0; i < arraysize(duplicate_counts);
611 d += duplicate_counts[i], ++i) {
612 // |d| is the index after compensating for duplicate compression.
613 SCOPED_TRACE("sample " + base::SizeTToString(i));
428 const CallStackProfile::Sample& proto_sample = 614 const CallStackProfile::Sample& proto_sample =
429 call_stack_profile.sample().Get(i); 615 call_stack_profile.sample().Get(i);
430 ASSERT_EQ(static_cast<int>(arraysize(sample_frames[i])), 616 ASSERT_EQ(static_cast<int>(arraysize(sample_frames[i])),
431 proto_sample.entry().size()); 617 proto_sample.entry().size());
432 ASSERT_TRUE(proto_sample.has_count()); 618 ASSERT_TRUE(proto_sample.has_count());
433 EXPECT_EQ(i == 2 ? 2u : 1u, proto_sample.count()); 619 EXPECT_EQ(duplicate_counts[i], proto_sample.count());
434 for (size_t j = 0; j < arraysize(sample_frames[i]); ++j) { 620 for (size_t j = 0; j < arraysize(sample_frames[d]); ++j) {
435 SCOPED_TRACE("frame " + base::SizeTToString(j)); 621 SCOPED_TRACE("frame " + base::SizeTToString(j));
436 const CallStackProfile::Entry& entry = proto_sample.entry().Get(j); 622 const CallStackProfile::Entry& entry = proto_sample.entry().Get(j);
437 ASSERT_TRUE(entry.has_address()); 623 ASSERT_TRUE(entry.has_address());
438 const char* instruction_pointer = reinterpret_cast<const char*>( 624 const char* instruction_pointer = reinterpret_cast<const char*>(
439 sample_frames[i][j].instruction_pointer); 625 sample_frames[d][j].instruction_pointer);
440 const char* module_base_address = reinterpret_cast<const char*>( 626 const char* module_base_address = reinterpret_cast<const char*>(
441 modules[sample_frames[i][j].module_index].base_address); 627 modules[sample_frames[d][j].module_index].base_address);
442 EXPECT_EQ( 628 EXPECT_EQ(
443 static_cast<uint64_t>(instruction_pointer - module_base_address), 629 static_cast<uint64_t>(instruction_pointer - module_base_address),
444 entry.address()); 630 entry.address());
445 ASSERT_TRUE(entry.has_module_id_index()); 631 ASSERT_TRUE(entry.has_module_id_index());
446 EXPECT_EQ(sample_frames[i][j].module_index, 632 EXPECT_EQ(sample_frames[d][j].module_index,
447 static_cast<size_t>(entry.module_id_index())); 633 static_cast<size_t>(entry.module_id_index()));
448 } 634 }
635
636 for (int x = 0; x < proto_sample.process_phase_size(); ++x) {
637 process_phase |= 1 << proto_sample.process_phase(x);
638 }
639 EXPECT_EQ(profile_phases_and_activities[d][0], process_phase);
640
641 for (int x = 0; x < proto_sample.activity_begun_size(); ++x) {
642 current_activities |= 1 << proto_sample.activity_begun(x);
643 }
644 for (int x = 0; x < proto_sample.activity_ended_size(); ++x) {
645 current_activities &= ~(1 << proto_sample.activity_ended(x));
646 }
647 EXPECT_EQ(profile_phases_and_activities[d][1], current_activities);
449 } 648 }
450 } 649 }
451 650
452 // Checks that unknown modules produce an empty Entry. 651 // Checks that unknown modules produce an empty Entry.
453 TEST_F(CallStackProfileMetricsProviderTest, UnknownModule) { 652 TEST_F(CallStackProfileMetricsProviderTest, UnknownModule) {
454 const Frame frame(0x1000, Frame::kUnknownModuleIndex);
455
456 Profile profile; 653 Profile profile;
457 654 profile.samples.push_back(Sample(Frame(0x1000, Frame::kUnknownModuleIndex)));
458 profile.samples.push_back(Sample(1, frame));
459
460 profile.profile_duration = base::TimeDelta::FromMilliseconds(100); 655 profile.profile_duration = base::TimeDelta::FromMilliseconds(100);
461 profile.sampling_period = base::TimeDelta::FromMilliseconds(10); 656 profile.sampling_period = base::TimeDelta::FromMilliseconds(10);
462 Profiles profiles; 657 Profiles profiles;
463 profiles.push_back(std::move(profile)); 658 profiles.push_back(std::move(profile));
464 659
465 CallStackProfileMetricsProvider provider; 660 CallStackProfileMetricsProvider provider;
466 provider.OnRecordingEnabled(); 661 provider.OnRecordingEnabled();
467 AppendProfiles( 662 AppendProfiles(
468 CallStackProfileParams(CallStackProfileParams::BROWSER_PROCESS, 663 CallStackProfileParams(CallStackProfileParams::BROWSER_PROCESS,
469 CallStackProfileParams::UI_THREAD, 664 CallStackProfileParams::UI_THREAD,
(...skipping 20 matching lines...) Expand all
490 EXPECT_FALSE(entry.has_module_id_index()); 685 EXPECT_FALSE(entry.has_module_id_index());
491 } 686 }
492 687
493 // Checks that pending profiles are only passed back to ProvideGeneralMetrics 688 // Checks that pending profiles are only passed back to ProvideGeneralMetrics
494 // once. 689 // once.
495 TEST_F(CallStackProfileMetricsProviderTest, ProfilesProvidedOnlyOnce) { 690 TEST_F(CallStackProfileMetricsProviderTest, ProfilesProvidedOnlyOnce) {
496 CallStackProfileMetricsProvider provider; 691 CallStackProfileMetricsProvider provider;
497 for (int i = 0; i < 2; ++i) { 692 for (int i = 0; i < 2; ++i) {
498 Profile profile; 693 Profile profile;
499 profile.samples.push_back( 694 profile.samples.push_back(
500 Sample(1, Frame(0x1000, Frame::kUnknownModuleIndex))); 695 Sample((Frame(0x1000, Frame::kUnknownModuleIndex))));
501 696
502 profile.profile_duration = base::TimeDelta::FromMilliseconds(100); 697 profile.profile_duration = base::TimeDelta::FromMilliseconds(100);
503 // Use the sampling period to distinguish the two profiles. 698 // Use the sampling period to distinguish the two profiles.
504 profile.sampling_period = base::TimeDelta::FromMilliseconds(i); 699 profile.sampling_period = base::TimeDelta::FromMilliseconds(i);
505 Profiles profiles; 700 Profiles profiles;
506 profiles.push_back(std::move(profile)); 701 profiles.push_back(std::move(profile));
507 702
508 provider.OnRecordingEnabled(); 703 provider.OnRecordingEnabled();
509 AppendProfiles( 704 AppendProfiles(
510 CallStackProfileParams(CallStackProfileParams::BROWSER_PROCESS, 705 CallStackProfileParams(CallStackProfileParams::BROWSER_PROCESS,
(...skipping 12 matching lines...) Expand all
523 ASSERT_TRUE(call_stack_profile.has_sampling_period_ms()); 718 ASSERT_TRUE(call_stack_profile.has_sampling_period_ms());
524 EXPECT_EQ(i, call_stack_profile.sampling_period_ms()); 719 EXPECT_EQ(i, call_stack_profile.sampling_period_ms());
525 } 720 }
526 } 721 }
527 722
528 // Checks that pending profiles are provided to ProvideGeneralMetrics 723 // Checks that pending profiles are provided to ProvideGeneralMetrics
529 // when collected before CallStackProfileMetricsProvider is instantiated. 724 // when collected before CallStackProfileMetricsProvider is instantiated.
530 TEST_F(CallStackProfileMetricsProviderTest, 725 TEST_F(CallStackProfileMetricsProviderTest,
531 ProfilesProvidedWhenCollectedBeforeInstantiation) { 726 ProfilesProvidedWhenCollectedBeforeInstantiation) {
532 Profile profile; 727 Profile profile;
533 profile.samples.push_back( 728 profile.samples.push_back(Sample(Frame(0x1000, Frame::kUnknownModuleIndex)));
534 Sample(1, Frame(0x1000, Frame::kUnknownModuleIndex)));
535
536 profile.profile_duration = base::TimeDelta::FromMilliseconds(100); 729 profile.profile_duration = base::TimeDelta::FromMilliseconds(100);
537 profile.sampling_period = base::TimeDelta::FromMilliseconds(10); 730 profile.sampling_period = base::TimeDelta::FromMilliseconds(10);
538 Profiles profiles; 731 Profiles profiles;
539 profiles.push_back(std::move(profile)); 732 profiles.push_back(std::move(profile));
540 733
541 AppendProfiles( 734 AppendProfiles(
542 CallStackProfileParams(CallStackProfileParams::BROWSER_PROCESS, 735 CallStackProfileParams(CallStackProfileParams::BROWSER_PROCESS,
543 CallStackProfileParams::UI_THREAD, 736 CallStackProfileParams::UI_THREAD,
544 CallStackProfileParams::PROCESS_STARTUP, 737 CallStackProfileParams::PROCESS_STARTUP,
545 CallStackProfileParams::MAY_SHUFFLE), 738 CallStackProfileParams::MAY_SHUFFLE),
546 std::move(profiles)); 739 std::move(profiles));
547 740
548 CallStackProfileMetricsProvider provider; 741 CallStackProfileMetricsProvider provider;
549 provider.OnRecordingEnabled(); 742 provider.OnRecordingEnabled();
550 ChromeUserMetricsExtension uma_proto; 743 ChromeUserMetricsExtension uma_proto;
551 provider.ProvideGeneralMetrics(&uma_proto); 744 provider.ProvideGeneralMetrics(&uma_proto);
552 745
553 EXPECT_EQ(1, uma_proto.sampled_profile_size()); 746 EXPECT_EQ(1, uma_proto.sampled_profile_size());
554 } 747 }
555 748
556 // Checks that pending profiles are not provided to ProvideGeneralMetrics 749 // Checks that pending profiles are not provided to ProvideGeneralMetrics
557 // while recording is disabled. 750 // while recording is disabled.
558 TEST_F(CallStackProfileMetricsProviderTest, ProfilesNotProvidedWhileDisabled) { 751 TEST_F(CallStackProfileMetricsProviderTest, ProfilesNotProvidedWhileDisabled) {
559 Profile profile; 752 Profile profile;
560 profile.samples.push_back( 753 profile.samples.push_back(Sample(Frame(0x1000, Frame::kUnknownModuleIndex)));
561 Sample(1, Frame(0x1000, Frame::kUnknownModuleIndex)));
562
563 profile.profile_duration = base::TimeDelta::FromMilliseconds(100); 754 profile.profile_duration = base::TimeDelta::FromMilliseconds(100);
564 profile.sampling_period = base::TimeDelta::FromMilliseconds(10); 755 profile.sampling_period = base::TimeDelta::FromMilliseconds(10);
565 Profiles profiles; 756 Profiles profiles;
566 profiles.push_back(std::move(profile)); 757 profiles.push_back(std::move(profile));
567 758
568 CallStackProfileMetricsProvider provider; 759 CallStackProfileMetricsProvider provider;
569 provider.OnRecordingDisabled(); 760 provider.OnRecordingDisabled();
570 AppendProfiles( 761 AppendProfiles(
571 CallStackProfileParams(CallStackProfileParams::BROWSER_PROCESS, 762 CallStackProfileParams(CallStackProfileParams::BROWSER_PROCESS,
572 CallStackProfileParams::UI_THREAD, 763 CallStackProfileParams::UI_THREAD,
573 CallStackProfileParams::PROCESS_STARTUP, 764 CallStackProfileParams::PROCESS_STARTUP,
574 CallStackProfileParams::MAY_SHUFFLE), 765 CallStackProfileParams::MAY_SHUFFLE),
575 std::move(profiles)); 766 std::move(profiles));
576 ChromeUserMetricsExtension uma_proto; 767 ChromeUserMetricsExtension uma_proto;
577 provider.ProvideGeneralMetrics(&uma_proto); 768 provider.ProvideGeneralMetrics(&uma_proto);
578 769
579 EXPECT_EQ(0, uma_proto.sampled_profile_size()); 770 EXPECT_EQ(0, uma_proto.sampled_profile_size());
580 } 771 }
581 772
582 // Checks that pending profiles are not provided to ProvideGeneralMetrics 773 // Checks that pending profiles are not provided to ProvideGeneralMetrics
583 // if recording is disabled while profiling. 774 // if recording is disabled while profiling.
584 TEST_F(CallStackProfileMetricsProviderTest, 775 TEST_F(CallStackProfileMetricsProviderTest,
585 ProfilesNotProvidedAfterChangeToDisabled) { 776 ProfilesNotProvidedAfterChangeToDisabled) {
586 Profile profile; 777 Profile profile;
587 profile.samples.push_back( 778 profile.samples.push_back(Sample(Frame(0x1000, Frame::kUnknownModuleIndex)));
588 Sample(1, Frame(0x1000, Frame::kUnknownModuleIndex)));
589
590 profile.profile_duration = base::TimeDelta::FromMilliseconds(100); 779 profile.profile_duration = base::TimeDelta::FromMilliseconds(100);
591 profile.sampling_period = base::TimeDelta::FromMilliseconds(10); 780 profile.sampling_period = base::TimeDelta::FromMilliseconds(10);
592 781
593 CallStackProfileMetricsProvider provider; 782 CallStackProfileMetricsProvider provider;
594 provider.OnRecordingEnabled(); 783 provider.OnRecordingEnabled();
595 base::StackSamplingProfiler::CompletedCallback callback = 784 base::StackSamplingProfiler::CompletedCallback callback =
596 CallStackProfileMetricsProvider::GetProfilerCallback( 785 CallStackProfileMetricsProvider::GetProfilerCallback(
597 CallStackProfileParams(CallStackProfileParams::BROWSER_PROCESS, 786 CallStackProfileParams(CallStackProfileParams::BROWSER_PROCESS,
598 CallStackProfileParams::UI_THREAD, 787 CallStackProfileParams::UI_THREAD,
599 CallStackProfileParams::PROCESS_STARTUP, 788 CallStackProfileParams::PROCESS_STARTUP,
600 CallStackProfileParams::MAY_SHUFFLE)); 789 CallStackProfileParams::MAY_SHUFFLE));
601 790
602 provider.OnRecordingDisabled(); 791 provider.OnRecordingDisabled();
603 Profiles profiles; 792 Profiles profiles;
604 profiles.push_back(std::move(profile)); 793 profiles.push_back(std::move(profile));
605 callback.Run(std::move(profiles)); 794 callback.Run(std::move(profiles));
606 ChromeUserMetricsExtension uma_proto; 795 ChromeUserMetricsExtension uma_proto;
607 provider.ProvideGeneralMetrics(&uma_proto); 796 provider.ProvideGeneralMetrics(&uma_proto);
608 797
609 EXPECT_EQ(0, uma_proto.sampled_profile_size()); 798 EXPECT_EQ(0, uma_proto.sampled_profile_size());
610 } 799 }
611 800
612 // Checks that pending profiles are not provided to ProvideGeneralMetrics if 801 // Checks that pending profiles are not provided to ProvideGeneralMetrics if
613 // recording is enabled, but then disabled and reenabled while profiling. 802 // recording is enabled, but then disabled and reenabled while profiling.
614 TEST_F(CallStackProfileMetricsProviderTest, 803 TEST_F(CallStackProfileMetricsProviderTest,
615 ProfilesNotProvidedAfterChangeToDisabledThenEnabled) { 804 ProfilesNotProvidedAfterChangeToDisabledThenEnabled) {
616 Profile profile; 805 Profile profile;
617 profile.samples.push_back( 806 profile.samples.push_back(Sample(Frame(0x1000, Frame::kUnknownModuleIndex)));
618 Sample(1, Frame(0x1000, Frame::kUnknownModuleIndex)));
619
620 profile.profile_duration = base::TimeDelta::FromMilliseconds(100); 807 profile.profile_duration = base::TimeDelta::FromMilliseconds(100);
621 profile.sampling_period = base::TimeDelta::FromMilliseconds(10); 808 profile.sampling_period = base::TimeDelta::FromMilliseconds(10);
622 809
623 CallStackProfileMetricsProvider provider; 810 CallStackProfileMetricsProvider provider;
624 provider.OnRecordingEnabled(); 811 provider.OnRecordingEnabled();
625 base::StackSamplingProfiler::CompletedCallback callback = 812 base::StackSamplingProfiler::CompletedCallback callback =
626 CallStackProfileMetricsProvider::GetProfilerCallback( 813 CallStackProfileMetricsProvider::GetProfilerCallback(
627 CallStackProfileParams(CallStackProfileParams::BROWSER_PROCESS, 814 CallStackProfileParams(CallStackProfileParams::BROWSER_PROCESS,
628 CallStackProfileParams::UI_THREAD, 815 CallStackProfileParams::UI_THREAD,
629 CallStackProfileParams::PROCESS_STARTUP, 816 CallStackProfileParams::PROCESS_STARTUP,
630 CallStackProfileParams::MAY_SHUFFLE)); 817 CallStackProfileParams::MAY_SHUFFLE));
631 818
632 provider.OnRecordingDisabled(); 819 provider.OnRecordingDisabled();
633 provider.OnRecordingEnabled(); 820 provider.OnRecordingEnabled();
634 Profiles profiles; 821 Profiles profiles;
635 profiles.push_back(std::move(profile)); 822 profiles.push_back(std::move(profile));
636 callback.Run(std::move(profiles)); 823 callback.Run(std::move(profiles));
637 ChromeUserMetricsExtension uma_proto; 824 ChromeUserMetricsExtension uma_proto;
638 provider.ProvideGeneralMetrics(&uma_proto); 825 provider.ProvideGeneralMetrics(&uma_proto);
639 826
640 EXPECT_EQ(0, uma_proto.sampled_profile_size()); 827 EXPECT_EQ(0, uma_proto.sampled_profile_size());
641 } 828 }
642 829
643 // Checks that pending profiles are not provided to ProvideGeneralMetrics 830 // Checks that pending profiles are not provided to ProvideGeneralMetrics
644 // if recording is disabled, but then enabled while profiling. 831 // if recording is disabled, but then enabled while profiling.
645 TEST_F(CallStackProfileMetricsProviderTest, 832 TEST_F(CallStackProfileMetricsProviderTest,
646 ProfilesNotProvidedAfterChangeFromDisabled) { 833 ProfilesNotProvidedAfterChangeFromDisabled) {
647 Profile profile; 834 Profile profile;
648 profile.samples.push_back( 835 profile.samples.push_back(Sample(Frame(0x1000, Frame::kUnknownModuleIndex)));
649 Sample(1, Frame(0x1000, Frame::kUnknownModuleIndex)));
650
651 profile.profile_duration = base::TimeDelta::FromMilliseconds(100); 836 profile.profile_duration = base::TimeDelta::FromMilliseconds(100);
652 profile.sampling_period = base::TimeDelta::FromMilliseconds(10); 837 profile.sampling_period = base::TimeDelta::FromMilliseconds(10);
653 838
654 CallStackProfileMetricsProvider provider; 839 CallStackProfileMetricsProvider provider;
655 provider.OnRecordingDisabled(); 840 provider.OnRecordingDisabled();
656 base::StackSamplingProfiler::CompletedCallback callback = 841 base::StackSamplingProfiler::CompletedCallback callback =
657 CallStackProfileMetricsProvider::GetProfilerCallback( 842 CallStackProfileMetricsProvider::GetProfilerCallback(
658 CallStackProfileParams(CallStackProfileParams::BROWSER_PROCESS, 843 CallStackProfileParams(CallStackProfileParams::BROWSER_PROCESS,
659 CallStackProfileParams::UI_THREAD, 844 CallStackProfileParams::UI_THREAD,
660 CallStackProfileParams::PROCESS_STARTUP, 845 CallStackProfileParams::PROCESS_STARTUP,
661 CallStackProfileParams::MAY_SHUFFLE)); 846 CallStackProfileParams::MAY_SHUFFLE));
662 847
663 provider.OnRecordingEnabled(); 848 provider.OnRecordingEnabled();
664 Profiles profiles; 849 Profiles profiles;
665 profiles.push_back(std::move(profile)); 850 profiles.push_back(std::move(profile));
666 callback.Run(std::move(profiles)); 851 callback.Run(std::move(profiles));
667 ChromeUserMetricsExtension uma_proto; 852 ChromeUserMetricsExtension uma_proto;
668 provider.ProvideGeneralMetrics(&uma_proto); 853 provider.ProvideGeneralMetrics(&uma_proto);
669 854
670 EXPECT_EQ(0, uma_proto.sampled_profile_size()); 855 EXPECT_EQ(0, uma_proto.sampled_profile_size());
671 } 856 }
672 857
673 } // namespace metrics 858 } // namespace metrics
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698