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

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: addressed review comments and finished converting tests 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 kNewProfile,
38 kNewSample,
39 kNextFrame,
40 kDefineModule,
41 };
42
43 struct ExpectedProtoModule {
44 const char* build_id;
45 uint64_t name_md5;
46 uint64_t base_address;
47 };
48
49 struct ExpectedProtoEntry {
50 int32_t module_index;
51 uint64_t address;
52 };
53
54 struct ExpectedProtoSample {
55 uint32_t process_phases; // Bit-field of expected phases.
56 const ExpectedProtoEntry* entries;
57 int entry_count;
58 int64_t entry_repeats;
59 };
60
61 struct ExpectedProtoProfile {
62 int32_t duration_ms;
63 int32_t period_ms;
64 const ExpectedProtoModule* modules;
65 int module_count;
66 const ExpectedProtoSample* samples;
67 int sample_count;
68 };
69
70 } // namespace
71
72 #define GEN_ADD_PHASE(phase) kAddPhase, phase
73 #define GEN_NEW_PROFILE(duration_ms, interval_ms) \
74 kNewProfile, duration_ms, interval_ms
75 #define GEN_NEW_SAMPLE() kNewSample
76 #define GEN_FRAME(module, offset) kNextFrame, module, offset
77 #define GEN_DEFINE_MODULE(name, path, base) \
78 kDefineModule, reinterpret_cast<uintptr_t>(name), \
79 reinterpret_cast<uintptr_t>(&path), base
80 #define GEN_END() kEndOfGenerator
81
30 namespace metrics { 82 namespace metrics {
31 83
32 // This test fixture enables the field trial that 84 // This test fixture enables the field trial that
33 // CallStackProfileMetricsProvider depends on to report profiles. 85 // CallStackProfileMetricsProvider depends on to report profiles.
34 class CallStackProfileMetricsProviderTest : public testing::Test { 86 class CallStackProfileMetricsProviderTest : public testing::Test {
35 public: 87 public:
36 CallStackProfileMetricsProviderTest() 88 CallStackProfileMetricsProviderTest()
37 : field_trial_list_(nullptr) { 89 : field_trial_list_(nullptr) {
38 base::FieldTrialList::CreateFieldTrial( 90 base::FieldTrialList::CreateFieldTrial(
39 TestState::kFieldTrialName, 91 TestState::kFieldTrialName,
40 TestState::kReportProfilesGroupName); 92 TestState::kReportProfilesGroupName);
41 TestState::ResetStaticStateForTesting(); 93 TestState::ResetStaticStateForTesting();
42 } 94 }
43 95
44 ~CallStackProfileMetricsProviderTest() override {} 96 ~CallStackProfileMetricsProviderTest() override {}
45 97
46 // Utility function to append profiles to the metrics provider. 98 // Utility function to append profiles to the metrics provider.
47 void AppendProfiles(const CallStackProfileParams& params, Profiles profiles) { 99 void AppendProfiles(const CallStackProfileParams& params, Profiles profiles) {
48 CallStackProfileMetricsProvider::GetProfilerCallback(params).Run( 100 CallStackProfileMetricsProvider::GetProfilerCallback(params).Run(
49 std::move(profiles)); 101 std::move(profiles));
50 } 102 }
51 103
104 // Utility to create a Profiles list from a generator constant.
105 void GenerateProfiles(Profiles* profiles, const ProfilesGenerator* generator);
106
107 void VerifyProfileProto(const SampledProfile& proto,
108 const ExpectedProtoProfile& expected);
109
52 private: 110 private:
53 // Exposes field trial/group names from the CallStackProfileMetricsProvider. 111 // Exposes field trial/group names from the CallStackProfileMetricsProvider.
54 class TestState : public CallStackProfileMetricsProvider { 112 class TestState : public CallStackProfileMetricsProvider {
55 public: 113 public:
56 using CallStackProfileMetricsProvider::kFieldTrialName; 114 using CallStackProfileMetricsProvider::kFieldTrialName;
57 using CallStackProfileMetricsProvider::kReportProfilesGroupName; 115 using CallStackProfileMetricsProvider::kReportProfilesGroupName;
58 using CallStackProfileMetricsProvider::ResetStaticStateForTesting; 116 using CallStackProfileMetricsProvider::ResetStaticStateForTesting;
59 }; 117 };
60 118
61 base::FieldTrialList field_trial_list_; 119 base::FieldTrialList field_trial_list_;
62 120
63 DISALLOW_COPY_AND_ASSIGN(CallStackProfileMetricsProviderTest); 121 DISALLOW_COPY_AND_ASSIGN(CallStackProfileMetricsProviderTest);
64 }; 122 };
65 123
124 void CallStackProfileMetricsProviderTest::GenerateProfiles(
Mike Wittman 2016/11/16 22:36:09 Can GenerateProfiles and VerifyProfileProto be mov
bcwhite 2016/11/16 23:10:49 I think it could be it's paired with Verify just b
125 Profiles* profiles,
Mike Wittman 2016/11/16 22:36:09 nit: output parameters come after input parameters
bcwhite 2016/11/16 23:10:49 Done.
126 const ProfilesGenerator* generator) {
127 uint32_t process_phases = 0;
128 Profile* profile = nullptr;
129
130 while (true) {
131 switch (*generator++) {
132 case kEndOfGenerator:
133 return;
134 case kAddPhase:
135 process_phases |= 1 << *generator++;
136 break;
137 case kNewProfile:
138 profiles->push_back(Profile());
139 profile = &profiles->back();
140 profile->profile_duration =
141 base::TimeDelta::FromMilliseconds(*generator++);
142 profile->sampling_period =
143 base::TimeDelta::FromMilliseconds(*generator++);
144 break;
145 case kNewSample:
146 profile->samples.push_back(Sample());
147 profile->samples.back().process_phases = process_phases;
148 break;
149 case kNextFrame: {
150 size_t index = static_cast<size_t>(*generator++);
151 uintptr_t address = static_cast<uintptr_t>(*generator++);
152 profile->samples.back().frames.push_back(Frame(address, index));
153 } break;
Alexei Svitkine (slow) 2016/11/16 19:10:24 Nit: I'm not sure this is correct style. I think
bcwhite 2016/11/16 23:10:49 That's the way git cl format put it.
154 case kDefineModule: {
155 const char* name =
156 reinterpret_cast<const char*>(static_cast<uintptr_t>(*generator++));
157 const base::FilePath* path = reinterpret_cast<const base::FilePath*>(
158 static_cast<uintptr_t>(*generator++));
159 uintptr_t base = static_cast<uintptr_t>(*generator++);
160 profile->modules.push_back(Module(base, name, *path));
161 } break;
162 default:
163 NOTREACHED();
164 };
165 }
166 }
167
168 void CallStackProfileMetricsProviderTest::VerifyProfileProto(
169 const SampledProfile& proto,
170 const ExpectedProtoProfile& expected) {
Mike Wittman 2016/11/16 22:36:09 nit: swap argument order to match typical (expecte
bcwhite 2016/11/16 23:10:49 Done.
171 ASSERT_TRUE(proto.has_call_stack_profile());
172 const CallStackProfile& stack = proto.call_stack_profile();
173
174 ASSERT_TRUE(stack.has_profile_duration_ms());
175 EXPECT_EQ(expected.duration_ms, stack.profile_duration_ms());
176 ASSERT_TRUE(stack.has_sampling_period_ms());
177 EXPECT_EQ(expected.period_ms, stack.sampling_period_ms());
178
179 ASSERT_EQ(expected.module_count, stack.module_id().size());
180 for (int m = 0; m < expected.module_count; ++m) {
181 SCOPED_TRACE("module " + base::IntToString(m));
182 const CallStackProfile::ModuleIdentifier& module_id =
183 stack.module_id().Get(m);
184 ASSERT_TRUE(module_id.has_build_id());
185 EXPECT_EQ(expected.modules[m].build_id, module_id.build_id());
186 ASSERT_TRUE(module_id.has_name_md5_prefix());
187 EXPECT_EQ(expected.modules[m].name_md5, module_id.name_md5_prefix());
188 }
189
190 ASSERT_EQ(expected.sample_count, stack.sample().size());
191 for (int s = 0; s < expected.sample_count; ++s) {
192 SCOPED_TRACE("sample " + base::IntToString(s));
193 const CallStackProfile::Sample& proto_sample = stack.sample().Get(s);
194
195 uint32_t process_phases = 0;
196 for (int i = 0; i < proto_sample.process_phase().size(); ++i)
197 process_phases |= 1U << proto_sample.process_phase().Get(i);
198 EXPECT_EQ(expected.samples[s].process_phases, process_phases);
199
200 ASSERT_EQ(expected.samples[s].entry_count, proto_sample.entry().size());
201 ASSERT_TRUE(proto_sample.has_count());
202 EXPECT_EQ(expected.samples[s].entry_repeats, proto_sample.count());
203 for (int e = 0; e < expected.samples[s].entry_count; ++e) {
204 SCOPED_TRACE("entry " + base::SizeTToString(e));
205 const CallStackProfile::Entry& entry = proto_sample.entry().Get(e);
206 if (expected.samples[s].entries[e].module_index >= 0) {
207 ASSERT_TRUE(entry.has_module_id_index());
208 EXPECT_EQ(expected.samples[s].entries[e].module_index,
209 entry.module_id_index());
210 ASSERT_TRUE(entry.has_address());
211 EXPECT_EQ(expected.samples[s].entries[e].address, entry.address());
212 } else {
213 EXPECT_FALSE(entry.has_module_id_index());
214 EXPECT_FALSE(entry.has_address());
215 }
216 }
217 }
218 }
219
66 // Checks that all properties from multiple profiles are filled as expected. 220 // Checks that all properties from multiple profiles are filled as expected.
67 TEST_F(CallStackProfileMetricsProviderTest, MultipleProfiles) { 221 TEST_F(CallStackProfileMetricsProviderTest, MultipleProfiles) {
68 const uintptr_t module1_base_address = 0x1000; 222 const uintptr_t moduleA_base_address = 0x1000;
69 const uintptr_t module2_base_address = 0x2000; 223 const uintptr_t moduleB_base_address = 0x2000;
70 const uintptr_t module3_base_address = 0x3000; 224 const uintptr_t moduleC_base_address = 0x3000;
71 225 const char* moduleA_name = "ABCD";
72 const Module profile_modules[][2] = { 226 const char* moduleB_name = "EFGH";
73 { 227 const char* moduleC_name = "MNOP";
74 Module(
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 228
115 // Values for Windows generated with: 229 // Values for Windows generated with:
116 // perl -MDigest::MD5=md5 -MEncode=encode 230 // perl -MDigest::MD5=md5 -MEncode=encode
117 // -e 'for(@ARGV){printf "%x\n", unpack "Q>", md5 encode "UTF-16LE", $_}' 231 // -e 'for(@ARGV){printf "%x\n", unpack "Q>", md5 encode "UTF-16LE", $_}'
118 // chrome.exe third_party.dll third_party2.dll 232 // chrome.exe third_party.dll third_party2.dll
119 // 233 //
120 // Values for Linux generated with: 234 // Values for Linux generated with:
121 // perl -MDigest::MD5=md5 235 // perl -MDigest::MD5=md5
122 // -e 'for(@ARGV){printf "%x\n", unpack "Q>", md5 $_}' 236 // -e 'for(@ARGV){printf "%x\n", unpack "Q>", md5 $_}'
123 // chrome third_party.so third_party2.so 237 // chrome third_party.so third_party2.so
124 const uint64_t profile_expected_name_md5_prefixes[][2] = {
125 {
126 #if defined(OS_WIN) 238 #if defined(OS_WIN)
127 0x46c3e4166659ac02ULL, 0x7e2b8bfddeae1abaULL 239 uint64_t moduleA_md5 = 0x46C3E4166659AC02ULL;
240 uint64_t moduleB_md5 = 0x7E2B8BFDDEAE1ABAULL;
241 uint64_t moduleC_md5 = 0x87B66F4573A4D5CAULL;
242 base::FilePath moduleA_path(L"c:\\some\\path\\to\\chrome.exe");
243 base::FilePath moduleB_path(L"c:\\some\\path\\to\\third_party.dll");
244 base::FilePath moduleC_path(L"c:\\some\\path\\to\\third_party2.dll");
128 #else 245 #else
129 0x554838a8451ac36cUL, 0x843661148659c9f8UL 246 uint64_t moduleA_md5 = 0x554838A8451AC36CULL;
247 uint64_t moduleB_md5 = 0x843661148659C9F8ULL;
248 uint64_t moduleC_md5 = 0xB4647E539FA6EC9EULL;
249 base::FilePath moduleA_path("/some/path/to/chrome");
250 base::FilePath moduleB_path("/some/path/to/third_party.so");
251 base::FilePath moduleC_path("/some/path/to/third_party2.so");
130 #endif 252 #endif
131 },
132 {
133 #if defined(OS_WIN)
134 0x87b66f4573a4d5caULL, 0x46c3e4166659ac02ULL
135 #else
136 0xb4647e539fa6ec9eUL, 0x554838a8451ac36cUL
137 #endif
138 }};
139 253
140 // Represents two stack samples for each of two profiles, where each stack 254 // Represents two stack samples for each of two profiles, where each stack
141 // contains three frames. Each frame contains an instruction pointer and a 255 // contains three frames. Each frame contains an instruction pointer and a
142 // module index corresponding to the module for the profile in 256 // module index corresponding to the module for the profile in
143 // profile_modules. 257 // profile_modules.
144 // 258 //
145 // So, the first stack sample below has its top frame in module 0 at an offset 259 // 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 260 // 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 261 // 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 262 // in module 0 at an offset of 0x30 from the module's base address
149 const Frame profile_sample_frames[][2][3] = { 263 const ProfilesGenerator test_profiles_generator[] = {
150 { 264 GEN_NEW_PROFILE(100, 10),
Mike Wittman 2016/11/16 22:36:09 What's the advantage of this form of input data in
bcwhite 2016/11/16 23:10:49 This is far more flexible because you're not limit
Mike Wittman 2016/11/17 17:23:21 Sounds reasonable. Macros are discouraged by C++ s
bcwhite 2016/11/17 17:43:19 I wouldn't have used them if it wasn't just a test
Mike Wittman 2016/11/17 17:51:27 I think it's worth it to eliminate the macros and
bcwhite 2016/11/22 22:50:13 Done.
265 GEN_DEFINE_MODULE(moduleA_name, moduleA_path, moduleA_base_address),
266 GEN_DEFINE_MODULE(moduleB_name, moduleB_path, moduleB_base_address),
267
268 GEN_NEW_SAMPLE(),
269 GEN_FRAME(0, moduleA_base_address + 0x10),
270 GEN_FRAME(1, moduleB_base_address + 0x20),
271 GEN_FRAME(0, moduleA_base_address + 0x30),
272 GEN_NEW_SAMPLE(),
273 GEN_FRAME(1, moduleB_base_address + 0x10),
274 GEN_FRAME(0, moduleA_base_address + 0x20),
275 GEN_FRAME(1, moduleB_base_address + 0x30),
276
277 GEN_NEW_PROFILE(200, 20),
278 GEN_DEFINE_MODULE(moduleC_name, moduleC_path, moduleC_base_address),
279 GEN_DEFINE_MODULE(moduleA_name, moduleA_path, moduleA_base_address),
280
281 GEN_NEW_SAMPLE(),
282 GEN_FRAME(0, moduleC_base_address + 0x10),
283 GEN_FRAME(1, moduleA_base_address + 0x20),
284 GEN_FRAME(0, moduleC_base_address + 0x30),
285 GEN_NEW_SAMPLE(),
286 GEN_FRAME(1, moduleA_base_address + 0x10),
287 GEN_FRAME(0, moduleC_base_address + 0x20),
288 GEN_FRAME(1, moduleA_base_address + 0x30),
289
290 GEN_END(),
291 };
292
293 const ExpectedProtoModule expected_proto_modules1[] = {
294 { moduleA_name, moduleA_md5, moduleA_base_address },
295 { moduleB_name, moduleB_md5, moduleB_base_address }
296 };
297
298 const ExpectedProtoEntry expected_proto_entries11[] = {
299 { 0, 0x10 },
300 { 1, 0x20 },
301 { 0, 0x30 },
302 };
303 const ExpectedProtoEntry expected_proto_entries12[] = {
304 { 1, 0x10 },
305 { 0, 0x20 },
306 { 1, 0x30 },
307 };
308 const ExpectedProtoSample expected_proto_samples1[] = {
151 { 309 {
152 Frame(module1_base_address + 0x10, 0), 310 0, expected_proto_entries11, arraysize(expected_proto_entries11), 1,
153 Frame(module2_base_address + 0x20, 1),
154 Frame(module1_base_address + 0x30, 0)
155 }, 311 },
156 { 312 {
157 Frame(module2_base_address + 0x10, 1), 313 0, expected_proto_entries12, arraysize(expected_proto_entries12), 1,
158 Frame(module1_base_address + 0x20, 0), 314 },
159 Frame(module2_base_address + 0x30, 1) 315 };
160 } 316
161 }, 317 const ExpectedProtoModule expected_proto_modules2[] = {
162 { 318 { moduleC_name, moduleC_md5, moduleC_base_address },
319 { moduleA_name, moduleA_md5, moduleA_base_address }
320 };
321
322 const ExpectedProtoEntry expected_proto_entries21[] = {
323 { 0, 0x10 },
324 { 1, 0x20 },
325 { 0, 0x30 },
326 };
327 const ExpectedProtoEntry expected_proto_entries22[] = {
328 { 1, 0x10 },
329 { 0, 0x20 },
330 { 1, 0x30 },
331 };
332 const ExpectedProtoSample expected_proto_samples2[] = {
163 { 333 {
164 Frame(module3_base_address + 0x10, 0), 334 0, expected_proto_entries11, arraysize(expected_proto_entries21), 1,
165 Frame(module1_base_address + 0x20, 1),
166 Frame(module3_base_address + 0x30, 0)
167 }, 335 },
168 { 336 {
169 Frame(module1_base_address + 0x10, 1), 337 0, expected_proto_entries12, arraysize(expected_proto_entries22), 1,
170 Frame(module3_base_address + 0x20, 0), 338 },
171 Frame(module1_base_address + 0x30, 1)
172 }
173 }
174 }; 339 };
175 340
176 base::TimeDelta profile_durations[2] = { 341 const ExpectedProtoProfile expected_proto_profiles[] = {
177 base::TimeDelta::FromMilliseconds(100), 342 {
178 base::TimeDelta::FromMilliseconds(200) 343 100, 10,
344 expected_proto_modules1, arraysize(expected_proto_modules1),
345 expected_proto_samples1, arraysize(expected_proto_samples1),
346 },
347 {
348 200, 20,
349 expected_proto_modules2, arraysize(expected_proto_modules2),
350 expected_proto_samples2, arraysize(expected_proto_samples2),
351 },
179 }; 352 };
180 353
181 base::TimeDelta profile_sampling_periods[2] = { 354 Profiles profiles;
182 base::TimeDelta::FromMilliseconds(10), 355 GenerateProfiles(&profiles, test_profiles_generator);
183 base::TimeDelta::FromMilliseconds(20) 356 ASSERT_EQ(arraysize(expected_proto_profiles), profiles.size());
184 };
185
186 std::vector<Profile> profiles;
187 for (size_t i = 0; i < arraysize(profile_sample_frames); ++i) {
188 Profile profile;
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 357
207 CallStackProfileMetricsProvider provider; 358 CallStackProfileMetricsProvider provider;
208 provider.OnRecordingEnabled(); 359 provider.OnRecordingEnabled();
209 AppendProfiles( 360 AppendProfiles(
210 CallStackProfileParams(CallStackProfileParams::BROWSER_PROCESS, 361 CallStackProfileParams(CallStackProfileParams::BROWSER_PROCESS,
211 CallStackProfileParams::UI_THREAD, 362 CallStackProfileParams::UI_THREAD,
212 CallStackProfileParams::PROCESS_STARTUP, 363 CallStackProfileParams::PROCESS_STARTUP,
213 CallStackProfileParams::MAY_SHUFFLE), 364 CallStackProfileParams::MAY_SHUFFLE),
214 std::move(profiles)); 365 std::move(profiles));
215 ChromeUserMetricsExtension uma_proto; 366 ChromeUserMetricsExtension uma_proto;
216 provider.ProvideGeneralMetrics(&uma_proto); 367 provider.ProvideGeneralMetrics(&uma_proto);
217 368
218 ASSERT_EQ(static_cast<int>(arraysize(profile_sample_frames)), 369 ASSERT_EQ(static_cast<int>(arraysize(expected_proto_profiles)),
219 uma_proto.sampled_profile().size()); 370 uma_proto.sampled_profile().size());
220 for (size_t i = 0; i < arraysize(profile_sample_frames); ++i) { 371 for (size_t p = 0; p < arraysize(expected_proto_profiles); ++p) {
221 SCOPED_TRACE("profile " + base::SizeTToString(i)); 372 SCOPED_TRACE("profile " + base::SizeTToString(p));
222 const SampledProfile& sampled_profile = uma_proto.sampled_profile().Get(i); 373 VerifyProfileProto(uma_proto.sampled_profile().Get(p),
223 ASSERT_TRUE(sampled_profile.has_call_stack_profile()); 374 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 } 375 }
281 } 376 }
282 377
283 // Checks that all duplicate samples are collapsed with 378 // Checks that all duplicate samples are collapsed with
284 // preserve_sample_ordering = false. 379 // preserve_sample_ordering = false.
285 TEST_F(CallStackProfileMetricsProviderTest, RepeatedStacksUnordered) { 380 TEST_F(CallStackProfileMetricsProviderTest, RepeatedStacksUnordered) {
286 const uintptr_t module_base_address = 0x1000; 381 const uintptr_t module_base_address = 0x1000;
382 const char* module_name = "ABCD";
287 383
288 const Module modules[] = {
289 Module(
290 module_base_address,
291 "ABCD",
292 #if defined(OS_WIN) 384 #if defined(OS_WIN)
293 base::FilePath(L"c:\\some\\path\\to\\chrome.exe") 385 uint64_t module_md5 = 0x46C3E4166659AC02ULL;
386 base::FilePath module_path(L"c:\\some\\path\\to\\chrome.exe");
294 #else 387 #else
295 base::FilePath("/some/path/to/chrome") 388 uint64_t module_md5 = 0x554838A8451AC36CULL;
389 base::FilePath module_path("/some/path/to/chrome");
296 #endif 390 #endif
297 ) 391
392 const ProfilesGenerator test_profiles_generator[] = {
393 GEN_NEW_PROFILE(100, 10),
394 GEN_DEFINE_MODULE(module_name, module_path, module_base_address),
395
396 GEN_ADD_PHASE(0),
397 GEN_NEW_SAMPLE(),
398 GEN_FRAME(0, module_base_address + 0x10),
399 GEN_NEW_SAMPLE(),
400 GEN_FRAME(0, module_base_address + 0x20),
401 GEN_NEW_SAMPLE(),
402 GEN_FRAME(0, module_base_address + 0x10),
403 GEN_NEW_SAMPLE(),
404 GEN_FRAME(0, module_base_address + 0x10),
405
406 GEN_ADD_PHASE(1),
407 GEN_NEW_SAMPLE(),
408 GEN_FRAME(0, module_base_address + 0x10),
409 GEN_NEW_SAMPLE(),
410 GEN_FRAME(0, module_base_address + 0x20),
411 GEN_NEW_SAMPLE(),
412 GEN_FRAME(0, module_base_address + 0x10),
413 GEN_NEW_SAMPLE(),
414 GEN_FRAME(0, module_base_address + 0x10),
415
416 GEN_END(),
298 }; 417 };
299 418
300 // Duplicate samples in slots 0, 2, and 3. 419 const ExpectedProtoModule expected_proto_modules[] = {
301 const Frame sample_frames[][1] = { 420 { module_name, module_md5, module_base_address },
302 { Frame(module_base_address + 0x10, 0), },
303 { Frame(module_base_address + 0x20, 0), },
304 { Frame(module_base_address + 0x10, 0), },
305 { Frame(module_base_address + 0x10, 0) }
306 }; 421 };
307 422
308 Profile profile; 423 const ExpectedProtoEntry expected_proto_entries[] = {
309 profile.modules.insert(profile.modules.end(), &modules[0], 424 { 0, 0x10 },
310 &modules[0] + arraysize(modules)); 425 { 0, 0x20 },
426 };
427 const ExpectedProtoSample expected_proto_samples[] = {
428 { 1, &expected_proto_entries[0], 1, 3 },
429 { 1, &expected_proto_entries[1], 1, 1 },
430 { 3, &expected_proto_entries[0], 1, 3 },
431 { 3, &expected_proto_entries[1], 1, 1 },
432 };
311 433
312 for (size_t i = 0; i < arraysize(sample_frames); ++i) { 434 const ExpectedProtoProfile expected_proto_profiles[] = {
313 profile.samples.push_back(Sample()); 435 {
314 Sample& sample = profile.samples.back(); 436 100, 10,
315 sample.insert(sample.end(), &sample_frames[i][0], 437 expected_proto_modules, arraysize(expected_proto_modules),
316 &sample_frames[i][0] + arraysize(sample_frames[i])); 438 expected_proto_samples, arraysize(expected_proto_samples),
317 } 439 },
440 };
318 441
319 profile.profile_duration = base::TimeDelta::FromMilliseconds(100);
320 profile.sampling_period = base::TimeDelta::FromMilliseconds(10);
321 Profiles profiles; 442 Profiles profiles;
322 profiles.push_back(std::move(profile)); 443 GenerateProfiles(&profiles, test_profiles_generator);
444 ASSERT_EQ(arraysize(expected_proto_profiles), profiles.size());
323 445
324 CallStackProfileMetricsProvider provider; 446 CallStackProfileMetricsProvider provider;
325 provider.OnRecordingEnabled(); 447 provider.OnRecordingEnabled();
326 AppendProfiles( 448 AppendProfiles(
327 CallStackProfileParams(CallStackProfileParams::BROWSER_PROCESS, 449 CallStackProfileParams(CallStackProfileParams::BROWSER_PROCESS,
328 CallStackProfileParams::UI_THREAD, 450 CallStackProfileParams::UI_THREAD,
329 CallStackProfileParams::PROCESS_STARTUP, 451 CallStackProfileParams::PROCESS_STARTUP,
330 CallStackProfileParams::MAY_SHUFFLE), 452 CallStackProfileParams::MAY_SHUFFLE),
331 std::move(profiles)); 453 std::move(profiles));
332 ChromeUserMetricsExtension uma_proto; 454 ChromeUserMetricsExtension uma_proto;
333 provider.ProvideGeneralMetrics(&uma_proto); 455 provider.ProvideGeneralMetrics(&uma_proto);
334 456
335 ASSERT_EQ(1, uma_proto.sampled_profile().size()); 457 ASSERT_EQ(static_cast<int>(arraysize(expected_proto_profiles)),
336 const SampledProfile& sampled_profile = uma_proto.sampled_profile().Get(0); 458 uma_proto.sampled_profile().size());
337 ASSERT_TRUE(sampled_profile.has_call_stack_profile()); 459 for (size_t p = 0; p < arraysize(expected_proto_profiles); ++p) {
338 const CallStackProfile& call_stack_profile = 460 SCOPED_TRACE("profile " + base::SizeTToString(p));
339 sampled_profile.call_stack_profile(); 461 VerifyProfileProto(uma_proto.sampled_profile().Get(p),
340 462 expected_proto_profiles[p]);
341 ASSERT_EQ(2, call_stack_profile.sample().size());
342 for (int i = 0; i < 2; ++i) {
343 SCOPED_TRACE("sample " + base::IntToString(i));
344 const CallStackProfile::Sample& proto_sample =
345 call_stack_profile.sample().Get(i);
346 ASSERT_EQ(static_cast<int>(arraysize(sample_frames[i])),
347 proto_sample.entry().size());
348 ASSERT_TRUE(proto_sample.has_count());
349 EXPECT_EQ(i == 0 ? 3u : 1u, proto_sample.count());
350 for (size_t j = 0; j < arraysize(sample_frames[i]); ++j) {
351 SCOPED_TRACE("frame " + base::SizeTToString(j));
352 const CallStackProfile::Entry& entry = proto_sample.entry().Get(j);
353 ASSERT_TRUE(entry.has_address());
354 const char* instruction_pointer = reinterpret_cast<const char*>(
355 sample_frames[i][j].instruction_pointer);
356 const char* module_base_address = reinterpret_cast<const char*>(
357 modules[sample_frames[i][j].module_index].base_address);
358 EXPECT_EQ(
359 static_cast<uint64_t>(instruction_pointer - module_base_address),
360 entry.address());
361 ASSERT_TRUE(entry.has_module_id_index());
362 EXPECT_EQ(sample_frames[i][j].module_index,
363 static_cast<size_t>(entry.module_id_index()));
364 }
365 } 463 }
366 } 464 }
367 465
368 // Checks that only contiguous duplicate samples are collapsed with 466 // Checks that only contiguous duplicate samples are collapsed with
369 // preserve_sample_ordering = true. 467 // preserve_sample_ordering = true.
370 TEST_F(CallStackProfileMetricsProviderTest, RepeatedStacksOrdered) { 468 TEST_F(CallStackProfileMetricsProviderTest, RepeatedStacksOrdered) {
371 const uintptr_t module_base_address = 0x1000; 469 const uintptr_t module_base_address = 0x1000;
470 const char* module_name = "ABCD";
372 471
373 const Module modules[] = {
374 Module(
375 module_base_address,
376 "ABCD",
377 #if defined(OS_WIN) 472 #if defined(OS_WIN)
378 base::FilePath(L"c:\\some\\path\\to\\chrome.exe") 473 uint64_t module_md5 = 0x46C3E4166659AC02ULL;
474 base::FilePath module_path(L"c:\\some\\path\\to\\chrome.exe");
379 #else 475 #else
380 base::FilePath("/some/path/to/chrome") 476 uint64_t module_md5 = 0x554838A8451AC36CULL;
477 base::FilePath module_path("/some/path/to/chrome");
381 #endif 478 #endif
382 ) 479
480 const ProfilesGenerator test_profiles_generator[] = {
481 GEN_NEW_PROFILE(100, 10),
482 GEN_DEFINE_MODULE(module_name, module_path, module_base_address),
483
484 GEN_ADD_PHASE(0),
485 GEN_NEW_SAMPLE(),
486 GEN_FRAME(0, module_base_address + 0x10),
487 GEN_NEW_SAMPLE(),
488 GEN_FRAME(0, module_base_address + 0x20),
489 GEN_NEW_SAMPLE(),
490 GEN_FRAME(0, module_base_address + 0x10),
491 GEN_NEW_SAMPLE(),
492 GEN_FRAME(0, module_base_address + 0x10),
493
494 GEN_ADD_PHASE(1),
495 GEN_NEW_SAMPLE(),
496 GEN_FRAME(0, module_base_address + 0x10),
497 GEN_NEW_SAMPLE(),
498 GEN_FRAME(0, module_base_address + 0x20),
499 GEN_NEW_SAMPLE(),
500 GEN_FRAME(0, module_base_address + 0x10),
501 GEN_NEW_SAMPLE(),
502 GEN_FRAME(0, module_base_address + 0x10),
503
504 GEN_END(),
383 }; 505 };
384 506
385 // Duplicate samples in slots 0, 2, and 3. 507 const ExpectedProtoModule expected_proto_modules[] = {
386 const Frame sample_frames[][1] = { 508 { module_name, module_md5, module_base_address },
387 { Frame(module_base_address + 0x10, 0), },
388 { Frame(module_base_address + 0x20, 0), },
389 { Frame(module_base_address + 0x10, 0), },
390 { Frame(module_base_address + 0x10, 0) }
391 }; 509 };
392 510
393 Profile profile; 511 const ExpectedProtoEntry expected_proto_entries[] = {
394 profile.modules.insert(profile.modules.end(), &modules[0], 512 { 0, 0x10 },
395 &modules[0] + arraysize(modules)); 513 { 0, 0x20 },
514 };
515 const ExpectedProtoSample expected_proto_samples[] = {
516 { 1, &expected_proto_entries[0], 1, 1 },
517 { 0, &expected_proto_entries[1], 1, 1 },
518 { 0, &expected_proto_entries[0], 1, 2 },
519 { 2, &expected_proto_entries[0], 1, 1 },
520 { 0, &expected_proto_entries[1], 1, 1 },
521 { 0, &expected_proto_entries[0], 1, 2 },
522 };
396 523
397 for (size_t i = 0; i < arraysize(sample_frames); ++i) { 524 const ExpectedProtoProfile expected_proto_profiles[] = {
398 profile.samples.push_back(Sample()); 525 {
399 Sample& sample = profile.samples.back(); 526 100, 10,
400 sample.insert(sample.end(), &sample_frames[i][0], 527 expected_proto_modules, arraysize(expected_proto_modules),
401 &sample_frames[i][0] + arraysize(sample_frames[i])); 528 expected_proto_samples, arraysize(expected_proto_samples),
402 } 529 },
530 };
403 531
404 profile.profile_duration = base::TimeDelta::FromMilliseconds(100);
405 profile.sampling_period = base::TimeDelta::FromMilliseconds(10);
406 Profiles profiles; 532 Profiles profiles;
407 profiles.push_back(std::move(profile)); 533 GenerateProfiles(&profiles, test_profiles_generator);
534 ASSERT_EQ(arraysize(expected_proto_profiles), profiles.size());
408 535
409 CallStackProfileMetricsProvider provider; 536 CallStackProfileMetricsProvider provider;
410 provider.OnRecordingEnabled(); 537 provider.OnRecordingEnabled();
411 AppendProfiles(CallStackProfileParams(CallStackProfileParams::BROWSER_PROCESS, 538 AppendProfiles(CallStackProfileParams(CallStackProfileParams::BROWSER_PROCESS,
412 CallStackProfileParams::UI_THREAD, 539 CallStackProfileParams::UI_THREAD,
413 CallStackProfileParams::PROCESS_STARTUP, 540 CallStackProfileParams::PROCESS_STARTUP,
414 CallStackProfileParams::PRESERVE_ORDER), 541 CallStackProfileParams::PRESERVE_ORDER),
415 std::move(profiles)); 542 std::move(profiles));
416 ChromeUserMetricsExtension uma_proto; 543 ChromeUserMetricsExtension uma_proto;
417 provider.ProvideGeneralMetrics(&uma_proto); 544 provider.ProvideGeneralMetrics(&uma_proto);
418 545
419 ASSERT_EQ(1, uma_proto.sampled_profile().size()); 546 ASSERT_EQ(static_cast<int>(arraysize(expected_proto_profiles)),
420 const SampledProfile& sampled_profile = uma_proto.sampled_profile().Get(0); 547 uma_proto.sampled_profile().size());
421 ASSERT_TRUE(sampled_profile.has_call_stack_profile()); 548 for (size_t p = 0; p < arraysize(expected_proto_profiles); ++p) {
422 const CallStackProfile& call_stack_profile = 549 SCOPED_TRACE("profile " + base::SizeTToString(p));
423 sampled_profile.call_stack_profile(); 550 VerifyProfileProto(uma_proto.sampled_profile().Get(p),
424 551 expected_proto_profiles[p]);
425 ASSERT_EQ(3, call_stack_profile.sample().size());
426 for (int i = 0; i < 3; ++i) {
427 SCOPED_TRACE("sample " + base::IntToString(i));
428 const CallStackProfile::Sample& proto_sample =
429 call_stack_profile.sample().Get(i);
430 ASSERT_EQ(static_cast<int>(arraysize(sample_frames[i])),
431 proto_sample.entry().size());
432 ASSERT_TRUE(proto_sample.has_count());
433 EXPECT_EQ(i == 2 ? 2u : 1u, proto_sample.count());
434 for (size_t j = 0; j < arraysize(sample_frames[i]); ++j) {
435 SCOPED_TRACE("frame " + base::SizeTToString(j));
436 const CallStackProfile::Entry& entry = proto_sample.entry().Get(j);
437 ASSERT_TRUE(entry.has_address());
438 const char* instruction_pointer = reinterpret_cast<const char*>(
439 sample_frames[i][j].instruction_pointer);
440 const char* module_base_address = reinterpret_cast<const char*>(
441 modules[sample_frames[i][j].module_index].base_address);
442 EXPECT_EQ(
443 static_cast<uint64_t>(instruction_pointer - module_base_address),
444 entry.address());
445 ASSERT_TRUE(entry.has_module_id_index());
446 EXPECT_EQ(sample_frames[i][j].module_index,
447 static_cast<size_t>(entry.module_id_index()));
448 }
449 } 552 }
450 } 553 }
451 554
452 // Checks that unknown modules produce an empty Entry. 555 // Checks that unknown modules produce an empty Entry.
453 TEST_F(CallStackProfileMetricsProviderTest, UnknownModule) { 556 TEST_F(CallStackProfileMetricsProviderTest, UnknownModule) {
454 const Frame frame(0x1000, Frame::kUnknownModuleIndex); 557 const ProfilesGenerator test_profiles_generator[] = {
558 GEN_NEW_PROFILE(100, 10),
559 GEN_NEW_SAMPLE(),
560 GEN_FRAME(Frame::kUnknownModuleIndex, 0x1234),
561 GEN_END(),
562 };
455 563
456 Profile profile; 564 const ExpectedProtoEntry expected_proto_entries[] = {
565 { -1, 0 },
566 };
567 const ExpectedProtoSample expected_proto_samples[] = {
568 { 0, &expected_proto_entries[0], 1, 1 },
569 };
457 570
458 profile.samples.push_back(Sample(1, frame)); 571 const ExpectedProtoProfile expected_proto_profiles[] = {
572 {
573 100, 10,
574 nullptr, 0,
575 expected_proto_samples, arraysize(expected_proto_samples),
576 },
577 };
459 578
460 profile.profile_duration = base::TimeDelta::FromMilliseconds(100);
461 profile.sampling_period = base::TimeDelta::FromMilliseconds(10);
462 Profiles profiles; 579 Profiles profiles;
463 profiles.push_back(std::move(profile)); 580 GenerateProfiles(&profiles, test_profiles_generator);
581 ASSERT_EQ(arraysize(expected_proto_profiles), profiles.size());
464 582
465 CallStackProfileMetricsProvider provider; 583 CallStackProfileMetricsProvider provider;
466 provider.OnRecordingEnabled(); 584 provider.OnRecordingEnabled();
467 AppendProfiles( 585 AppendProfiles(
468 CallStackProfileParams(CallStackProfileParams::BROWSER_PROCESS, 586 CallStackProfileParams(CallStackProfileParams::BROWSER_PROCESS,
469 CallStackProfileParams::UI_THREAD, 587 CallStackProfileParams::UI_THREAD,
470 CallStackProfileParams::PROCESS_STARTUP, 588 CallStackProfileParams::PROCESS_STARTUP,
471 CallStackProfileParams::MAY_SHUFFLE), 589 CallStackProfileParams::MAY_SHUFFLE),
472 std::move(profiles)); 590 std::move(profiles));
473 ChromeUserMetricsExtension uma_proto; 591 ChromeUserMetricsExtension uma_proto;
474 provider.ProvideGeneralMetrics(&uma_proto); 592 provider.ProvideGeneralMetrics(&uma_proto);
475 593
476 ASSERT_EQ(1, uma_proto.sampled_profile().size()); 594 ASSERT_EQ(static_cast<int>(arraysize(expected_proto_profiles)),
477 const SampledProfile& sampled_profile = uma_proto.sampled_profile().Get(0); 595 uma_proto.sampled_profile().size());
478 ASSERT_TRUE(sampled_profile.has_call_stack_profile()); 596 for (size_t p = 0; p < arraysize(expected_proto_profiles); ++p) {
479 const CallStackProfile& call_stack_profile = 597 SCOPED_TRACE("profile " + base::SizeTToString(p));
480 sampled_profile.call_stack_profile(); 598 VerifyProfileProto(uma_proto.sampled_profile().Get(p),
481 599 expected_proto_profiles[p]);
482 ASSERT_EQ(1, call_stack_profile.sample().size()); 600 }
483 const CallStackProfile::Sample& proto_sample =
484 call_stack_profile.sample().Get(0);
485 ASSERT_EQ(1, proto_sample.entry().size());
486 ASSERT_TRUE(proto_sample.has_count());
487 EXPECT_EQ(1u, proto_sample.count());
488 const CallStackProfile::Entry& entry = proto_sample.entry().Get(0);
489 EXPECT_FALSE(entry.has_address());
490 EXPECT_FALSE(entry.has_module_id_index());
491 } 601 }
492 602
493 // Checks that pending profiles are only passed back to ProvideGeneralMetrics 603 // Checks that pending profiles are only passed back to ProvideGeneralMetrics
494 // once. 604 // once.
495 TEST_F(CallStackProfileMetricsProviderTest, ProfilesProvidedOnlyOnce) { 605 TEST_F(CallStackProfileMetricsProviderTest, ProfilesProvidedOnlyOnce) {
496 CallStackProfileMetricsProvider provider; 606 CallStackProfileMetricsProvider provider;
497 for (int i = 0; i < 2; ++i) { 607 for (int r = 0; r < 2; ++r) {
498 Profile profile; 608 const ProfilesGenerator test_profiles_generator[] = {
499 profile.samples.push_back( 609 // Use the sampling period to distinguish the two profiles.
500 Sample(1, Frame(0x1000, Frame::kUnknownModuleIndex))); 610 GEN_NEW_PROFILE(100, r),
611 GEN_NEW_SAMPLE(),
612 GEN_FRAME(Frame::kUnknownModuleIndex, 0x1234),
613 GEN_END(),
614 };
501 615
502 profile.profile_duration = base::TimeDelta::FromMilliseconds(100);
503 // Use the sampling period to distinguish the two profiles.
504 profile.sampling_period = base::TimeDelta::FromMilliseconds(i);
505 Profiles profiles; 616 Profiles profiles;
506 profiles.push_back(std::move(profile)); 617 GenerateProfiles(&profiles, test_profiles_generator);
618 ASSERT_EQ(1U, profiles.size());
507 619
620 CallStackProfileMetricsProvider provider;
508 provider.OnRecordingEnabled(); 621 provider.OnRecordingEnabled();
509 AppendProfiles( 622 AppendProfiles(
510 CallStackProfileParams(CallStackProfileParams::BROWSER_PROCESS, 623 CallStackProfileParams(CallStackProfileParams::BROWSER_PROCESS,
511 CallStackProfileParams::UI_THREAD, 624 CallStackProfileParams::UI_THREAD,
512 CallStackProfileParams::PROCESS_STARTUP, 625 CallStackProfileParams::PROCESS_STARTUP,
513 CallStackProfileParams::MAY_SHUFFLE), 626 CallStackProfileParams::MAY_SHUFFLE),
514 std::move(profiles)); 627 std::move(profiles));
515 ChromeUserMetricsExtension uma_proto; 628 ChromeUserMetricsExtension uma_proto;
516 provider.ProvideGeneralMetrics(&uma_proto); 629 provider.ProvideGeneralMetrics(&uma_proto);
517 630
518 ASSERT_EQ(1, uma_proto.sampled_profile().size()); 631 ASSERT_EQ(1, uma_proto.sampled_profile().size());
519 const SampledProfile& sampled_profile = uma_proto.sampled_profile().Get(0); 632 const SampledProfile& sampled_profile = uma_proto.sampled_profile().Get(0);
520 ASSERT_TRUE(sampled_profile.has_call_stack_profile()); 633 ASSERT_TRUE(sampled_profile.has_call_stack_profile());
521 const CallStackProfile& call_stack_profile = 634 const CallStackProfile& call_stack_profile =
522 sampled_profile.call_stack_profile(); 635 sampled_profile.call_stack_profile();
523 ASSERT_TRUE(call_stack_profile.has_sampling_period_ms()); 636 ASSERT_TRUE(call_stack_profile.has_sampling_period_ms());
524 EXPECT_EQ(i, call_stack_profile.sampling_period_ms()); 637 EXPECT_EQ(r, call_stack_profile.sampling_period_ms());
525 } 638 }
526 } 639 }
527 640
528 // Checks that pending profiles are provided to ProvideGeneralMetrics 641 // Checks that pending profiles are provided to ProvideGeneralMetrics
529 // when collected before CallStackProfileMetricsProvider is instantiated. 642 // when collected before CallStackProfileMetricsProvider is instantiated.
530 TEST_F(CallStackProfileMetricsProviderTest, 643 TEST_F(CallStackProfileMetricsProviderTest,
531 ProfilesProvidedWhenCollectedBeforeInstantiation) { 644 ProfilesProvidedWhenCollectedBeforeInstantiation) {
532 Profile profile; 645 const ProfilesGenerator test_profiles_generator[] = {
533 profile.samples.push_back( 646 GEN_NEW_PROFILE(100, 10),
534 Sample(1, Frame(0x1000, Frame::kUnknownModuleIndex))); 647 GEN_NEW_SAMPLE(),
648 GEN_FRAME(Frame::kUnknownModuleIndex, 0x1234),
649 GEN_END(),
650 };
535 651
536 profile.profile_duration = base::TimeDelta::FromMilliseconds(100);
537 profile.sampling_period = base::TimeDelta::FromMilliseconds(10);
538 Profiles profiles; 652 Profiles profiles;
539 profiles.push_back(std::move(profile)); 653 GenerateProfiles(&profiles, test_profiles_generator);
654 ASSERT_EQ(1U, profiles.size());
540 655
541 AppendProfiles( 656 AppendProfiles(
542 CallStackProfileParams(CallStackProfileParams::BROWSER_PROCESS, 657 CallStackProfileParams(CallStackProfileParams::BROWSER_PROCESS,
543 CallStackProfileParams::UI_THREAD, 658 CallStackProfileParams::UI_THREAD,
544 CallStackProfileParams::PROCESS_STARTUP, 659 CallStackProfileParams::PROCESS_STARTUP,
545 CallStackProfileParams::MAY_SHUFFLE), 660 CallStackProfileParams::MAY_SHUFFLE),
546 std::move(profiles)); 661 std::move(profiles));
547 662
548 CallStackProfileMetricsProvider provider; 663 CallStackProfileMetricsProvider provider;
549 provider.OnRecordingEnabled(); 664 provider.OnRecordingEnabled();
550 ChromeUserMetricsExtension uma_proto; 665 ChromeUserMetricsExtension uma_proto;
551 provider.ProvideGeneralMetrics(&uma_proto); 666 provider.ProvideGeneralMetrics(&uma_proto);
552 667
553 EXPECT_EQ(1, uma_proto.sampled_profile_size()); 668 EXPECT_EQ(1, uma_proto.sampled_profile_size());
554 } 669 }
555 670
556 // Checks that pending profiles are not provided to ProvideGeneralMetrics 671 // Checks that pending profiles are not provided to ProvideGeneralMetrics
557 // while recording is disabled. 672 // while recording is disabled.
558 TEST_F(CallStackProfileMetricsProviderTest, ProfilesNotProvidedWhileDisabled) { 673 TEST_F(CallStackProfileMetricsProviderTest, ProfilesNotProvidedWhileDisabled) {
559 Profile profile; 674 const ProfilesGenerator test_profiles_generator[] = {
560 profile.samples.push_back( 675 GEN_NEW_PROFILE(100, 10),
561 Sample(1, Frame(0x1000, Frame::kUnknownModuleIndex))); 676 GEN_NEW_SAMPLE(),
677 GEN_FRAME(Frame::kUnknownModuleIndex, 0x1234),
678 GEN_END(),
679 };
562 680
563 profile.profile_duration = base::TimeDelta::FromMilliseconds(100);
564 profile.sampling_period = base::TimeDelta::FromMilliseconds(10);
565 Profiles profiles; 681 Profiles profiles;
566 profiles.push_back(std::move(profile)); 682 GenerateProfiles(&profiles, test_profiles_generator);
683 ASSERT_EQ(1U, profiles.size());
567 684
568 CallStackProfileMetricsProvider provider; 685 CallStackProfileMetricsProvider provider;
569 provider.OnRecordingDisabled(); 686 provider.OnRecordingDisabled();
570 AppendProfiles( 687 AppendProfiles(
571 CallStackProfileParams(CallStackProfileParams::BROWSER_PROCESS, 688 CallStackProfileParams(CallStackProfileParams::BROWSER_PROCESS,
572 CallStackProfileParams::UI_THREAD, 689 CallStackProfileParams::UI_THREAD,
573 CallStackProfileParams::PROCESS_STARTUP, 690 CallStackProfileParams::PROCESS_STARTUP,
574 CallStackProfileParams::MAY_SHUFFLE), 691 CallStackProfileParams::MAY_SHUFFLE),
575 std::move(profiles)); 692 std::move(profiles));
576 ChromeUserMetricsExtension uma_proto; 693 ChromeUserMetricsExtension uma_proto;
577 provider.ProvideGeneralMetrics(&uma_proto); 694 provider.ProvideGeneralMetrics(&uma_proto);
578 695
579 EXPECT_EQ(0, uma_proto.sampled_profile_size()); 696 EXPECT_EQ(0, uma_proto.sampled_profile_size());
580 } 697 }
581 698
582 // Checks that pending profiles are not provided to ProvideGeneralMetrics 699 // Checks that pending profiles are not provided to ProvideGeneralMetrics
583 // if recording is disabled while profiling. 700 // if recording is disabled while profiling.
584 TEST_F(CallStackProfileMetricsProviderTest, 701 TEST_F(CallStackProfileMetricsProviderTest,
585 ProfilesNotProvidedAfterChangeToDisabled) { 702 ProfilesNotProvidedAfterChangeToDisabled) {
586 Profile profile; 703 const ProfilesGenerator test_profiles_generator[] = {
587 profile.samples.push_back( 704 GEN_NEW_PROFILE(100, 10),
588 Sample(1, Frame(0x1000, Frame::kUnknownModuleIndex))); 705 GEN_NEW_SAMPLE(),
589 706 GEN_FRAME(Frame::kUnknownModuleIndex, 0x1234),
590 profile.profile_duration = base::TimeDelta::FromMilliseconds(100); 707 GEN_END(),
591 profile.sampling_period = base::TimeDelta::FromMilliseconds(10); 708 };
592 709
593 CallStackProfileMetricsProvider provider; 710 CallStackProfileMetricsProvider provider;
594 provider.OnRecordingEnabled(); 711 provider.OnRecordingEnabled();
595 base::StackSamplingProfiler::CompletedCallback callback = 712 base::StackSamplingProfiler::CompletedCallback callback =
596 CallStackProfileMetricsProvider::GetProfilerCallback( 713 CallStackProfileMetricsProvider::GetProfilerCallback(
597 CallStackProfileParams(CallStackProfileParams::BROWSER_PROCESS, 714 CallStackProfileParams(CallStackProfileParams::BROWSER_PROCESS,
598 CallStackProfileParams::UI_THREAD, 715 CallStackProfileParams::UI_THREAD,
599 CallStackProfileParams::PROCESS_STARTUP, 716 CallStackProfileParams::PROCESS_STARTUP,
600 CallStackProfileParams::MAY_SHUFFLE)); 717 CallStackProfileParams::MAY_SHUFFLE));
601 718
602 provider.OnRecordingDisabled(); 719 provider.OnRecordingDisabled();
603 Profiles profiles; 720 Profiles profiles;
604 profiles.push_back(std::move(profile)); 721 GenerateProfiles(&profiles, test_profiles_generator);
605 callback.Run(std::move(profiles)); 722 callback.Run(std::move(profiles));
606 ChromeUserMetricsExtension uma_proto; 723 ChromeUserMetricsExtension uma_proto;
607 provider.ProvideGeneralMetrics(&uma_proto); 724 provider.ProvideGeneralMetrics(&uma_proto);
608 725
609 EXPECT_EQ(0, uma_proto.sampled_profile_size()); 726 EXPECT_EQ(0, uma_proto.sampled_profile_size());
610 } 727 }
611 728
612 // Checks that pending profiles are not provided to ProvideGeneralMetrics if 729 // Checks that pending profiles are not provided to ProvideGeneralMetrics if
613 // recording is enabled, but then disabled and reenabled while profiling. 730 // recording is enabled, but then disabled and reenabled while profiling.
614 TEST_F(CallStackProfileMetricsProviderTest, 731 TEST_F(CallStackProfileMetricsProviderTest,
615 ProfilesNotProvidedAfterChangeToDisabledThenEnabled) { 732 ProfilesNotProvidedAfterChangeToDisabledThenEnabled) {
616 Profile profile; 733 const ProfilesGenerator test_profiles_generator[] = {
617 profile.samples.push_back( 734 GEN_NEW_PROFILE(100, 10),
618 Sample(1, Frame(0x1000, Frame::kUnknownModuleIndex))); 735 GEN_NEW_SAMPLE(),
619 736 GEN_FRAME(Frame::kUnknownModuleIndex, 0x1234),
620 profile.profile_duration = base::TimeDelta::FromMilliseconds(100); 737 GEN_END(),
621 profile.sampling_period = base::TimeDelta::FromMilliseconds(10); 738 };
622 739
623 CallStackProfileMetricsProvider provider; 740 CallStackProfileMetricsProvider provider;
624 provider.OnRecordingEnabled(); 741 provider.OnRecordingEnabled();
625 base::StackSamplingProfiler::CompletedCallback callback = 742 base::StackSamplingProfiler::CompletedCallback callback =
626 CallStackProfileMetricsProvider::GetProfilerCallback( 743 CallStackProfileMetricsProvider::GetProfilerCallback(
627 CallStackProfileParams(CallStackProfileParams::BROWSER_PROCESS, 744 CallStackProfileParams(CallStackProfileParams::BROWSER_PROCESS,
628 CallStackProfileParams::UI_THREAD, 745 CallStackProfileParams::UI_THREAD,
629 CallStackProfileParams::PROCESS_STARTUP, 746 CallStackProfileParams::PROCESS_STARTUP,
630 CallStackProfileParams::MAY_SHUFFLE)); 747 CallStackProfileParams::MAY_SHUFFLE));
631 748
632 provider.OnRecordingDisabled(); 749 provider.OnRecordingDisabled();
633 provider.OnRecordingEnabled(); 750 provider.OnRecordingEnabled();
634 Profiles profiles; 751 Profiles profiles;
635 profiles.push_back(std::move(profile)); 752 GenerateProfiles(&profiles, test_profiles_generator);
636 callback.Run(std::move(profiles)); 753 callback.Run(std::move(profiles));
637 ChromeUserMetricsExtension uma_proto; 754 ChromeUserMetricsExtension uma_proto;
638 provider.ProvideGeneralMetrics(&uma_proto); 755 provider.ProvideGeneralMetrics(&uma_proto);
639 756
640 EXPECT_EQ(0, uma_proto.sampled_profile_size()); 757 EXPECT_EQ(0, uma_proto.sampled_profile_size());
641 } 758 }
642 759
643 // Checks that pending profiles are not provided to ProvideGeneralMetrics 760 // Checks that pending profiles are not provided to ProvideGeneralMetrics
644 // if recording is disabled, but then enabled while profiling. 761 // if recording is disabled, but then enabled while profiling.
645 TEST_F(CallStackProfileMetricsProviderTest, 762 TEST_F(CallStackProfileMetricsProviderTest,
646 ProfilesNotProvidedAfterChangeFromDisabled) { 763 ProfilesNotProvidedAfterChangeFromDisabled) {
647 Profile profile; 764 const ProfilesGenerator test_profiles_generator[] = {
648 profile.samples.push_back( 765 GEN_NEW_PROFILE(100, 10),
649 Sample(1, Frame(0x1000, Frame::kUnknownModuleIndex))); 766 GEN_NEW_SAMPLE(),
650 767 GEN_FRAME(Frame::kUnknownModuleIndex, 0x1234),
651 profile.profile_duration = base::TimeDelta::FromMilliseconds(100); 768 GEN_END(),
652 profile.sampling_period = base::TimeDelta::FromMilliseconds(10); 769 };
653 770
654 CallStackProfileMetricsProvider provider; 771 CallStackProfileMetricsProvider provider;
655 provider.OnRecordingDisabled(); 772 provider.OnRecordingDisabled();
656 base::StackSamplingProfiler::CompletedCallback callback = 773 base::StackSamplingProfiler::CompletedCallback callback =
657 CallStackProfileMetricsProvider::GetProfilerCallback( 774 CallStackProfileMetricsProvider::GetProfilerCallback(
658 CallStackProfileParams(CallStackProfileParams::BROWSER_PROCESS, 775 CallStackProfileParams(CallStackProfileParams::BROWSER_PROCESS,
659 CallStackProfileParams::UI_THREAD, 776 CallStackProfileParams::UI_THREAD,
660 CallStackProfileParams::PROCESS_STARTUP, 777 CallStackProfileParams::PROCESS_STARTUP,
661 CallStackProfileParams::MAY_SHUFFLE)); 778 CallStackProfileParams::MAY_SHUFFLE));
662 779
663 provider.OnRecordingEnabled(); 780 provider.OnRecordingEnabled();
664 Profiles profiles; 781 Profiles profiles;
665 profiles.push_back(std::move(profile)); 782 GenerateProfiles(&profiles, test_profiles_generator);
666 callback.Run(std::move(profiles)); 783 callback.Run(std::move(profiles));
667 ChromeUserMetricsExtension uma_proto; 784 ChromeUserMetricsExtension uma_proto;
668 provider.ProvideGeneralMetrics(&uma_proto); 785 provider.ProvideGeneralMetrics(&uma_proto);
669 786
670 EXPECT_EQ(0, uma_proto.sampled_profile_size()); 787 EXPECT_EQ(0, uma_proto.sampled_profile_size());
671 } 788 }
672 789
673 } // namespace metrics 790 } // namespace metrics
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698