OLD | NEW |
---|---|
(Empty) | |
1 // Copyright 2016 The Chromium Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 #include <utility> | |
6 | |
7 #include "base/logging.h" | |
8 #include "base/macros.h" | |
9 #include "base/message_loop/message_loop.h" | |
10 #include "components/metrics/public/interfaces/call_stack_profile_collector_test .mojom.h" | |
11 #include "mojo/public/cpp/bindings/binding.h" | |
12 #include "testing/gtest/include/gtest/gtest.h" | |
13 | |
14 namespace metrics { | |
15 | |
16 namespace { | |
17 | |
18 base::StackSamplingProfiler::CallStackProfile CreateProfile( | |
19 const std::vector<base::StackSamplingProfiler::Module>& modules, | |
20 const std::vector<base::StackSamplingProfiler::Sample>& samples, | |
21 base::TimeDelta profile_duration, | |
22 base::TimeDelta sampling_period) { | |
23 base::StackSamplingProfiler::CallStackProfile profile; | |
24 profile.modules = modules; | |
25 profile.samples = samples; | |
26 profile.profile_duration = profile_duration; | |
27 profile.sampling_period = sampling_period; | |
28 return profile; | |
29 } | |
30 | |
31 } | |
32 | |
33 class CallStackProfileCollectorTestImpl | |
34 : public mojom::CallStackProfileCollectorTest { | |
35 public: | |
36 explicit CallStackProfileCollectorTestImpl( | |
37 mojo::InterfaceRequest<mojom::CallStackProfileCollectorTest> request) | |
38 : binding_(this, std::move(request)) { | |
39 } | |
40 | |
41 // CallStackProfileCollectorTest: | |
42 void BounceFrame(const base::StackSamplingProfiler::Frame& in, | |
43 const BounceFrameCallback& callback) override { | |
44 callback.Run(in); | |
45 } | |
46 | |
47 void BounceModule(const base::StackSamplingProfiler::Module& in, | |
48 const BounceModuleCallback& callback) override { | |
49 callback.Run(in); | |
50 } | |
51 | |
52 void BounceProfile(const base::StackSamplingProfiler::CallStackProfile& in, | |
53 const BounceProfileCallback& callback) override { | |
54 callback.Run(in); | |
55 } | |
56 | |
57 private: | |
58 mojo::Binding<CallStackProfileCollectorTest> binding_; | |
59 }; | |
60 | |
61 // Checks serialization/deserialization of Module fields. | |
62 TEST(CallStackProfileStructTraitsTest, Module) { | |
63 using Module = base::StackSamplingProfiler::Module; | |
64 | |
65 base::MessageLoop message_loop; | |
Ilya Sherman
2016/08/18 07:59:18
nit: Why not declare this as part of the harness?
Mike Wittman
2016/08/18 17:49:19
Done.
| |
66 | |
67 mojom::CallStackProfileCollectorTestPtr proxy; | |
68 CallStackProfileCollectorTestImpl impl(GetProxy(&proxy)); | |
69 | |
70 const Module serialize_cases[] = { | |
71 Module(0x0, "abcd", base::FilePath(base::FilePath::kCurrentDirectory)), | |
72 Module(0x10, "abcd", base::FilePath(base::FilePath::kCurrentDirectory)), | |
73 Module(1ULL << (sizeof(uintptr_t) * 8) * 3 / 4, "abcd", | |
74 base::FilePath(base::FilePath::kCurrentDirectory)), | |
75 Module(0x10, "", base::FilePath(base::FilePath::kCurrentDirectory)), | |
Ilya Sherman
2016/08/18 07:59:18
nit: It would be great to have a brief comment for
Mike Wittman
2016/08/18 17:49:19
Done.
| |
76 }; | |
77 | |
78 for (const Module& input : serialize_cases) { | |
79 Module output; | |
80 EXPECT_TRUE(proxy->BounceModule(input, &output)); | |
81 | |
82 EXPECT_EQ(input.base_address, output.base_address); | |
83 EXPECT_EQ(input.id, output.id); | |
84 EXPECT_EQ(input.filename, output.filename); | |
85 } | |
86 } | |
87 | |
88 // Checks serialization/deserialization of Frame fields. | |
89 TEST(CallStackProfileStructTraitsTest, Frame) { | |
90 using Frame = base::StackSamplingProfiler::Frame; | |
91 | |
92 base::MessageLoop message_loop; | |
93 | |
94 mojom::CallStackProfileCollectorTestPtr proxy; | |
95 CallStackProfileCollectorTestImpl impl(GetProxy(&proxy)); | |
96 | |
97 const Frame serialize_cases[] = { | |
98 Frame(0x0, 10), | |
99 Frame(0x10, 10), | |
100 Frame(1ULL << (sizeof(uintptr_t) * 8) * 3 / 4, 10), | |
101 Frame(0xabcd, 0), | |
102 Frame(0xabcd, 1), | |
103 Frame(0xabcd, 10), | |
104 Frame(0xabcd, Frame::kUnknownModuleIndex), | |
105 }; | |
106 | |
107 for (const Frame& input : serialize_cases) { | |
108 Frame output; | |
109 EXPECT_TRUE(proxy->BounceFrame(input, &output)); | |
110 | |
111 EXPECT_EQ(input.instruction_pointer, output.instruction_pointer); | |
112 EXPECT_EQ(input.module_index, output.module_index); | |
113 } | |
114 } | |
115 | |
116 // Checks serialization/deserialization of Profile fields, including validation | |
117 // of the Frame module_index field. | |
118 TEST(CallStackProfileStructTraitsTest, Profile) { | |
119 using Module = base::StackSamplingProfiler::Module; | |
120 using Frame = base::StackSamplingProfiler::Frame; | |
121 using Sample = base::StackSamplingProfiler::Sample; | |
122 using Profile = base::StackSamplingProfiler::CallStackProfile; | |
Ilya Sherman
2016/08/18 07:59:18
Hmm, why not write these using statements at the t
Mike Wittman
2016/08/18 17:49:19
The code under test is translating between two set
| |
123 | |
124 base::MessageLoop message_loop; | |
125 | |
126 mojom::CallStackProfileCollectorTestPtr proxy; | |
127 CallStackProfileCollectorTestImpl impl(GetProxy(&proxy)); | |
128 | |
129 struct SerializeCase { | |
130 Profile profile; | |
131 bool expect_success; | |
132 }; | |
133 const SerializeCase serialize_cases[] = { | |
134 { | |
135 CreateProfile(std::vector<Module>(), std::vector<Sample>(), | |
136 base::TimeDelta::FromSeconds(1), | |
137 base::TimeDelta::FromSeconds(2)), | |
138 true | |
139 }, | |
140 { | |
141 CreateProfile({ Module(0x4000, "a", base::FilePath()) }, | |
142 std::vector<Sample>(), | |
143 base::TimeDelta::FromSeconds(1), | |
144 base::TimeDelta::FromSeconds(2)), | |
145 true | |
146 }, | |
147 { | |
148 CreateProfile({ | |
149 Module(0x4000, "a", base::FilePath()), | |
150 Module(0x4100, "b", base::FilePath()), | |
151 }, | |
152 { | |
153 { | |
154 Frame(0x4010, 0), | |
155 Frame(0x4110, 1), | |
156 Frame(0x4110, Frame::kUnknownModuleIndex), | |
157 } | |
158 }, | |
159 base::TimeDelta::FromSeconds(1), | |
160 base::TimeDelta::FromSeconds(2)), | |
161 true | |
162 }, | |
163 // The out of range module index in the second sample should cause the | |
164 // entire deserialization to fail. | |
165 { | |
166 CreateProfile({ | |
167 Module(0x4000, "a", base::FilePath()), | |
168 Module(0x4100, "b", base::FilePath()), | |
169 }, | |
170 { | |
171 { | |
172 Frame(0x4010, 0), | |
173 Frame(0x4110, 1), | |
174 Frame(0x4110, Frame::kUnknownModuleIndex), | |
175 }, | |
176 { | |
177 Frame(0x4010, 0), | |
178 Frame(0x4110, 2), | |
179 }, | |
180 }, | |
181 base::TimeDelta::FromSeconds(1), | |
182 base::TimeDelta::FromSeconds(2)), | |
183 false | |
184 }, | |
185 }; | |
186 | |
187 for (const SerializeCase& input : serialize_cases) { | |
188 SCOPED_TRACE(&input - &serialize_cases[0]); | |
189 | |
190 Profile output; | |
191 EXPECT_EQ(input.expect_success, | |
192 proxy->BounceProfile(input.profile, &output)); | |
193 | |
194 if (!input.expect_success) | |
195 continue; | |
196 | |
197 EXPECT_EQ(input.profile.modules, output.modules); | |
198 EXPECT_EQ(input.profile.samples, output.samples); | |
199 EXPECT_EQ(input.profile.profile_duration, output.profile_duration); | |
200 EXPECT_EQ(input.profile.sampling_period, output.sampling_period); | |
201 } | |
202 } | |
203 | |
204 } // namespace metrics | |
OLD | NEW |