Chromium Code Reviews| Index: components/metrics/call_stack_profile_metrics_provider_unittest.cc |
| diff --git a/components/metrics/call_stack_profile_metrics_provider_unittest.cc b/components/metrics/call_stack_profile_metrics_provider_unittest.cc |
| index 3e515b5c2db336cc09e2b1cbf66d5e4437cfa6af..4429fadfc278b7508f02a33c5d582052a85be46e 100644 |
| --- a/components/metrics/call_stack_profile_metrics_provider_unittest.cc |
| +++ b/components/metrics/call_stack_profile_metrics_provider_unittest.cc |
| @@ -27,6 +27,58 @@ using Profile = StackSamplingProfiler::CallStackProfile; |
| using Profiles = StackSamplingProfiler::CallStackProfiles; |
| using Sample = StackSamplingProfiler::Sample; |
| +namespace { |
| + |
| +using ProfilesGenerator = uint64_t; |
| + |
| +enum : ProfilesGenerator { |
| + kEndOfGenerator, |
| + kAddPhase, |
| + kNewProfile, |
| + kNewSample, |
| + kNextFrame, |
| + kDefineModule, |
| +}; |
| + |
| +struct ExpectedProtoModule { |
| + const char* build_id; |
| + uint64_t name_md5; |
| + uint64_t base_address; |
| +}; |
| + |
| +struct ExpectedProtoEntry { |
| + int32_t module_index; |
| + uint64_t address; |
| +}; |
| + |
| +struct ExpectedProtoSample { |
| + uint32_t process_phases; // Bit-field of expected phases. |
| + const ExpectedProtoEntry* entries; |
| + int entry_count; |
| + int64_t entry_repeats; |
| +}; |
| + |
| +struct ExpectedProtoProfile { |
| + int32_t duration_ms; |
| + int32_t period_ms; |
| + const ExpectedProtoModule* modules; |
| + int module_count; |
| + const ExpectedProtoSample* samples; |
| + int sample_count; |
| +}; |
| + |
| +} // namespace |
| + |
| +#define GEN_ADD_PHASE(phase) kAddPhase, phase |
| +#define GEN_NEW_PROFILE(duration_ms, interval_ms) \ |
| + kNewProfile, duration_ms, interval_ms |
| +#define GEN_NEW_SAMPLE() kNewSample |
| +#define GEN_FRAME(module, offset) kNextFrame, module, offset |
| +#define GEN_DEFINE_MODULE(name, path, base) \ |
| + kDefineModule, reinterpret_cast<uintptr_t>(name), \ |
| + reinterpret_cast<uintptr_t>(&path), base |
| +#define GEN_END() kEndOfGenerator |
| + |
| namespace metrics { |
| // This test fixture enables the field trial that |
| @@ -49,6 +101,12 @@ class CallStackProfileMetricsProviderTest : public testing::Test { |
| std::move(profiles)); |
| } |
| + // Utility to create a Profiles list from a generator constant. |
| + void GenerateProfiles(Profiles* profiles, const ProfilesGenerator* generator); |
| + |
| + void VerifyProfileProto(const SampledProfile& proto, |
| + const ExpectedProtoProfile& expected); |
| + |
| private: |
| // Exposes field trial/group names from the CallStackProfileMetricsProvider. |
| class TestState : public CallStackProfileMetricsProvider { |
| @@ -63,54 +121,110 @@ class CallStackProfileMetricsProviderTest : public testing::Test { |
| DISALLOW_COPY_AND_ASSIGN(CallStackProfileMetricsProviderTest); |
| }; |
| +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
|
| + 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.
|
| + const ProfilesGenerator* generator) { |
| + uint32_t process_phases = 0; |
| + Profile* profile = nullptr; |
| + |
| + while (true) { |
| + switch (*generator++) { |
| + case kEndOfGenerator: |
| + return; |
| + case kAddPhase: |
| + process_phases |= 1 << *generator++; |
| + break; |
| + case kNewProfile: |
| + profiles->push_back(Profile()); |
| + profile = &profiles->back(); |
| + profile->profile_duration = |
| + base::TimeDelta::FromMilliseconds(*generator++); |
| + profile->sampling_period = |
| + base::TimeDelta::FromMilliseconds(*generator++); |
| + break; |
| + case kNewSample: |
| + profile->samples.push_back(Sample()); |
| + profile->samples.back().process_phases = process_phases; |
| + break; |
| + case kNextFrame: { |
| + size_t index = static_cast<size_t>(*generator++); |
| + uintptr_t address = static_cast<uintptr_t>(*generator++); |
| + profile->samples.back().frames.push_back(Frame(address, index)); |
| + } 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.
|
| + case kDefineModule: { |
| + const char* name = |
| + reinterpret_cast<const char*>(static_cast<uintptr_t>(*generator++)); |
| + const base::FilePath* path = reinterpret_cast<const base::FilePath*>( |
| + static_cast<uintptr_t>(*generator++)); |
| + uintptr_t base = static_cast<uintptr_t>(*generator++); |
| + profile->modules.push_back(Module(base, name, *path)); |
| + } break; |
| + default: |
| + NOTREACHED(); |
| + }; |
| + } |
| +} |
| + |
| +void CallStackProfileMetricsProviderTest::VerifyProfileProto( |
| + const SampledProfile& proto, |
| + 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.
|
| + ASSERT_TRUE(proto.has_call_stack_profile()); |
| + const CallStackProfile& stack = proto.call_stack_profile(); |
| + |
| + ASSERT_TRUE(stack.has_profile_duration_ms()); |
| + EXPECT_EQ(expected.duration_ms, stack.profile_duration_ms()); |
| + ASSERT_TRUE(stack.has_sampling_period_ms()); |
| + EXPECT_EQ(expected.period_ms, stack.sampling_period_ms()); |
| + |
| + ASSERT_EQ(expected.module_count, stack.module_id().size()); |
| + for (int m = 0; m < expected.module_count; ++m) { |
| + SCOPED_TRACE("module " + base::IntToString(m)); |
| + const CallStackProfile::ModuleIdentifier& module_id = |
| + stack.module_id().Get(m); |
| + ASSERT_TRUE(module_id.has_build_id()); |
| + EXPECT_EQ(expected.modules[m].build_id, module_id.build_id()); |
| + ASSERT_TRUE(module_id.has_name_md5_prefix()); |
| + EXPECT_EQ(expected.modules[m].name_md5, module_id.name_md5_prefix()); |
| + } |
| + |
| + ASSERT_EQ(expected.sample_count, stack.sample().size()); |
| + for (int s = 0; s < expected.sample_count; ++s) { |
| + SCOPED_TRACE("sample " + base::IntToString(s)); |
| + const CallStackProfile::Sample& proto_sample = stack.sample().Get(s); |
| + |
| + uint32_t process_phases = 0; |
| + for (int i = 0; i < proto_sample.process_phase().size(); ++i) |
| + process_phases |= 1U << proto_sample.process_phase().Get(i); |
| + EXPECT_EQ(expected.samples[s].process_phases, process_phases); |
| + |
| + ASSERT_EQ(expected.samples[s].entry_count, proto_sample.entry().size()); |
| + ASSERT_TRUE(proto_sample.has_count()); |
| + EXPECT_EQ(expected.samples[s].entry_repeats, proto_sample.count()); |
| + for (int e = 0; e < expected.samples[s].entry_count; ++e) { |
| + SCOPED_TRACE("entry " + base::SizeTToString(e)); |
| + const CallStackProfile::Entry& entry = proto_sample.entry().Get(e); |
| + if (expected.samples[s].entries[e].module_index >= 0) { |
| + ASSERT_TRUE(entry.has_module_id_index()); |
| + EXPECT_EQ(expected.samples[s].entries[e].module_index, |
| + entry.module_id_index()); |
| + ASSERT_TRUE(entry.has_address()); |
| + EXPECT_EQ(expected.samples[s].entries[e].address, entry.address()); |
| + } else { |
| + EXPECT_FALSE(entry.has_module_id_index()); |
| + EXPECT_FALSE(entry.has_address()); |
| + } |
| + } |
| + } |
| +} |
| + |
| // Checks that all properties from multiple profiles are filled as expected. |
| TEST_F(CallStackProfileMetricsProviderTest, MultipleProfiles) { |
| - const uintptr_t module1_base_address = 0x1000; |
| - const uintptr_t module2_base_address = 0x2000; |
| - const uintptr_t module3_base_address = 0x3000; |
| - |
| - const Module profile_modules[][2] = { |
| - { |
| - Module( |
| - module1_base_address, |
| - "ABCD", |
| -#if defined(OS_WIN) |
| - base::FilePath(L"c:\\some\\path\\to\\chrome.exe") |
| -#else |
| - base::FilePath("/some/path/to/chrome") |
| -#endif |
| - ), |
| - Module( |
| - module2_base_address, |
| - "EFGH", |
| -#if defined(OS_WIN) |
| - base::FilePath(L"c:\\some\\path\\to\\third_party.dll") |
| -#else |
| - base::FilePath("/some/path/to/third_party.so") |
| -#endif |
| - ), |
| - }, |
| - { |
| - Module( |
| - module3_base_address, |
| - "MNOP", |
| -#if defined(OS_WIN) |
| - base::FilePath(L"c:\\some\\path\\to\\third_party2.dll") |
| -#else |
| - base::FilePath("/some/path/to/third_party2.so") |
| -#endif |
| - ), |
| - Module( // Repeated from the first profile. |
| - module1_base_address, |
| - "ABCD", |
| -#if defined(OS_WIN) |
| - base::FilePath(L"c:\\some\\path\\to\\chrome.exe") |
| -#else |
| - base::FilePath("/some/path/to/chrome") |
| -#endif |
| - ) |
| - } |
| - }; |
| + const uintptr_t moduleA_base_address = 0x1000; |
| + const uintptr_t moduleB_base_address = 0x2000; |
| + const uintptr_t moduleC_base_address = 0x3000; |
| + const char* moduleA_name = "ABCD"; |
| + const char* moduleB_name = "EFGH"; |
| + const char* moduleC_name = "MNOP"; |
| // Values for Windows generated with: |
| // perl -MDigest::MD5=md5 -MEncode=encode |
| @@ -121,21 +235,21 @@ TEST_F(CallStackProfileMetricsProviderTest, MultipleProfiles) { |
| // perl -MDigest::MD5=md5 |
| // -e 'for(@ARGV){printf "%x\n", unpack "Q>", md5 $_}' |
| // chrome third_party.so third_party2.so |
| - const uint64_t profile_expected_name_md5_prefixes[][2] = { |
| - { |
| #if defined(OS_WIN) |
| - 0x46c3e4166659ac02ULL, 0x7e2b8bfddeae1abaULL |
| + uint64_t moduleA_md5 = 0x46C3E4166659AC02ULL; |
| + uint64_t moduleB_md5 = 0x7E2B8BFDDEAE1ABAULL; |
| + uint64_t moduleC_md5 = 0x87B66F4573A4D5CAULL; |
| + base::FilePath moduleA_path(L"c:\\some\\path\\to\\chrome.exe"); |
| + base::FilePath moduleB_path(L"c:\\some\\path\\to\\third_party.dll"); |
| + base::FilePath moduleC_path(L"c:\\some\\path\\to\\third_party2.dll"); |
| #else |
| - 0x554838a8451ac36cUL, 0x843661148659c9f8UL |
| + uint64_t moduleA_md5 = 0x554838A8451AC36CULL; |
| + uint64_t moduleB_md5 = 0x843661148659C9F8ULL; |
| + uint64_t moduleC_md5 = 0xB4647E539FA6EC9EULL; |
| + base::FilePath moduleA_path("/some/path/to/chrome"); |
| + base::FilePath moduleB_path("/some/path/to/third_party.so"); |
| + base::FilePath moduleC_path("/some/path/to/third_party2.so"); |
| #endif |
| - }, |
| - { |
| -#if defined(OS_WIN) |
| - 0x87b66f4573a4d5caULL, 0x46c3e4166659ac02ULL |
| -#else |
| - 0xb4647e539fa6ec9eUL, 0x554838a8451ac36cUL |
| -#endif |
| - }}; |
| // Represents two stack samples for each of two profiles, where each stack |
| // contains three frames. Each frame contains an instruction pointer and a |
| @@ -146,63 +260,100 @@ TEST_F(CallStackProfileMetricsProviderTest, MultipleProfiles) { |
| // of 0x10 from the module's base address, the next-to-top frame in module 1 |
| // at an offset of 0x20 from the module's base address, and the bottom frame |
| // in module 0 at an offset of 0x30 from the module's base address |
| - const Frame profile_sample_frames[][2][3] = { |
| - { |
| + const ProfilesGenerator test_profiles_generator[] = { |
| + 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.
|
| + GEN_DEFINE_MODULE(moduleA_name, moduleA_path, moduleA_base_address), |
| + GEN_DEFINE_MODULE(moduleB_name, moduleB_path, moduleB_base_address), |
| + |
| + GEN_NEW_SAMPLE(), |
| + GEN_FRAME(0, moduleA_base_address + 0x10), |
| + GEN_FRAME(1, moduleB_base_address + 0x20), |
| + GEN_FRAME(0, moduleA_base_address + 0x30), |
| + GEN_NEW_SAMPLE(), |
| + GEN_FRAME(1, moduleB_base_address + 0x10), |
| + GEN_FRAME(0, moduleA_base_address + 0x20), |
| + GEN_FRAME(1, moduleB_base_address + 0x30), |
| + |
| + GEN_NEW_PROFILE(200, 20), |
| + GEN_DEFINE_MODULE(moduleC_name, moduleC_path, moduleC_base_address), |
| + GEN_DEFINE_MODULE(moduleA_name, moduleA_path, moduleA_base_address), |
| + |
| + GEN_NEW_SAMPLE(), |
| + GEN_FRAME(0, moduleC_base_address + 0x10), |
| + GEN_FRAME(1, moduleA_base_address + 0x20), |
| + GEN_FRAME(0, moduleC_base_address + 0x30), |
| + GEN_NEW_SAMPLE(), |
| + GEN_FRAME(1, moduleA_base_address + 0x10), |
| + GEN_FRAME(0, moduleC_base_address + 0x20), |
| + GEN_FRAME(1, moduleA_base_address + 0x30), |
| + |
| + GEN_END(), |
| + }; |
| + |
| + const ExpectedProtoModule expected_proto_modules1[] = { |
| + { moduleA_name, moduleA_md5, moduleA_base_address }, |
| + { moduleB_name, moduleB_md5, moduleB_base_address } |
| + }; |
| + |
| + const ExpectedProtoEntry expected_proto_entries11[] = { |
| + { 0, 0x10 }, |
| + { 1, 0x20 }, |
| + { 0, 0x30 }, |
| + }; |
| + const ExpectedProtoEntry expected_proto_entries12[] = { |
| + { 1, 0x10 }, |
| + { 0, 0x20 }, |
| + { 1, 0x30 }, |
| + }; |
| + const ExpectedProtoSample expected_proto_samples1[] = { |
| { |
| - Frame(module1_base_address + 0x10, 0), |
| - Frame(module2_base_address + 0x20, 1), |
| - Frame(module1_base_address + 0x30, 0) |
| + 0, expected_proto_entries11, arraysize(expected_proto_entries11), 1, |
| }, |
| { |
| - Frame(module2_base_address + 0x10, 1), |
| - Frame(module1_base_address + 0x20, 0), |
| - Frame(module2_base_address + 0x30, 1) |
| - } |
| - }, |
| - { |
| - { |
| - Frame(module3_base_address + 0x10, 0), |
| - Frame(module1_base_address + 0x20, 1), |
| - Frame(module3_base_address + 0x30, 0) |
| + 0, expected_proto_entries12, arraysize(expected_proto_entries12), 1, |
| }, |
| - { |
| - Frame(module1_base_address + 0x10, 1), |
| - Frame(module3_base_address + 0x20, 0), |
| - Frame(module1_base_address + 0x30, 1) |
| - } |
| - } |
| }; |
| - base::TimeDelta profile_durations[2] = { |
| - base::TimeDelta::FromMilliseconds(100), |
| - base::TimeDelta::FromMilliseconds(200) |
| + const ExpectedProtoModule expected_proto_modules2[] = { |
| + { moduleC_name, moduleC_md5, moduleC_base_address }, |
| + { moduleA_name, moduleA_md5, moduleA_base_address } |
| }; |
| - base::TimeDelta profile_sampling_periods[2] = { |
| - base::TimeDelta::FromMilliseconds(10), |
| - base::TimeDelta::FromMilliseconds(20) |
| + const ExpectedProtoEntry expected_proto_entries21[] = { |
| + { 0, 0x10 }, |
| + { 1, 0x20 }, |
| + { 0, 0x30 }, |
| + }; |
| + const ExpectedProtoEntry expected_proto_entries22[] = { |
| + { 1, 0x10 }, |
| + { 0, 0x20 }, |
| + { 1, 0x30 }, |
| + }; |
| + const ExpectedProtoSample expected_proto_samples2[] = { |
| + { |
| + 0, expected_proto_entries11, arraysize(expected_proto_entries21), 1, |
| + }, |
| + { |
| + 0, expected_proto_entries12, arraysize(expected_proto_entries22), 1, |
| + }, |
| }; |
| - std::vector<Profile> profiles; |
| - for (size_t i = 0; i < arraysize(profile_sample_frames); ++i) { |
| - Profile profile; |
| - profile.modules.insert( |
| - profile.modules.end(), &profile_modules[i][0], |
| - &profile_modules[i][0] + arraysize(profile_modules[i])); |
| - |
| - for (size_t j = 0; j < arraysize(profile_sample_frames[i]); ++j) { |
| - profile.samples.push_back(Sample()); |
| - Sample& sample = profile.samples.back(); |
| - sample.insert(sample.end(), &profile_sample_frames[i][j][0], |
| - &profile_sample_frames[i][j][0] + |
| - arraysize(profile_sample_frames[i][j])); |
| - } |
| - |
| - profile.profile_duration = profile_durations[i]; |
| - profile.sampling_period = profile_sampling_periods[i]; |
| + const ExpectedProtoProfile expected_proto_profiles[] = { |
| + { |
| + 100, 10, |
| + expected_proto_modules1, arraysize(expected_proto_modules1), |
| + expected_proto_samples1, arraysize(expected_proto_samples1), |
| + }, |
| + { |
| + 200, 20, |
| + expected_proto_modules2, arraysize(expected_proto_modules2), |
| + expected_proto_samples2, arraysize(expected_proto_samples2), |
| + }, |
| + }; |
| - profiles.push_back(std::move(profile)); |
| - } |
| + Profiles profiles; |
| + GenerateProfiles(&profiles, test_profiles_generator); |
| + ASSERT_EQ(arraysize(expected_proto_profiles), profiles.size()); |
| CallStackProfileMetricsProvider provider; |
| provider.OnRecordingEnabled(); |
| @@ -215,68 +366,12 @@ TEST_F(CallStackProfileMetricsProviderTest, MultipleProfiles) { |
| ChromeUserMetricsExtension uma_proto; |
| provider.ProvideGeneralMetrics(&uma_proto); |
| - ASSERT_EQ(static_cast<int>(arraysize(profile_sample_frames)), |
| + ASSERT_EQ(static_cast<int>(arraysize(expected_proto_profiles)), |
| uma_proto.sampled_profile().size()); |
| - for (size_t i = 0; i < arraysize(profile_sample_frames); ++i) { |
| - SCOPED_TRACE("profile " + base::SizeTToString(i)); |
| - const SampledProfile& sampled_profile = uma_proto.sampled_profile().Get(i); |
| - ASSERT_TRUE(sampled_profile.has_call_stack_profile()); |
| - const CallStackProfile& call_stack_profile = |
| - sampled_profile.call_stack_profile(); |
| - |
| - ASSERT_EQ(static_cast<int>(arraysize(profile_sample_frames[i])), |
| - call_stack_profile.sample().size()); |
| - for (size_t j = 0; j < arraysize(profile_sample_frames[i]); ++j) { |
| - SCOPED_TRACE("sample " + base::SizeTToString(j)); |
| - const CallStackProfile::Sample& proto_sample = |
| - call_stack_profile.sample().Get(j); |
| - ASSERT_EQ(static_cast<int>(arraysize(profile_sample_frames[i][j])), |
| - proto_sample.entry().size()); |
| - ASSERT_TRUE(proto_sample.has_count()); |
| - EXPECT_EQ(1u, proto_sample.count()); |
| - for (size_t k = 0; k < arraysize(profile_sample_frames[i][j]); ++k) { |
| - SCOPED_TRACE("frame " + base::SizeTToString(k)); |
| - const CallStackProfile::Entry& entry = proto_sample.entry().Get(k); |
| - ASSERT_TRUE(entry.has_address()); |
| - const char* instruction_pointer = reinterpret_cast<const char*>( |
| - profile_sample_frames[i][j][k].instruction_pointer); |
| - const char* module_base_address = reinterpret_cast<const char*>( |
| - profile_modules[i][profile_sample_frames[i][j][k].module_index] |
| - .base_address); |
| - EXPECT_EQ( |
| - static_cast<uint64_t>(instruction_pointer - module_base_address), |
| - entry.address()); |
| - ASSERT_TRUE(entry.has_module_id_index()); |
| - EXPECT_EQ(profile_sample_frames[i][j][k].module_index, |
| - static_cast<size_t>(entry.module_id_index())); |
| - } |
| - } |
| - |
| - ASSERT_EQ(static_cast<int>(arraysize(profile_modules[i])), |
| - call_stack_profile.module_id().size()); |
| - for (size_t j = 0; j < arraysize(profile_modules[i]); ++j) { |
| - SCOPED_TRACE("module " + base::SizeTToString(j)); |
| - const CallStackProfile::ModuleIdentifier& module_identifier = |
| - call_stack_profile.module_id().Get(j); |
| - ASSERT_TRUE(module_identifier.has_build_id()); |
| - EXPECT_EQ(profile_modules[i][j].id, module_identifier.build_id()); |
| - ASSERT_TRUE(module_identifier.has_name_md5_prefix()); |
| - EXPECT_EQ(profile_expected_name_md5_prefixes[i][j], |
| - module_identifier.name_md5_prefix()); |
| - } |
| - |
| - ASSERT_TRUE(call_stack_profile.has_profile_duration_ms()); |
| - EXPECT_EQ(profile_durations[i].InMilliseconds(), |
| - call_stack_profile.profile_duration_ms()); |
| - ASSERT_TRUE(call_stack_profile.has_sampling_period_ms()); |
| - EXPECT_EQ(profile_sampling_periods[i].InMilliseconds(), |
| - call_stack_profile.sampling_period_ms()); |
| - ASSERT_TRUE(sampled_profile.has_process()); |
| - EXPECT_EQ(BROWSER_PROCESS, sampled_profile.process()); |
| - ASSERT_TRUE(sampled_profile.has_thread()); |
| - EXPECT_EQ(UI_THREAD, sampled_profile.thread()); |
| - ASSERT_TRUE(sampled_profile.has_trigger_event()); |
| - EXPECT_EQ(SampledProfile::PROCESS_STARTUP, sampled_profile.trigger_event()); |
| + for (size_t p = 0; p < arraysize(expected_proto_profiles); ++p) { |
| + SCOPED_TRACE("profile " + base::SizeTToString(p)); |
| + VerifyProfileProto(uma_proto.sampled_profile().Get(p), |
| + expected_proto_profiles[p]); |
| } |
| } |
| @@ -284,42 +379,69 @@ TEST_F(CallStackProfileMetricsProviderTest, MultipleProfiles) { |
| // preserve_sample_ordering = false. |
| TEST_F(CallStackProfileMetricsProviderTest, RepeatedStacksUnordered) { |
| const uintptr_t module_base_address = 0x1000; |
| + const char* module_name = "ABCD"; |
| - const Module modules[] = { |
| - Module( |
| - module_base_address, |
| - "ABCD", |
| #if defined(OS_WIN) |
| - base::FilePath(L"c:\\some\\path\\to\\chrome.exe") |
| + uint64_t module_md5 = 0x46C3E4166659AC02ULL; |
| + base::FilePath module_path(L"c:\\some\\path\\to\\chrome.exe"); |
| #else |
| - base::FilePath("/some/path/to/chrome") |
| + uint64_t module_md5 = 0x554838A8451AC36CULL; |
| + base::FilePath module_path("/some/path/to/chrome"); |
| #endif |
| - ) |
| + |
| + const ProfilesGenerator test_profiles_generator[] = { |
| + GEN_NEW_PROFILE(100, 10), |
| + GEN_DEFINE_MODULE(module_name, module_path, module_base_address), |
| + |
| + GEN_ADD_PHASE(0), |
| + GEN_NEW_SAMPLE(), |
| + GEN_FRAME(0, module_base_address + 0x10), |
| + GEN_NEW_SAMPLE(), |
| + GEN_FRAME(0, module_base_address + 0x20), |
| + GEN_NEW_SAMPLE(), |
| + GEN_FRAME(0, module_base_address + 0x10), |
| + GEN_NEW_SAMPLE(), |
| + GEN_FRAME(0, module_base_address + 0x10), |
| + |
| + GEN_ADD_PHASE(1), |
| + GEN_NEW_SAMPLE(), |
| + GEN_FRAME(0, module_base_address + 0x10), |
| + GEN_NEW_SAMPLE(), |
| + GEN_FRAME(0, module_base_address + 0x20), |
| + GEN_NEW_SAMPLE(), |
| + GEN_FRAME(0, module_base_address + 0x10), |
| + GEN_NEW_SAMPLE(), |
| + GEN_FRAME(0, module_base_address + 0x10), |
| + |
| + GEN_END(), |
| }; |
| - // Duplicate samples in slots 0, 2, and 3. |
| - const Frame sample_frames[][1] = { |
| - { Frame(module_base_address + 0x10, 0), }, |
| - { Frame(module_base_address + 0x20, 0), }, |
| - { Frame(module_base_address + 0x10, 0), }, |
| - { Frame(module_base_address + 0x10, 0) } |
| + const ExpectedProtoModule expected_proto_modules[] = { |
| + { module_name, module_md5, module_base_address }, |
| }; |
| - Profile profile; |
| - profile.modules.insert(profile.modules.end(), &modules[0], |
| - &modules[0] + arraysize(modules)); |
| + const ExpectedProtoEntry expected_proto_entries[] = { |
| + { 0, 0x10 }, |
| + { 0, 0x20 }, |
| + }; |
| + const ExpectedProtoSample expected_proto_samples[] = { |
| + { 1, &expected_proto_entries[0], 1, 3 }, |
| + { 1, &expected_proto_entries[1], 1, 1 }, |
| + { 3, &expected_proto_entries[0], 1, 3 }, |
| + { 3, &expected_proto_entries[1], 1, 1 }, |
| + }; |
| - for (size_t i = 0; i < arraysize(sample_frames); ++i) { |
| - profile.samples.push_back(Sample()); |
| - Sample& sample = profile.samples.back(); |
| - sample.insert(sample.end(), &sample_frames[i][0], |
| - &sample_frames[i][0] + arraysize(sample_frames[i])); |
| - } |
| + const ExpectedProtoProfile expected_proto_profiles[] = { |
| + { |
| + 100, 10, |
| + expected_proto_modules, arraysize(expected_proto_modules), |
| + expected_proto_samples, arraysize(expected_proto_samples), |
| + }, |
| + }; |
| - profile.profile_duration = base::TimeDelta::FromMilliseconds(100); |
| - profile.sampling_period = base::TimeDelta::FromMilliseconds(10); |
| Profiles profiles; |
| - profiles.push_back(std::move(profile)); |
| + GenerateProfiles(&profiles, test_profiles_generator); |
| + ASSERT_EQ(arraysize(expected_proto_profiles), profiles.size()); |
| CallStackProfileMetricsProvider provider; |
| provider.OnRecordingEnabled(); |
| @@ -332,36 +454,12 @@ TEST_F(CallStackProfileMetricsProviderTest, RepeatedStacksUnordered) { |
| ChromeUserMetricsExtension uma_proto; |
| provider.ProvideGeneralMetrics(&uma_proto); |
| - ASSERT_EQ(1, uma_proto.sampled_profile().size()); |
| - const SampledProfile& sampled_profile = uma_proto.sampled_profile().Get(0); |
| - ASSERT_TRUE(sampled_profile.has_call_stack_profile()); |
| - const CallStackProfile& call_stack_profile = |
| - sampled_profile.call_stack_profile(); |
| - |
| - ASSERT_EQ(2, call_stack_profile.sample().size()); |
| - for (int i = 0; i < 2; ++i) { |
| - SCOPED_TRACE("sample " + base::IntToString(i)); |
| - const CallStackProfile::Sample& proto_sample = |
| - call_stack_profile.sample().Get(i); |
| - ASSERT_EQ(static_cast<int>(arraysize(sample_frames[i])), |
| - proto_sample.entry().size()); |
| - ASSERT_TRUE(proto_sample.has_count()); |
| - EXPECT_EQ(i == 0 ? 3u : 1u, proto_sample.count()); |
| - for (size_t j = 0; j < arraysize(sample_frames[i]); ++j) { |
| - SCOPED_TRACE("frame " + base::SizeTToString(j)); |
| - const CallStackProfile::Entry& entry = proto_sample.entry().Get(j); |
| - ASSERT_TRUE(entry.has_address()); |
| - const char* instruction_pointer = reinterpret_cast<const char*>( |
| - sample_frames[i][j].instruction_pointer); |
| - const char* module_base_address = reinterpret_cast<const char*>( |
| - modules[sample_frames[i][j].module_index].base_address); |
| - EXPECT_EQ( |
| - static_cast<uint64_t>(instruction_pointer - module_base_address), |
| - entry.address()); |
| - ASSERT_TRUE(entry.has_module_id_index()); |
| - EXPECT_EQ(sample_frames[i][j].module_index, |
| - static_cast<size_t>(entry.module_id_index())); |
| - } |
| + ASSERT_EQ(static_cast<int>(arraysize(expected_proto_profiles)), |
| + uma_proto.sampled_profile().size()); |
| + for (size_t p = 0; p < arraysize(expected_proto_profiles); ++p) { |
| + SCOPED_TRACE("profile " + base::SizeTToString(p)); |
| + VerifyProfileProto(uma_proto.sampled_profile().Get(p), |
| + expected_proto_profiles[p]); |
| } |
| } |
| @@ -369,42 +467,71 @@ TEST_F(CallStackProfileMetricsProviderTest, RepeatedStacksUnordered) { |
| // preserve_sample_ordering = true. |
| TEST_F(CallStackProfileMetricsProviderTest, RepeatedStacksOrdered) { |
| const uintptr_t module_base_address = 0x1000; |
| + const char* module_name = "ABCD"; |
| - const Module modules[] = { |
| - Module( |
| - module_base_address, |
| - "ABCD", |
| #if defined(OS_WIN) |
| - base::FilePath(L"c:\\some\\path\\to\\chrome.exe") |
| + uint64_t module_md5 = 0x46C3E4166659AC02ULL; |
| + base::FilePath module_path(L"c:\\some\\path\\to\\chrome.exe"); |
| #else |
| - base::FilePath("/some/path/to/chrome") |
| + uint64_t module_md5 = 0x554838A8451AC36CULL; |
| + base::FilePath module_path("/some/path/to/chrome"); |
| #endif |
| - ) |
| + |
| + const ProfilesGenerator test_profiles_generator[] = { |
| + GEN_NEW_PROFILE(100, 10), |
| + GEN_DEFINE_MODULE(module_name, module_path, module_base_address), |
| + |
| + GEN_ADD_PHASE(0), |
| + GEN_NEW_SAMPLE(), |
| + GEN_FRAME(0, module_base_address + 0x10), |
| + GEN_NEW_SAMPLE(), |
| + GEN_FRAME(0, module_base_address + 0x20), |
| + GEN_NEW_SAMPLE(), |
| + GEN_FRAME(0, module_base_address + 0x10), |
| + GEN_NEW_SAMPLE(), |
| + GEN_FRAME(0, module_base_address + 0x10), |
| + |
| + GEN_ADD_PHASE(1), |
| + GEN_NEW_SAMPLE(), |
| + GEN_FRAME(0, module_base_address + 0x10), |
| + GEN_NEW_SAMPLE(), |
| + GEN_FRAME(0, module_base_address + 0x20), |
| + GEN_NEW_SAMPLE(), |
| + GEN_FRAME(0, module_base_address + 0x10), |
| + GEN_NEW_SAMPLE(), |
| + GEN_FRAME(0, module_base_address + 0x10), |
| + |
| + GEN_END(), |
| }; |
| - // Duplicate samples in slots 0, 2, and 3. |
| - const Frame sample_frames[][1] = { |
| - { Frame(module_base_address + 0x10, 0), }, |
| - { Frame(module_base_address + 0x20, 0), }, |
| - { Frame(module_base_address + 0x10, 0), }, |
| - { Frame(module_base_address + 0x10, 0) } |
| + const ExpectedProtoModule expected_proto_modules[] = { |
| + { module_name, module_md5, module_base_address }, |
| }; |
| - Profile profile; |
| - profile.modules.insert(profile.modules.end(), &modules[0], |
| - &modules[0] + arraysize(modules)); |
| + const ExpectedProtoEntry expected_proto_entries[] = { |
| + { 0, 0x10 }, |
| + { 0, 0x20 }, |
| + }; |
| + const ExpectedProtoSample expected_proto_samples[] = { |
| + { 1, &expected_proto_entries[0], 1, 1 }, |
| + { 0, &expected_proto_entries[1], 1, 1 }, |
| + { 0, &expected_proto_entries[0], 1, 2 }, |
| + { 2, &expected_proto_entries[0], 1, 1 }, |
| + { 0, &expected_proto_entries[1], 1, 1 }, |
| + { 0, &expected_proto_entries[0], 1, 2 }, |
| + }; |
| - for (size_t i = 0; i < arraysize(sample_frames); ++i) { |
| - profile.samples.push_back(Sample()); |
| - Sample& sample = profile.samples.back(); |
| - sample.insert(sample.end(), &sample_frames[i][0], |
| - &sample_frames[i][0] + arraysize(sample_frames[i])); |
| - } |
| + const ExpectedProtoProfile expected_proto_profiles[] = { |
| + { |
| + 100, 10, |
| + expected_proto_modules, arraysize(expected_proto_modules), |
| + expected_proto_samples, arraysize(expected_proto_samples), |
| + }, |
| + }; |
| - profile.profile_duration = base::TimeDelta::FromMilliseconds(100); |
| - profile.sampling_period = base::TimeDelta::FromMilliseconds(10); |
| Profiles profiles; |
| - profiles.push_back(std::move(profile)); |
| + GenerateProfiles(&profiles, test_profiles_generator); |
| + ASSERT_EQ(arraysize(expected_proto_profiles), profiles.size()); |
| CallStackProfileMetricsProvider provider; |
| provider.OnRecordingEnabled(); |
| @@ -416,51 +543,42 @@ TEST_F(CallStackProfileMetricsProviderTest, RepeatedStacksOrdered) { |
| ChromeUserMetricsExtension uma_proto; |
| provider.ProvideGeneralMetrics(&uma_proto); |
| - ASSERT_EQ(1, uma_proto.sampled_profile().size()); |
| - const SampledProfile& sampled_profile = uma_proto.sampled_profile().Get(0); |
| - ASSERT_TRUE(sampled_profile.has_call_stack_profile()); |
| - const CallStackProfile& call_stack_profile = |
| - sampled_profile.call_stack_profile(); |
| - |
| - ASSERT_EQ(3, call_stack_profile.sample().size()); |
| - for (int i = 0; i < 3; ++i) { |
| - SCOPED_TRACE("sample " + base::IntToString(i)); |
| - const CallStackProfile::Sample& proto_sample = |
| - call_stack_profile.sample().Get(i); |
| - ASSERT_EQ(static_cast<int>(arraysize(sample_frames[i])), |
| - proto_sample.entry().size()); |
| - ASSERT_TRUE(proto_sample.has_count()); |
| - EXPECT_EQ(i == 2 ? 2u : 1u, proto_sample.count()); |
| - for (size_t j = 0; j < arraysize(sample_frames[i]); ++j) { |
| - SCOPED_TRACE("frame " + base::SizeTToString(j)); |
| - const CallStackProfile::Entry& entry = proto_sample.entry().Get(j); |
| - ASSERT_TRUE(entry.has_address()); |
| - const char* instruction_pointer = reinterpret_cast<const char*>( |
| - sample_frames[i][j].instruction_pointer); |
| - const char* module_base_address = reinterpret_cast<const char*>( |
| - modules[sample_frames[i][j].module_index].base_address); |
| - EXPECT_EQ( |
| - static_cast<uint64_t>(instruction_pointer - module_base_address), |
| - entry.address()); |
| - ASSERT_TRUE(entry.has_module_id_index()); |
| - EXPECT_EQ(sample_frames[i][j].module_index, |
| - static_cast<size_t>(entry.module_id_index())); |
| - } |
| + ASSERT_EQ(static_cast<int>(arraysize(expected_proto_profiles)), |
| + uma_proto.sampled_profile().size()); |
| + for (size_t p = 0; p < arraysize(expected_proto_profiles); ++p) { |
| + SCOPED_TRACE("profile " + base::SizeTToString(p)); |
| + VerifyProfileProto(uma_proto.sampled_profile().Get(p), |
| + expected_proto_profiles[p]); |
| } |
| } |
| // Checks that unknown modules produce an empty Entry. |
| TEST_F(CallStackProfileMetricsProviderTest, UnknownModule) { |
| - const Frame frame(0x1000, Frame::kUnknownModuleIndex); |
| + const ProfilesGenerator test_profiles_generator[] = { |
| + GEN_NEW_PROFILE(100, 10), |
| + GEN_NEW_SAMPLE(), |
| + GEN_FRAME(Frame::kUnknownModuleIndex, 0x1234), |
| + GEN_END(), |
| + }; |
| - Profile profile; |
| + const ExpectedProtoEntry expected_proto_entries[] = { |
| + { -1, 0 }, |
| + }; |
| + const ExpectedProtoSample expected_proto_samples[] = { |
| + { 0, &expected_proto_entries[0], 1, 1 }, |
| + }; |
| - profile.samples.push_back(Sample(1, frame)); |
| + const ExpectedProtoProfile expected_proto_profiles[] = { |
| + { |
| + 100, 10, |
| + nullptr, 0, |
| + expected_proto_samples, arraysize(expected_proto_samples), |
| + }, |
| + }; |
| - profile.profile_duration = base::TimeDelta::FromMilliseconds(100); |
| - profile.sampling_period = base::TimeDelta::FromMilliseconds(10); |
| Profiles profiles; |
| - profiles.push_back(std::move(profile)); |
| + GenerateProfiles(&profiles, test_profiles_generator); |
| + ASSERT_EQ(arraysize(expected_proto_profiles), profiles.size()); |
| CallStackProfileMetricsProvider provider; |
| provider.OnRecordingEnabled(); |
| @@ -473,38 +591,33 @@ TEST_F(CallStackProfileMetricsProviderTest, UnknownModule) { |
| ChromeUserMetricsExtension uma_proto; |
| provider.ProvideGeneralMetrics(&uma_proto); |
| - ASSERT_EQ(1, uma_proto.sampled_profile().size()); |
| - const SampledProfile& sampled_profile = uma_proto.sampled_profile().Get(0); |
| - ASSERT_TRUE(sampled_profile.has_call_stack_profile()); |
| - const CallStackProfile& call_stack_profile = |
| - sampled_profile.call_stack_profile(); |
| - |
| - ASSERT_EQ(1, call_stack_profile.sample().size()); |
| - const CallStackProfile::Sample& proto_sample = |
| - call_stack_profile.sample().Get(0); |
| - ASSERT_EQ(1, proto_sample.entry().size()); |
| - ASSERT_TRUE(proto_sample.has_count()); |
| - EXPECT_EQ(1u, proto_sample.count()); |
| - const CallStackProfile::Entry& entry = proto_sample.entry().Get(0); |
| - EXPECT_FALSE(entry.has_address()); |
| - EXPECT_FALSE(entry.has_module_id_index()); |
| + ASSERT_EQ(static_cast<int>(arraysize(expected_proto_profiles)), |
| + uma_proto.sampled_profile().size()); |
| + for (size_t p = 0; p < arraysize(expected_proto_profiles); ++p) { |
| + SCOPED_TRACE("profile " + base::SizeTToString(p)); |
| + VerifyProfileProto(uma_proto.sampled_profile().Get(p), |
| + expected_proto_profiles[p]); |
| + } |
| } |
| // Checks that pending profiles are only passed back to ProvideGeneralMetrics |
| // once. |
| TEST_F(CallStackProfileMetricsProviderTest, ProfilesProvidedOnlyOnce) { |
| CallStackProfileMetricsProvider provider; |
| - for (int i = 0; i < 2; ++i) { |
| - Profile profile; |
| - profile.samples.push_back( |
| - Sample(1, Frame(0x1000, Frame::kUnknownModuleIndex))); |
| - |
| - profile.profile_duration = base::TimeDelta::FromMilliseconds(100); |
| - // Use the sampling period to distinguish the two profiles. |
| - profile.sampling_period = base::TimeDelta::FromMilliseconds(i); |
| + for (int r = 0; r < 2; ++r) { |
| + const ProfilesGenerator test_profiles_generator[] = { |
| + // Use the sampling period to distinguish the two profiles. |
| + GEN_NEW_PROFILE(100, r), |
| + GEN_NEW_SAMPLE(), |
| + GEN_FRAME(Frame::kUnknownModuleIndex, 0x1234), |
| + GEN_END(), |
| + }; |
| + |
| Profiles profiles; |
| - profiles.push_back(std::move(profile)); |
| + GenerateProfiles(&profiles, test_profiles_generator); |
| + ASSERT_EQ(1U, profiles.size()); |
| + CallStackProfileMetricsProvider provider; |
| provider.OnRecordingEnabled(); |
| AppendProfiles( |
| CallStackProfileParams(CallStackProfileParams::BROWSER_PROCESS, |
| @@ -521,7 +634,7 @@ TEST_F(CallStackProfileMetricsProviderTest, ProfilesProvidedOnlyOnce) { |
| const CallStackProfile& call_stack_profile = |
| sampled_profile.call_stack_profile(); |
| ASSERT_TRUE(call_stack_profile.has_sampling_period_ms()); |
| - EXPECT_EQ(i, call_stack_profile.sampling_period_ms()); |
| + EXPECT_EQ(r, call_stack_profile.sampling_period_ms()); |
| } |
| } |
| @@ -529,14 +642,16 @@ TEST_F(CallStackProfileMetricsProviderTest, ProfilesProvidedOnlyOnce) { |
| // when collected before CallStackProfileMetricsProvider is instantiated. |
| TEST_F(CallStackProfileMetricsProviderTest, |
| ProfilesProvidedWhenCollectedBeforeInstantiation) { |
| - Profile profile; |
| - profile.samples.push_back( |
| - Sample(1, Frame(0x1000, Frame::kUnknownModuleIndex))); |
| + const ProfilesGenerator test_profiles_generator[] = { |
| + GEN_NEW_PROFILE(100, 10), |
| + GEN_NEW_SAMPLE(), |
| + GEN_FRAME(Frame::kUnknownModuleIndex, 0x1234), |
| + GEN_END(), |
| + }; |
| - profile.profile_duration = base::TimeDelta::FromMilliseconds(100); |
| - profile.sampling_period = base::TimeDelta::FromMilliseconds(10); |
| Profiles profiles; |
| - profiles.push_back(std::move(profile)); |
| + GenerateProfiles(&profiles, test_profiles_generator); |
| + ASSERT_EQ(1U, profiles.size()); |
| AppendProfiles( |
| CallStackProfileParams(CallStackProfileParams::BROWSER_PROCESS, |
| @@ -556,14 +671,16 @@ TEST_F(CallStackProfileMetricsProviderTest, |
| // Checks that pending profiles are not provided to ProvideGeneralMetrics |
| // while recording is disabled. |
| TEST_F(CallStackProfileMetricsProviderTest, ProfilesNotProvidedWhileDisabled) { |
| - Profile profile; |
| - profile.samples.push_back( |
| - Sample(1, Frame(0x1000, Frame::kUnknownModuleIndex))); |
| + const ProfilesGenerator test_profiles_generator[] = { |
| + GEN_NEW_PROFILE(100, 10), |
| + GEN_NEW_SAMPLE(), |
| + GEN_FRAME(Frame::kUnknownModuleIndex, 0x1234), |
| + GEN_END(), |
| + }; |
| - profile.profile_duration = base::TimeDelta::FromMilliseconds(100); |
| - profile.sampling_period = base::TimeDelta::FromMilliseconds(10); |
| Profiles profiles; |
| - profiles.push_back(std::move(profile)); |
| + GenerateProfiles(&profiles, test_profiles_generator); |
| + ASSERT_EQ(1U, profiles.size()); |
| CallStackProfileMetricsProvider provider; |
| provider.OnRecordingDisabled(); |
| @@ -583,12 +700,12 @@ TEST_F(CallStackProfileMetricsProviderTest, ProfilesNotProvidedWhileDisabled) { |
| // if recording is disabled while profiling. |
| TEST_F(CallStackProfileMetricsProviderTest, |
| ProfilesNotProvidedAfterChangeToDisabled) { |
| - Profile profile; |
| - profile.samples.push_back( |
| - Sample(1, Frame(0x1000, Frame::kUnknownModuleIndex))); |
| - |
| - profile.profile_duration = base::TimeDelta::FromMilliseconds(100); |
| - profile.sampling_period = base::TimeDelta::FromMilliseconds(10); |
| + const ProfilesGenerator test_profiles_generator[] = { |
| + GEN_NEW_PROFILE(100, 10), |
| + GEN_NEW_SAMPLE(), |
| + GEN_FRAME(Frame::kUnknownModuleIndex, 0x1234), |
| + GEN_END(), |
| + }; |
| CallStackProfileMetricsProvider provider; |
| provider.OnRecordingEnabled(); |
| @@ -601,7 +718,7 @@ TEST_F(CallStackProfileMetricsProviderTest, |
| provider.OnRecordingDisabled(); |
| Profiles profiles; |
| - profiles.push_back(std::move(profile)); |
| + GenerateProfiles(&profiles, test_profiles_generator); |
| callback.Run(std::move(profiles)); |
| ChromeUserMetricsExtension uma_proto; |
| provider.ProvideGeneralMetrics(&uma_proto); |
| @@ -613,12 +730,12 @@ TEST_F(CallStackProfileMetricsProviderTest, |
| // recording is enabled, but then disabled and reenabled while profiling. |
| TEST_F(CallStackProfileMetricsProviderTest, |
| ProfilesNotProvidedAfterChangeToDisabledThenEnabled) { |
| - Profile profile; |
| - profile.samples.push_back( |
| - Sample(1, Frame(0x1000, Frame::kUnknownModuleIndex))); |
| - |
| - profile.profile_duration = base::TimeDelta::FromMilliseconds(100); |
| - profile.sampling_period = base::TimeDelta::FromMilliseconds(10); |
| + const ProfilesGenerator test_profiles_generator[] = { |
| + GEN_NEW_PROFILE(100, 10), |
| + GEN_NEW_SAMPLE(), |
| + GEN_FRAME(Frame::kUnknownModuleIndex, 0x1234), |
| + GEN_END(), |
| + }; |
| CallStackProfileMetricsProvider provider; |
| provider.OnRecordingEnabled(); |
| @@ -632,7 +749,7 @@ TEST_F(CallStackProfileMetricsProviderTest, |
| provider.OnRecordingDisabled(); |
| provider.OnRecordingEnabled(); |
| Profiles profiles; |
| - profiles.push_back(std::move(profile)); |
| + GenerateProfiles(&profiles, test_profiles_generator); |
| callback.Run(std::move(profiles)); |
| ChromeUserMetricsExtension uma_proto; |
| provider.ProvideGeneralMetrics(&uma_proto); |
| @@ -644,12 +761,12 @@ TEST_F(CallStackProfileMetricsProviderTest, |
| // if recording is disabled, but then enabled while profiling. |
| TEST_F(CallStackProfileMetricsProviderTest, |
| ProfilesNotProvidedAfterChangeFromDisabled) { |
| - Profile profile; |
| - profile.samples.push_back( |
| - Sample(1, Frame(0x1000, Frame::kUnknownModuleIndex))); |
| - |
| - profile.profile_duration = base::TimeDelta::FromMilliseconds(100); |
| - profile.sampling_period = base::TimeDelta::FromMilliseconds(10); |
| + const ProfilesGenerator test_profiles_generator[] = { |
| + GEN_NEW_PROFILE(100, 10), |
| + GEN_NEW_SAMPLE(), |
| + GEN_FRAME(Frame::kUnknownModuleIndex, 0x1234), |
| + GEN_END(), |
| + }; |
| CallStackProfileMetricsProvider provider; |
| provider.OnRecordingDisabled(); |
| @@ -662,7 +779,7 @@ TEST_F(CallStackProfileMetricsProviderTest, |
| provider.OnRecordingEnabled(); |
| Profiles profiles; |
| - profiles.push_back(std::move(profile)); |
| + GenerateProfiles(&profiles, test_profiles_generator); |
| callback.Run(std::move(profiles)); |
| ChromeUserMetricsExtension uma_proto; |
| provider.ProvideGeneralMetrics(&uma_proto); |