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 DISALLOW_COPY_AND_ASSIGN(CallStackProfileCollectorTestImpl); | |
61 }; | |
62 | |
63 class CallStackProfileStructTraitsTest : public testing::Test { | |
64 public: | |
65 CallStackProfileStructTraitsTest() : impl_(GetProxy(&proxy_)) {} | |
66 | |
67 protected: | |
68 base::MessageLoop message_loop_; | |
69 mojom::CallStackProfileCollectorTestPtr proxy_; | |
70 CallStackProfileCollectorTestImpl impl_; | |
71 | |
72 DISALLOW_COPY_AND_ASSIGN(CallStackProfileStructTraitsTest); | |
73 }; | |
74 | |
75 // Checks serialization/deserialization of Module fields. | |
76 TEST_F(CallStackProfileStructTraitsTest, Module) { | |
77 using Module = base::StackSamplingProfiler::Module; | |
78 | |
79 struct SerializeCase { | |
80 Module module; | |
81 bool expect_success; | |
82 }; | |
83 | |
84 const SerializeCase serialize_cases[] = { | |
85 // Null base address. | |
86 { | |
87 Module(0x0, "abcd", base::FilePath(base::FilePath::kCurrentDirectory)), | |
88 true | |
89 }, | |
90 // Non-null base address. | |
91 { | |
92 Module(0x10, "abcd", base::FilePath(base::FilePath::kCurrentDirectory)), | |
93 true | |
94 }, | |
95 // Base address with a bit set beyond 32 bits, when built for x64. | |
96 { | |
97 Module(1ULL << (sizeof(uintptr_t) * 8) * 3 / 4, "abcd", | |
98 base::FilePath(base::FilePath::kCurrentDirectory)), | |
99 true | |
100 }, | |
101 // Empty module id. | |
102 { | |
103 Module(0x10, "", base::FilePath(base::FilePath::kCurrentDirectory)), | |
104 true | |
105 }, | |
106 // Module id at the length limit. | |
107 { | |
108 Module(0x10, std::string(40, ' '), | |
109 base::FilePath(base::FilePath::kCurrentDirectory)), | |
110 true | |
111 }, | |
112 // Module id beyond the length limit. | |
113 { | |
114 Module(0x10, std::string(41, ' '), | |
115 base::FilePath(base::FilePath::kCurrentDirectory)), | |
116 false | |
117 }, | |
118 }; | |
119 | |
120 for (const SerializeCase& input : serialize_cases) { | |
121 Module output; | |
122 EXPECT_EQ(input.expect_success, | |
123 proxy_->BounceModule(input.module, &output)); | |
124 | |
125 if (!input.expect_success) | |
126 continue; | |
127 | |
128 EXPECT_EQ(input.module.base_address, output.base_address); | |
129 EXPECT_EQ(input.module.id, output.id); | |
130 EXPECT_EQ(input.module.filename, output.filename); | |
131 } | |
132 } | |
133 | |
134 // Checks serialization/deserialization of Frame fields. | |
135 TEST_F(CallStackProfileStructTraitsTest, Frame) { | |
136 using Frame = base::StackSamplingProfiler::Frame; | |
137 | |
138 const Frame serialize_cases[] = { | |
139 // Null instruction pointer. | |
140 Frame(0x0, 10), | |
141 // Non-null instruction pointer. | |
142 Frame(0x10, 10), | |
143 // Instruction pointer with a bit set beyond 32 bits, when built for x64. | |
144 Frame(1ULL << (sizeof(uintptr_t) * 8) * 3 / 4, 10), | |
145 // Zero module index. | |
146 Frame(0xabcd, 0), | |
147 // Non-zero module index. | |
148 Frame(0xabcd, 1), | |
149 // Non-zero module index. | |
150 Frame(0xabcd, 10), | |
151 // Unknown module index. | |
152 Frame(0xabcd, Frame::kUnknownModuleIndex), | |
153 }; | |
154 | |
155 for (const Frame& input : serialize_cases) { | |
156 Frame output; | |
157 EXPECT_TRUE(proxy_->BounceFrame(input, &output)); | |
158 | |
159 EXPECT_EQ(input.instruction_pointer, output.instruction_pointer); | |
160 EXPECT_EQ(input.module_index, output.module_index); | |
161 } | |
162 } | |
163 | |
164 // Checks serialization/deserialization of Profile fields, including validation | |
165 // of the Frame module_index field. | |
166 TEST_F(CallStackProfileStructTraitsTest, Profile) { | |
167 using Module = base::StackSamplingProfiler::Module; | |
168 using Frame = base::StackSamplingProfiler::Frame; | |
169 using Sample = base::StackSamplingProfiler::Sample; | |
170 using Profile = base::StackSamplingProfiler::CallStackProfile; | |
171 | |
172 struct SerializeCase { | |
173 Profile profile; | |
174 bool expect_success; | |
175 }; | |
176 | |
177 const SerializeCase serialize_cases[] = { | |
178 // Empty modules and samples. | |
179 { | |
180 CreateProfile(std::vector<Module>(), std::vector<Sample>(), | |
181 base::TimeDelta::FromSeconds(1), | |
182 base::TimeDelta::FromSeconds(2)), | |
183 true | |
184 }, | |
185 // Non-empty modules and empty samples. | |
186 { | |
187 CreateProfile({ Module(0x4000, "a", base::FilePath()) }, | |
188 std::vector<Sample>(), | |
189 base::TimeDelta::FromSeconds(1), | |
190 base::TimeDelta::FromSeconds(2)), | |
191 true | |
192 }, | |
193 // Valid values for modules and samples. | |
194 { | |
195 CreateProfile({ | |
196 Module(0x4000, "a", base::FilePath()), | |
197 Module(0x4100, "b", base::FilePath()), | |
198 }, | |
199 { | |
200 { | |
201 Frame(0x4010, 0), | |
202 Frame(0x4110, 1), | |
203 Frame(0x4110, Frame::kUnknownModuleIndex), | |
204 } | |
205 }, | |
206 base::TimeDelta::FromSeconds(1), | |
207 base::TimeDelta::FromSeconds(2)), | |
208 true | |
209 }, | |
210 // Valid values for modules, but an out of range module index in the second | |
211 // sample. | |
212 { | |
213 CreateProfile({ | |
214 Module(0x4000, "a", base::FilePath()), | |
215 Module(0x4100, "b", base::FilePath()), | |
216 }, | |
217 { | |
218 { | |
219 Frame(0x4010, 0), | |
220 Frame(0x4110, 1), | |
221 Frame(0x4110, Frame::kUnknownModuleIndex), | |
222 }, | |
223 { | |
224 Frame(0x4010, 0), | |
225 Frame(0x4110, 2), | |
226 }, | |
227 }, | |
228 base::TimeDelta::FromSeconds(1), | |
229 base::TimeDelta::FromSeconds(2)), | |
230 false | |
231 }, | |
232 }; | |
233 | |
234 for (const SerializeCase& input : serialize_cases) { | |
235 SCOPED_TRACE(&input - &serialize_cases[0]); | |
236 | |
237 Profile output; | |
238 EXPECT_EQ(input.expect_success, | |
239 proxy_->BounceProfile(input.profile, &output)); | |
240 | |
241 if (!input.expect_success) | |
242 continue; | |
243 | |
244 EXPECT_EQ(input.profile.modules, output.modules); | |
245 EXPECT_EQ(input.profile.samples, output.samples); | |
246 EXPECT_EQ(input.profile.profile_duration, output.profile_duration); | |
247 EXPECT_EQ(input.profile.sampling_period, output.sampling_period); | |
248 } | |
249 } | |
250 | |
251 } // namespace metrics | |
OLD | NEW |