| Index: components/metrics/call_stack_profile_struct_traits_unittest.cc
|
| diff --git a/components/metrics/call_stack_profile_struct_traits_unittest.cc b/components/metrics/call_stack_profile_struct_traits_unittest.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..400d257b855c7c450da4d3d55a2fd11dfe57d889
|
| --- /dev/null
|
| +++ b/components/metrics/call_stack_profile_struct_traits_unittest.cc
|
| @@ -0,0 +1,204 @@
|
| +// Copyright 2016 The Chromium Authors. All rights reserved.
|
| +// Use of this source code is governed by a BSD-style license that can be
|
| +// found in the LICENSE file.
|
| +
|
| +#include <utility>
|
| +
|
| +#include "base/logging.h"
|
| +#include "base/macros.h"
|
| +#include "base/message_loop/message_loop.h"
|
| +#include "components/metrics/call_stack_profile_collector_test.mojom.h"
|
| +#include "mojo/public/cpp/bindings/binding.h"
|
| +#include "testing/gtest/include/gtest/gtest.h"
|
| +
|
| +namespace metrics {
|
| +
|
| +namespace {
|
| +
|
| +base::StackSamplingProfiler::CallStackProfile CreateProfile(
|
| + const std::vector<base::StackSamplingProfiler::Module>& modules,
|
| + const std::vector<base::StackSamplingProfiler::Sample>& samples,
|
| + base::TimeDelta profile_duration,
|
| + base::TimeDelta sampling_period) {
|
| + base::StackSamplingProfiler::CallStackProfile profile;
|
| + profile.modules = modules;
|
| + profile.samples = samples;
|
| + profile.profile_duration = profile_duration;
|
| + profile.sampling_period = sampling_period;
|
| + return profile;
|
| +}
|
| +
|
| +}
|
| +
|
| +class CallStackProfileCollectorTestImpl
|
| + : public mojom::CallStackProfileCollectorTest {
|
| + public:
|
| + explicit CallStackProfileCollectorTestImpl(
|
| + mojo::InterfaceRequest<mojom::CallStackProfileCollectorTest> request)
|
| + : binding_(this, std::move(request)) {
|
| + }
|
| +
|
| + // CallStackProfileCollectorTest:
|
| + void BounceFrame(const base::StackSamplingProfiler::Frame& in,
|
| + const BounceFrameCallback& callback) override {
|
| + callback.Run(in);
|
| + }
|
| +
|
| + void BounceModule(const base::StackSamplingProfiler::Module& in,
|
| + const BounceModuleCallback& callback) override {
|
| + callback.Run(in);
|
| + }
|
| +
|
| + void BounceProfile(const base::StackSamplingProfiler::CallStackProfile& in,
|
| + const BounceProfileCallback& callback) override {
|
| + callback.Run(in);
|
| + }
|
| +
|
| + private:
|
| + mojo::Binding<CallStackProfileCollectorTest> binding_;
|
| +};
|
| +
|
| +// Checks serialization/deserialization of Module fields.
|
| +TEST(CallStackProfileStructTraitsTest, Module) {
|
| + using Module = base::StackSamplingProfiler::Module;
|
| +
|
| + base::MessageLoop message_loop;
|
| +
|
| + mojom::CallStackProfileCollectorTestPtr proxy;
|
| + CallStackProfileCollectorTestImpl impl(GetProxy(&proxy));
|
| +
|
| + const Module serialize_cases[] = {
|
| + Module(0x0, "abcd", base::FilePath(base::FilePath::kCurrentDirectory)),
|
| + Module(0x10, "abcd", base::FilePath(base::FilePath::kCurrentDirectory)),
|
| + Module(1ULL << (sizeof(uintptr_t) * 8) * 3 / 4, "abcd",
|
| + base::FilePath(base::FilePath::kCurrentDirectory)),
|
| + Module(0x10, "", base::FilePath(base::FilePath::kCurrentDirectory)),
|
| + };
|
| +
|
| + for (const Module& input : serialize_cases) {
|
| + Module output;
|
| + EXPECT_TRUE(proxy->BounceModule(input, &output));
|
| +
|
| + EXPECT_EQ(input.base_address, output.base_address);
|
| + EXPECT_EQ(input.id, output.id);
|
| + EXPECT_EQ(input.filename, output.filename);
|
| + }
|
| +}
|
| +
|
| +// Checks serialization/deserialization of Frame fields.
|
| +TEST(CallStackProfileStructTraitsTest, Frame) {
|
| + using Frame = base::StackSamplingProfiler::Frame;
|
| +
|
| + base::MessageLoop message_loop;
|
| +
|
| + mojom::CallStackProfileCollectorTestPtr proxy;
|
| + CallStackProfileCollectorTestImpl impl(GetProxy(&proxy));
|
| +
|
| + const Frame serialize_cases[] = {
|
| + Frame(0x0, 10),
|
| + Frame(0x10, 10),
|
| + Frame(1ULL << (sizeof(uintptr_t) * 8) * 3 / 4, 10),
|
| + Frame(0xabcd, 0),
|
| + Frame(0xabcd, 1),
|
| + Frame(0xabcd, 10),
|
| + Frame(0xabcd, Frame::kUnknownModuleIndex),
|
| + };
|
| +
|
| + for (const Frame& input : serialize_cases) {
|
| + Frame output;
|
| + EXPECT_TRUE(proxy->BounceFrame(input, &output));
|
| +
|
| + EXPECT_EQ(input.instruction_pointer, output.instruction_pointer);
|
| + EXPECT_EQ(input.module_index, output.module_index);
|
| + }
|
| +}
|
| +
|
| +// Checks serialization/deserialization of Profile fields, including validation
|
| +// of the Frame module_index field.
|
| +TEST(CallStackProfileStructTraitsTest, Profile) {
|
| + using Module = base::StackSamplingProfiler::Module;
|
| + using Frame = base::StackSamplingProfiler::Frame;
|
| + using Sample = base::StackSamplingProfiler::Sample;
|
| + using Profile = base::StackSamplingProfiler::CallStackProfile;
|
| +
|
| + base::MessageLoop message_loop;
|
| +
|
| + mojom::CallStackProfileCollectorTestPtr proxy;
|
| + CallStackProfileCollectorTestImpl impl(GetProxy(&proxy));
|
| +
|
| + struct SerializeCase {
|
| + Profile profile;
|
| + bool expect_success;
|
| + };
|
| + const SerializeCase serialize_cases[] = {
|
| + {
|
| + CreateProfile(std::vector<Module>(), std::vector<Sample>(),
|
| + base::TimeDelta::FromSeconds(1),
|
| + base::TimeDelta::FromSeconds(2)),
|
| + true
|
| + },
|
| + {
|
| + CreateProfile({ Module(0x4000, "a", base::FilePath()) },
|
| + std::vector<Sample>(),
|
| + base::TimeDelta::FromSeconds(1),
|
| + base::TimeDelta::FromSeconds(2)),
|
| + true
|
| + },
|
| + {
|
| + CreateProfile({
|
| + Module(0x4000, "a", base::FilePath()),
|
| + Module(0x4100, "b", base::FilePath()),
|
| + },
|
| + {
|
| + {
|
| + Frame(0x4010, 0),
|
| + Frame(0x4110, 1),
|
| + Frame(0x4110, Frame::kUnknownModuleIndex),
|
| + }
|
| + },
|
| + base::TimeDelta::FromSeconds(1),
|
| + base::TimeDelta::FromSeconds(2)),
|
| + true
|
| + },
|
| + // The out of range module index in the second sample should cause the
|
| + // entire deserialization to fail.
|
| + {
|
| + CreateProfile({
|
| + Module(0x4000, "a", base::FilePath()),
|
| + Module(0x4100, "b", base::FilePath()),
|
| + },
|
| + {
|
| + {
|
| + Frame(0x4010, 0),
|
| + Frame(0x4110, 1),
|
| + Frame(0x4110, Frame::kUnknownModuleIndex),
|
| + },
|
| + {
|
| + Frame(0x4010, 0),
|
| + Frame(0x4110, 2),
|
| + },
|
| + },
|
| + base::TimeDelta::FromSeconds(1),
|
| + base::TimeDelta::FromSeconds(2)),
|
| + false
|
| + },
|
| + };
|
| +
|
| + for (const SerializeCase& input : serialize_cases) {
|
| + SCOPED_TRACE(&input - &serialize_cases[0]);
|
| +
|
| + Profile output;
|
| + EXPECT_EQ(input.expect_success,
|
| + proxy->BounceProfile(input.profile, &output));
|
| +
|
| + if (!input.expect_success)
|
| + continue;
|
| +
|
| + EXPECT_EQ(input.profile.modules, output.modules);
|
| + EXPECT_EQ(input.profile.samples, output.samples);
|
| + EXPECT_EQ(input.profile.profile_duration, output.profile_duration);
|
| + EXPECT_EQ(input.profile.sampling_period, output.sampling_period);
|
| + }
|
| +}
|
| +
|
| +} // namespace metrics
|
|
|