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

Unified Diff: components/metrics/call_stack_profile_metrics_provider_unittest.cc

Issue 2444143002: Add process lifetime annotations to stack samples. (Closed)
Patch Set: abandon generator for on-the-fly Profiles creation 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 side-by-side diff with in-line comments
Download patch
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..727b506d3891aaffa43c7fc227d548062ad670ab 100644
--- a/components/metrics/call_stack_profile_metrics_provider_unittest.cc
+++ b/components/metrics/call_stack_profile_metrics_provider_unittest.cc
@@ -27,6 +27,94 @@ using Profile = StackSamplingProfiler::CallStackProfile;
using Profiles = StackSamplingProfiler::CallStackProfiles;
using Sample = StackSamplingProfiler::Sample;
+namespace {
+
+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;
+};
+
+class ProfilesFactory {
+ public:
+ ProfilesFactory(){};
+ ~ProfilesFactory(){};
+
+ ProfilesFactory& AddPhase(int phase);
+ ProfilesFactory& NewProfile(int duration_ms, int interval_ms);
+ ProfilesFactory& NewSample();
+ ProfilesFactory& AddFrame(size_t module, uintptr_t offset);
+ ProfilesFactory& DefineModule(const char* name,
+ const base::FilePath& path,
+ uintptr_t base);
+
+ Profiles Build();
+
+ private:
+ Profiles profiles_;
+ uint32_t process_phases_ = 0;
+
+ DISALLOW_COPY_AND_ASSIGN(ProfilesFactory);
+};
+
+ProfilesFactory& ProfilesFactory::AddPhase(int phase) {
+ process_phases_ |= 1 << phase;
+ return *this;
+}
+
+ProfilesFactory& ProfilesFactory::NewProfile(int duration_ms, int interval_ms) {
+ profiles_.push_back(Profile());
+ Profile* profile = &profiles_.back();
+ profile->profile_duration = base::TimeDelta::FromMilliseconds(duration_ms);
+ profile->sampling_period = base::TimeDelta::FromMilliseconds(interval_ms);
+ return *this;
+}
+
+ProfilesFactory& ProfilesFactory::NewSample() {
+ profiles_.back().samples.push_back(Sample());
+ profiles_.back().samples.back().process_phases = process_phases_;
+ return *this;
+}
+
+ProfilesFactory& ProfilesFactory::AddFrame(size_t module, uintptr_t offset) {
+ profiles_.back().samples.back().frames.push_back(Frame(offset, module));
+ return *this;
+}
+
+ProfilesFactory& ProfilesFactory::DefineModule(const char* name,
+ const base::FilePath& path,
+ uintptr_t base) {
+ profiles_.back().modules.push_back(Module(base, name, path));
+ return *this;
+}
+
+Profiles ProfilesFactory::Build() {
+ return std::move(profiles_);
+}
+
+} // namespace
+
namespace metrics {
// This test fixture enables the field trial that
@@ -49,6 +137,9 @@ class CallStackProfileMetricsProviderTest : public testing::Test {
std::move(profiles));
}
+ void VerifyProfileProto(const ExpectedProtoProfile& expected,
+ const SampledProfile& proto);
+
private:
// Exposes field trial/group names from the CallStackProfileMetricsProvider.
class TestState : public CallStackProfileMetricsProvider {
@@ -63,54 +154,66 @@ class CallStackProfileMetricsProviderTest : public testing::Test {
DISALLOW_COPY_AND_ASSIGN(CallStackProfileMetricsProviderTest);
};
+void CallStackProfileMetricsProviderTest::VerifyProfileProto(
+ const ExpectedProtoProfile& expected,
+ const SampledProfile& proto) {
+ 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 +224,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 +249,97 @@ 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] = {
- {
+ Profiles profiles = ProfilesFactory()
+ .NewProfile(100, 10)
+ .DefineModule(moduleA_name, moduleA_path, moduleA_base_address)
+ .DefineModule(moduleB_name, moduleB_path, moduleB_base_address)
+
+ .NewSample()
+ .AddFrame(0, moduleA_base_address + 0x10)
+ .AddFrame(1, moduleB_base_address + 0x20)
+ .AddFrame(0, moduleA_base_address + 0x30)
+ .NewSample()
+ .AddFrame(1, moduleB_base_address + 0x10)
+ .AddFrame(0, moduleA_base_address + 0x20)
+ .AddFrame(1, moduleB_base_address + 0x30)
+
+ .NewProfile(200, 20)
+ .DefineModule(moduleC_name, moduleC_path, moduleC_base_address)
+ .DefineModule(moduleA_name, moduleA_path, moduleA_base_address)
+
+ .NewSample()
+ .AddFrame(0, moduleC_base_address + 0x10)
+ .AddFrame(1, moduleA_base_address + 0x20)
+ .AddFrame(0, moduleC_base_address + 0x30)
+ .NewSample()
+ .AddFrame(1, moduleA_base_address + 0x10)
+ .AddFrame(0, moduleC_base_address + 0x20)
+ .AddFrame(1, moduleA_base_address + 0x30)
+
+ .Build();
+
+ 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));
- }
+ ASSERT_EQ(arraysize(expected_proto_profiles), profiles.size());
CallStackProfileMetricsProvider provider;
provider.OnRecordingEnabled();
@@ -215,68 +352,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(expected_proto_profiles[p],
+ uma_proto.sampled_profile().Get(p));
}
}
@@ -284,42 +365,66 @@ 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
- )
- };
- // 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) }
+ Profiles profiles = ProfilesFactory()
+ .NewProfile(100, 10)
+ .DefineModule(module_name, module_path, module_base_address)
+
+ .AddPhase(0)
+ .NewSample()
+ .AddFrame(0, module_base_address + 0x10)
+ .NewSample()
+ .AddFrame(0, module_base_address + 0x20)
+ .NewSample()
+ .AddFrame(0, module_base_address + 0x10)
+ .NewSample()
+ .AddFrame(0, module_base_address + 0x10)
+
+ .AddPhase(1)
+ .NewSample()
+ .AddFrame(0, module_base_address + 0x10)
+ .NewSample()
+ .AddFrame(0, module_base_address + 0x20)
+ .NewSample()
+ .AddFrame(0, module_base_address + 0x10)
+ .NewSample()
+ .AddFrame(0, module_base_address + 0x10)
+
+ .Build();
+
+ 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 },
+ { 0, &expected_proto_entries[1], 1, 1 },
+ { 2, &expected_proto_entries[0], 1, 3 },
+ { 0, &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));
+ ASSERT_EQ(arraysize(expected_proto_profiles), profiles.size());
CallStackProfileMetricsProvider provider;
provider.OnRecordingEnabled();
@@ -332,36 +437,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(expected_proto_profiles[p],
+ uma_proto.sampled_profile().Get(p));
}
}
@@ -369,42 +450,68 @@ 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
- )
- };
- // 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) }
+ Profiles profiles = ProfilesFactory()
+ .NewProfile(100, 10)
+ .DefineModule(module_name, module_path, module_base_address)
+
+ .AddPhase(0)
+ .NewSample()
+ .AddFrame(0, module_base_address + 0x10)
+ .NewSample()
+ .AddFrame(0, module_base_address + 0x20)
+ .NewSample()
+ .AddFrame(0, module_base_address + 0x10)
+ .NewSample()
+ .AddFrame(0, module_base_address + 0x10)
+
+ .AddPhase(1)
+ .NewSample()
+ .AddFrame(0, module_base_address + 0x10)
+ .NewSample()
+ .AddFrame(0, module_base_address + 0x20)
+ .NewSample()
+ .AddFrame(0, module_base_address + 0x10)
+ .NewSample()
+ .AddFrame(0, module_base_address + 0x10)
+
+ .Build();
+
+ 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));
+ ASSERT_EQ(arraysize(expected_proto_profiles), profiles.size());
CallStackProfileMetricsProvider provider;
provider.OnRecordingEnabled();
@@ -416,51 +523,39 @@ 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(expected_proto_profiles[p],
+ uma_proto.sampled_profile().Get(p));
}
}
// Checks that unknown modules produce an empty Entry.
TEST_F(CallStackProfileMetricsProviderTest, UnknownModule) {
- const Frame frame(0x1000, Frame::kUnknownModuleIndex);
-
- Profile profile;
+ Profiles profiles = ProfilesFactory()
+ .NewProfile(100, 10)
+ .NewSample()
+ .AddFrame(Frame::kUnknownModuleIndex, 0x1234)
+ .Build();
+
+ 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));
+ ASSERT_EQ(arraysize(expected_proto_profiles), profiles.size());
CallStackProfileMetricsProvider provider;
provider.OnRecordingEnabled();
@@ -473,38 +568,30 @@ 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(expected_proto_profiles[p],
+ uma_proto.sampled_profile().Get(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)));
+ for (int r = 0; r < 2; ++r) {
+ Profiles profiles = ProfilesFactory()
+ // Use the sampling period to distinguish the two profiles.
+ .NewProfile(100, r)
+ .NewSample()
+ .AddFrame(Frame::kUnknownModuleIndex, 0x1234)
+ .Build();
- profile.profile_duration = base::TimeDelta::FromMilliseconds(100);
- // Use the sampling period to distinguish the two profiles.
- profile.sampling_period = base::TimeDelta::FromMilliseconds(i);
- Profiles profiles;
- profiles.push_back(std::move(profile));
+ ASSERT_EQ(1U, profiles.size());
+ CallStackProfileMetricsProvider provider;
provider.OnRecordingEnabled();
AppendProfiles(
CallStackProfileParams(CallStackProfileParams::BROWSER_PROCESS,
@@ -521,7 +608,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 +616,13 @@ 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)));
+ Profiles profiles = ProfilesFactory()
+ .NewProfile(100, 10)
+ .NewSample()
+ .AddFrame(Frame::kUnknownModuleIndex, 0x1234)
+ .Build();
- profile.profile_duration = base::TimeDelta::FromMilliseconds(100);
- profile.sampling_period = base::TimeDelta::FromMilliseconds(10);
- Profiles profiles;
- profiles.push_back(std::move(profile));
+ ASSERT_EQ(1U, profiles.size());
AppendProfiles(
CallStackProfileParams(CallStackProfileParams::BROWSER_PROCESS,
@@ -556,14 +642,13 @@ 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)));
+ Profiles profiles = ProfilesFactory()
+ .NewProfile(100, 10)
+ .NewSample()
+ .AddFrame(Frame::kUnknownModuleIndex, 0x1234)
+ .Build();
- profile.profile_duration = base::TimeDelta::FromMilliseconds(100);
- profile.sampling_period = base::TimeDelta::FromMilliseconds(10);
- Profiles profiles;
- profiles.push_back(std::move(profile));
+ ASSERT_EQ(1U, profiles.size());
CallStackProfileMetricsProvider provider;
provider.OnRecordingDisabled();
@@ -583,13 +668,6 @@ 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);
-
CallStackProfileMetricsProvider provider;
provider.OnRecordingEnabled();
base::StackSamplingProfiler::CompletedCallback callback =
@@ -598,10 +676,13 @@ TEST_F(CallStackProfileMetricsProviderTest,
CallStackProfileParams::UI_THREAD,
CallStackProfileParams::PROCESS_STARTUP,
CallStackProfileParams::MAY_SHUFFLE));
-
provider.OnRecordingDisabled();
- Profiles profiles;
- profiles.push_back(std::move(profile));
+
+ Profiles profiles = ProfilesFactory()
+ .NewProfile(100, 10)
+ .NewSample()
+ .AddFrame(Frame::kUnknownModuleIndex, 0x1234)
+ .Build();
callback.Run(std::move(profiles));
ChromeUserMetricsExtension uma_proto;
provider.ProvideGeneralMetrics(&uma_proto);
@@ -613,13 +694,6 @@ 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);
-
CallStackProfileMetricsProvider provider;
provider.OnRecordingEnabled();
base::StackSamplingProfiler::CompletedCallback callback =
@@ -628,11 +702,14 @@ TEST_F(CallStackProfileMetricsProviderTest,
CallStackProfileParams::UI_THREAD,
CallStackProfileParams::PROCESS_STARTUP,
CallStackProfileParams::MAY_SHUFFLE));
-
provider.OnRecordingDisabled();
provider.OnRecordingEnabled();
- Profiles profiles;
- profiles.push_back(std::move(profile));
+
+ Profiles profiles = ProfilesFactory()
+ .NewProfile(100, 10)
+ .NewSample()
+ .AddFrame(Frame::kUnknownModuleIndex, 0x1234)
+ .Build();
callback.Run(std::move(profiles));
ChromeUserMetricsExtension uma_proto;
provider.ProvideGeneralMetrics(&uma_proto);
@@ -644,13 +721,6 @@ 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);
-
CallStackProfileMetricsProvider provider;
provider.OnRecordingDisabled();
base::StackSamplingProfiler::CompletedCallback callback =
@@ -659,10 +729,13 @@ TEST_F(CallStackProfileMetricsProviderTest,
CallStackProfileParams::UI_THREAD,
CallStackProfileParams::PROCESS_STARTUP,
CallStackProfileParams::MAY_SHUFFLE));
-
provider.OnRecordingEnabled();
- Profiles profiles;
- profiles.push_back(std::move(profile));
+
+ Profiles profiles = ProfilesFactory()
+ .NewProfile(100, 10)
+ .NewSample()
+ .AddFrame(Frame::kUnknownModuleIndex, 0x1234)
+ .Build();
callback.Run(std::move(profiles));
ChromeUserMetricsExtension uma_proto;
provider.ProvideGeneralMetrics(&uma_proto);
« no previous file with comments | « components/metrics/call_stack_profile_metrics_provider.cc ('k') | components/metrics/proto/call_stack_profile.proto » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698