| OLD | NEW |
| 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 "base/metrics/field_trial.h" |
| 7 #include "base/profiler/stack_sampling_profiler.h" | 8 #include "base/profiler/stack_sampling_profiler.h" |
| 8 #include "base/strings/string_number_conversions.h" | 9 #include "base/strings/string_number_conversions.h" |
| 9 #include "components/metrics/proto/chrome_user_metrics_extension.pb.h" | 10 #include "components/metrics/proto/chrome_user_metrics_extension.pb.h" |
| 11 #include "components/variations/entropy_provider.h" |
| 10 #include "testing/gtest/include/gtest/gtest.h" | 12 #include "testing/gtest/include/gtest/gtest.h" |
| 11 | 13 |
| 12 using base::StackSamplingProfiler; | 14 using base::StackSamplingProfiler; |
| 13 using Frame = StackSamplingProfiler::Frame; | 15 using Frame = StackSamplingProfiler::Frame; |
| 14 using Module = StackSamplingProfiler::Module; | 16 using Module = StackSamplingProfiler::Module; |
| 15 using Profile = StackSamplingProfiler::CallStackProfile; | 17 using Profile = StackSamplingProfiler::CallStackProfile; |
| 16 using Sample = StackSamplingProfiler::Sample; | 18 using Sample = StackSamplingProfiler::Sample; |
| 17 | 19 |
| 18 namespace metrics { | 20 namespace metrics { |
| 19 | 21 |
| 22 // This test fixture enables the field trial that |
| 23 // CallStackProfileMetricsProvider depends on to report profiles. |
| 24 class CallStackProfileMetricsProviderTest : public testing::Test { |
| 25 public: |
| 26 CallStackProfileMetricsProviderTest() |
| 27 : field_trial_list_(new base::FieldTrialList( |
| 28 new metrics::SHA1EntropyProvider("foo"))) { |
| 29 base::FieldTrialList::CreateFieldTrial( |
| 30 FieldTrialState::kFieldTrialName, |
| 31 FieldTrialState::kReportProfilesGroupName); |
| 32 } |
| 33 |
| 34 ~CallStackProfileMetricsProviderTest() override {} |
| 35 |
| 36 private: |
| 37 // Exposes field trial/group names from the CallStackProfileMetricsProvider. |
| 38 class FieldTrialState : public CallStackProfileMetricsProvider { |
| 39 public: |
| 40 using CallStackProfileMetricsProvider::kFieldTrialName; |
| 41 using CallStackProfileMetricsProvider::kReportProfilesGroupName; |
| 42 }; |
| 43 |
| 44 const scoped_ptr<base::FieldTrialList> field_trial_list_; |
| 45 }; |
| 46 |
| 20 // Checks that all properties from multiple profiles are filled as expected. | 47 // Checks that all properties from multiple profiles are filled as expected. |
| 21 TEST(CallStackProfileMetricsProviderTest, MultipleProfiles) { | 48 TEST_F(CallStackProfileMetricsProviderTest, MultipleProfiles) { |
| 22 const uintptr_t module1_base_address = 0x1000; | 49 const uintptr_t module1_base_address = 0x1000; |
| 23 const uintptr_t module2_base_address = 0x2000; | 50 const uintptr_t module2_base_address = 0x2000; |
| 24 const uintptr_t module3_base_address = 0x3000; | 51 const uintptr_t module3_base_address = 0x3000; |
| 25 | 52 |
| 26 const Module profile_modules[][2] = { | 53 const Module profile_modules[][2] = { |
| 27 { | 54 { |
| 28 Module( | 55 Module( |
| 29 reinterpret_cast<const void*>(module1_base_address), | 56 reinterpret_cast<const void*>(module1_base_address), |
| 30 "ABCD", | 57 "ABCD", |
| 31 #if defined(OS_WIN) | 58 #if defined(OS_WIN) |
| (...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 158 } | 185 } |
| 159 | 186 |
| 160 profile.profile_duration = profile_durations[i]; | 187 profile.profile_duration = profile_durations[i]; |
| 161 profile.sampling_period = profile_sampling_periods[i]; | 188 profile.sampling_period = profile_sampling_periods[i]; |
| 162 profile.preserve_sample_ordering = false; | 189 profile.preserve_sample_ordering = false; |
| 163 | 190 |
| 164 profiles.push_back(profile); | 191 profiles.push_back(profile); |
| 165 } | 192 } |
| 166 | 193 |
| 167 CallStackProfileMetricsProvider provider; | 194 CallStackProfileMetricsProvider provider; |
| 168 provider.SetSourceProfilesForTesting(profiles); | 195 provider.AppendSourceProfilesForTesting(profiles); |
| 169 ChromeUserMetricsExtension uma_proto; | 196 ChromeUserMetricsExtension uma_proto; |
| 170 provider.ProvideGeneralMetrics(&uma_proto); | 197 provider.ProvideGeneralMetrics(&uma_proto); |
| 171 | 198 |
| 172 ASSERT_EQ(static_cast<int>(arraysize(profile_sample_frames)), | 199 ASSERT_EQ(static_cast<int>(arraysize(profile_sample_frames)), |
| 173 uma_proto.sampled_profile().size()); | 200 uma_proto.sampled_profile().size()); |
| 174 for (size_t i = 0; i < arraysize(profile_sample_frames); ++i) { | 201 for (size_t i = 0; i < arraysize(profile_sample_frames); ++i) { |
| 175 SCOPED_TRACE("profile " + base::IntToString(i)); | 202 SCOPED_TRACE("profile " + base::IntToString(i)); |
| 176 const SampledProfile& sampled_profile = uma_proto.sampled_profile().Get(i); | 203 const SampledProfile& sampled_profile = uma_proto.sampled_profile().Get(i); |
| 177 ASSERT_TRUE(sampled_profile.has_call_stack_profile()); | 204 ASSERT_TRUE(sampled_profile.has_call_stack_profile()); |
| 178 const CallStackProfile& call_stack_profile = | 205 const CallStackProfile& call_stack_profile = |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 222 EXPECT_EQ(profile_durations[i].InMilliseconds(), | 249 EXPECT_EQ(profile_durations[i].InMilliseconds(), |
| 223 call_stack_profile.profile_duration_ms()); | 250 call_stack_profile.profile_duration_ms()); |
| 224 ASSERT_TRUE(call_stack_profile.has_sampling_period_ms()); | 251 ASSERT_TRUE(call_stack_profile.has_sampling_period_ms()); |
| 225 EXPECT_EQ(profile_sampling_periods[i].InMilliseconds(), | 252 EXPECT_EQ(profile_sampling_periods[i].InMilliseconds(), |
| 226 call_stack_profile.sampling_period_ms()); | 253 call_stack_profile.sampling_period_ms()); |
| 227 } | 254 } |
| 228 } | 255 } |
| 229 | 256 |
| 230 // Checks that all duplicate samples are collapsed with | 257 // Checks that all duplicate samples are collapsed with |
| 231 // preserve_sample_ordering = false. | 258 // preserve_sample_ordering = false. |
| 232 TEST(CallStackProfileMetricsProviderTest, RepeatedStacksUnordered) { | 259 TEST_F(CallStackProfileMetricsProviderTest, RepeatedStacksUnordered) { |
| 233 const uintptr_t module_base_address = 0x1000; | 260 const uintptr_t module_base_address = 0x1000; |
| 234 | 261 |
| 235 const Module modules[] = { | 262 const Module modules[] = { |
| 236 Module( | 263 Module( |
| 237 reinterpret_cast<const void*>(module_base_address), | 264 reinterpret_cast<const void*>(module_base_address), |
| 238 "ABCD", | 265 "ABCD", |
| 239 #if defined(OS_WIN) | 266 #if defined(OS_WIN) |
| 240 base::FilePath(L"c:\\some\\path\\to\\chrome.exe") | 267 base::FilePath(L"c:\\some\\path\\to\\chrome.exe") |
| 241 #else | 268 #else |
| 242 base::FilePath("/some/path/to/chrome") | 269 base::FilePath("/some/path/to/chrome") |
| (...skipping 18 matching lines...) Expand all Loading... |
| 261 Sample& sample = profile.samples.back(); | 288 Sample& sample = profile.samples.back(); |
| 262 sample.insert(sample.end(), &sample_frames[i][0], | 289 sample.insert(sample.end(), &sample_frames[i][0], |
| 263 &sample_frames[i][0] + arraysize(sample_frames[i])); | 290 &sample_frames[i][0] + arraysize(sample_frames[i])); |
| 264 } | 291 } |
| 265 | 292 |
| 266 profile.profile_duration = base::TimeDelta::FromMilliseconds(100); | 293 profile.profile_duration = base::TimeDelta::FromMilliseconds(100); |
| 267 profile.sampling_period = base::TimeDelta::FromMilliseconds(10); | 294 profile.sampling_period = base::TimeDelta::FromMilliseconds(10); |
| 268 profile.preserve_sample_ordering = false; | 295 profile.preserve_sample_ordering = false; |
| 269 | 296 |
| 270 CallStackProfileMetricsProvider provider; | 297 CallStackProfileMetricsProvider provider; |
| 271 provider.SetSourceProfilesForTesting(std::vector<Profile>(1, profile)); | 298 provider.AppendSourceProfilesForTesting(std::vector<Profile>(1, profile)); |
| 272 ChromeUserMetricsExtension uma_proto; | 299 ChromeUserMetricsExtension uma_proto; |
| 273 provider.ProvideGeneralMetrics(&uma_proto); | 300 provider.ProvideGeneralMetrics(&uma_proto); |
| 274 | 301 |
| 275 ASSERT_EQ(1, uma_proto.sampled_profile().size()); | 302 ASSERT_EQ(1, uma_proto.sampled_profile().size()); |
| 276 const SampledProfile& sampled_profile = uma_proto.sampled_profile().Get(0); | 303 const SampledProfile& sampled_profile = uma_proto.sampled_profile().Get(0); |
| 277 ASSERT_TRUE(sampled_profile.has_call_stack_profile()); | 304 ASSERT_TRUE(sampled_profile.has_call_stack_profile()); |
| 278 const CallStackProfile& call_stack_profile = | 305 const CallStackProfile& call_stack_profile = |
| 279 sampled_profile.call_stack_profile(); | 306 sampled_profile.call_stack_profile(); |
| 280 | 307 |
| 281 ASSERT_EQ(2, call_stack_profile.sample().size()); | 308 ASSERT_EQ(2, call_stack_profile.sample().size()); |
| (...skipping 17 matching lines...) Expand all Loading... |
| 299 entry.address()); | 326 entry.address()); |
| 300 ASSERT_TRUE(entry.has_module_id_index()); | 327 ASSERT_TRUE(entry.has_module_id_index()); |
| 301 EXPECT_EQ(sample_frames[i][j].module_index, | 328 EXPECT_EQ(sample_frames[i][j].module_index, |
| 302 static_cast<size_t>(entry.module_id_index())); | 329 static_cast<size_t>(entry.module_id_index())); |
| 303 } | 330 } |
| 304 } | 331 } |
| 305 } | 332 } |
| 306 | 333 |
| 307 // Checks that only contiguous duplicate samples are collapsed with | 334 // Checks that only contiguous duplicate samples are collapsed with |
| 308 // preserve_sample_ordering = true. | 335 // preserve_sample_ordering = true. |
| 309 TEST(CallStackProfileMetricsProviderTest, RepeatedStacksOrdered) { | 336 TEST_F(CallStackProfileMetricsProviderTest, RepeatedStacksOrdered) { |
| 310 const uintptr_t module_base_address = 0x1000; | 337 const uintptr_t module_base_address = 0x1000; |
| 311 | 338 |
| 312 const Module modules[] = { | 339 const Module modules[] = { |
| 313 Module( | 340 Module( |
| 314 reinterpret_cast<const void*>(module_base_address), | 341 reinterpret_cast<const void*>(module_base_address), |
| 315 "ABCD", | 342 "ABCD", |
| 316 #if defined(OS_WIN) | 343 #if defined(OS_WIN) |
| 317 base::FilePath(L"c:\\some\\path\\to\\chrome.exe") | 344 base::FilePath(L"c:\\some\\path\\to\\chrome.exe") |
| 318 #else | 345 #else |
| 319 base::FilePath("/some/path/to/chrome") | 346 base::FilePath("/some/path/to/chrome") |
| (...skipping 18 matching lines...) Expand all Loading... |
| 338 Sample& sample = profile.samples.back(); | 365 Sample& sample = profile.samples.back(); |
| 339 sample.insert(sample.end(), &sample_frames[i][0], | 366 sample.insert(sample.end(), &sample_frames[i][0], |
| 340 &sample_frames[i][0] + arraysize(sample_frames[i])); | 367 &sample_frames[i][0] + arraysize(sample_frames[i])); |
| 341 } | 368 } |
| 342 | 369 |
| 343 profile.profile_duration = base::TimeDelta::FromMilliseconds(100); | 370 profile.profile_duration = base::TimeDelta::FromMilliseconds(100); |
| 344 profile.sampling_period = base::TimeDelta::FromMilliseconds(10); | 371 profile.sampling_period = base::TimeDelta::FromMilliseconds(10); |
| 345 profile.preserve_sample_ordering = true; | 372 profile.preserve_sample_ordering = true; |
| 346 | 373 |
| 347 CallStackProfileMetricsProvider provider; | 374 CallStackProfileMetricsProvider provider; |
| 348 provider.SetSourceProfilesForTesting(std::vector<Profile>(1, profile)); | 375 provider.AppendSourceProfilesForTesting(std::vector<Profile>(1, profile)); |
| 349 ChromeUserMetricsExtension uma_proto; | 376 ChromeUserMetricsExtension uma_proto; |
| 350 provider.ProvideGeneralMetrics(&uma_proto); | 377 provider.ProvideGeneralMetrics(&uma_proto); |
| 351 | 378 |
| 352 ASSERT_EQ(1, uma_proto.sampled_profile().size()); | 379 ASSERT_EQ(1, uma_proto.sampled_profile().size()); |
| 353 const SampledProfile& sampled_profile = uma_proto.sampled_profile().Get(0); | 380 const SampledProfile& sampled_profile = uma_proto.sampled_profile().Get(0); |
| 354 ASSERT_TRUE(sampled_profile.has_call_stack_profile()); | 381 ASSERT_TRUE(sampled_profile.has_call_stack_profile()); |
| 355 const CallStackProfile& call_stack_profile = | 382 const CallStackProfile& call_stack_profile = |
| 356 sampled_profile.call_stack_profile(); | 383 sampled_profile.call_stack_profile(); |
| 357 | 384 |
| 358 ASSERT_EQ(3, call_stack_profile.sample().size()); | 385 ASSERT_EQ(3, call_stack_profile.sample().size()); |
| (...skipping 15 matching lines...) Expand all Loading... |
| 374 modules[sample_frames[i][j].module_index].base_address); | 401 modules[sample_frames[i][j].module_index].base_address); |
| 375 EXPECT_EQ(static_cast<uint64>(instruction_pointer - module_base_address), | 402 EXPECT_EQ(static_cast<uint64>(instruction_pointer - module_base_address), |
| 376 entry.address()); | 403 entry.address()); |
| 377 ASSERT_TRUE(entry.has_module_id_index()); | 404 ASSERT_TRUE(entry.has_module_id_index()); |
| 378 EXPECT_EQ(sample_frames[i][j].module_index, | 405 EXPECT_EQ(sample_frames[i][j].module_index, |
| 379 static_cast<size_t>(entry.module_id_index())); | 406 static_cast<size_t>(entry.module_id_index())); |
| 380 } | 407 } |
| 381 } | 408 } |
| 382 } | 409 } |
| 383 | 410 |
| 384 | |
| 385 // Checks that unknown modules produce an empty Entry. | 411 // Checks that unknown modules produce an empty Entry. |
| 386 TEST(CallStackProfileMetricsProviderTest, UnknownModule) { | 412 TEST_F(CallStackProfileMetricsProviderTest, UnknownModule) { |
| 387 const Frame frame(reinterpret_cast<const void*>(0x1000), | 413 const Frame frame(reinterpret_cast<const void*>(0x1000), |
| 388 Frame::kUnknownModuleIndex); | 414 Frame::kUnknownModuleIndex); |
| 389 | 415 |
| 390 Profile profile; | 416 Profile profile; |
| 391 | 417 |
| 392 profile.samples.push_back(Sample(1, frame)); | 418 profile.samples.push_back(Sample(1, frame)); |
| 393 | 419 |
| 394 profile.profile_duration = base::TimeDelta::FromMilliseconds(100); | 420 profile.profile_duration = base::TimeDelta::FromMilliseconds(100); |
| 395 profile.sampling_period = base::TimeDelta::FromMilliseconds(10); | 421 profile.sampling_period = base::TimeDelta::FromMilliseconds(10); |
| 396 profile.preserve_sample_ordering = false; | 422 profile.preserve_sample_ordering = false; |
| 397 | 423 |
| 398 CallStackProfileMetricsProvider provider; | 424 CallStackProfileMetricsProvider provider; |
| 399 provider.SetSourceProfilesForTesting(std::vector<Profile>(1, profile)); | 425 provider.AppendSourceProfilesForTesting(std::vector<Profile>(1, profile)); |
| 400 ChromeUserMetricsExtension uma_proto; | 426 ChromeUserMetricsExtension uma_proto; |
| 401 provider.ProvideGeneralMetrics(&uma_proto); | 427 provider.ProvideGeneralMetrics(&uma_proto); |
| 402 | 428 |
| 403 ASSERT_EQ(1, uma_proto.sampled_profile().size()); | 429 ASSERT_EQ(1, uma_proto.sampled_profile().size()); |
| 404 const SampledProfile& sampled_profile = uma_proto.sampled_profile().Get(0); | 430 const SampledProfile& sampled_profile = uma_proto.sampled_profile().Get(0); |
| 405 ASSERT_TRUE(sampled_profile.has_call_stack_profile()); | 431 ASSERT_TRUE(sampled_profile.has_call_stack_profile()); |
| 406 const CallStackProfile& call_stack_profile = | 432 const CallStackProfile& call_stack_profile = |
| 407 sampled_profile.call_stack_profile(); | 433 sampled_profile.call_stack_profile(); |
| 408 | 434 |
| 409 ASSERT_EQ(1, call_stack_profile.sample().size()); | 435 ASSERT_EQ(1, call_stack_profile.sample().size()); |
| 410 const CallStackProfile::Sample& proto_sample = | 436 const CallStackProfile::Sample& proto_sample = |
| 411 call_stack_profile.sample().Get(0); | 437 call_stack_profile.sample().Get(0); |
| 412 ASSERT_EQ(1, proto_sample.entry().size()); | 438 ASSERT_EQ(1, proto_sample.entry().size()); |
| 413 ASSERT_TRUE(proto_sample.has_count()); | 439 ASSERT_TRUE(proto_sample.has_count()); |
| 414 EXPECT_EQ(1u, proto_sample.count()); | 440 EXPECT_EQ(1u, proto_sample.count()); |
| 415 const CallStackProfile::Entry& entry = proto_sample.entry().Get(0); | 441 const CallStackProfile::Entry& entry = proto_sample.entry().Get(0); |
| 416 EXPECT_FALSE(entry.has_address()); | 442 EXPECT_FALSE(entry.has_address()); |
| 417 EXPECT_FALSE(entry.has_module_id_index()); | 443 EXPECT_FALSE(entry.has_module_id_index()); |
| 418 } | 444 } |
| 419 | 445 |
| 446 // Checks that pending profiles are only passed back to ProvideGeneralMetrics |
| 447 // once. |
| 448 TEST_F(CallStackProfileMetricsProviderTest, ProfilesProvidedOnlyOnce) { |
| 449 CallStackProfileMetricsProvider provider; |
| 450 for (int i = 0; i < 2; ++i) { |
| 451 Profile profile; |
| 452 profile.samples.push_back(Sample(1, Frame( |
| 453 reinterpret_cast<const void*>(0x1000), Frame::kUnknownModuleIndex))); |
| 454 |
| 455 profile.profile_duration = base::TimeDelta::FromMilliseconds(100); |
| 456 // Use the sampling period to distinguish the two profiles. |
| 457 profile.sampling_period = base::TimeDelta::FromMilliseconds(i); |
| 458 profile.preserve_sample_ordering = false; |
| 459 |
| 460 provider.AppendSourceProfilesForTesting(std::vector<Profile>(1, profile)); |
| 461 ChromeUserMetricsExtension uma_proto; |
| 462 provider.ProvideGeneralMetrics(&uma_proto); |
| 463 |
| 464 ASSERT_EQ(1, uma_proto.sampled_profile().size()); |
| 465 const SampledProfile& sampled_profile = uma_proto.sampled_profile().Get(0); |
| 466 ASSERT_TRUE(sampled_profile.has_call_stack_profile()); |
| 467 const CallStackProfile& call_stack_profile = |
| 468 sampled_profile.call_stack_profile(); |
| 469 ASSERT_TRUE(call_stack_profile.has_sampling_period_ms()); |
| 470 EXPECT_EQ(i, call_stack_profile.sampling_period_ms()); |
| 471 } |
| 472 } |
| 473 |
| 420 } // namespace metrics | 474 } // namespace metrics |
| OLD | NEW |