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

Side by Side Diff: chrome/test/chromedriver/performance_logger_unittest.cc

Issue 454133003: [ChromeDriver] Implementing tracing support (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Fixing nits Created 6 years, 4 months 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 unified diff | Download patch
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/test/chromedriver/performance_logger.h" 5 #include "chrome/test/chromedriver/performance_logger.h"
6 6
7 #include "base/compiler_specific.h" 7 #include "base/compiler_specific.h"
8 #include "base/format_macros.h" 8 #include "base/format_macros.h"
9 #include "base/json/json_reader.h" 9 #include "base/json/json_reader.h"
10 #include "base/memory/scoped_vector.h" 10 #include "base/memory/scoped_vector.h"
11 #include "base/time/time.h" 11 #include "base/time/time.h"
12 #include "base/values.h" 12 #include "base/values.h"
13 #include "chrome/test/chromedriver/chrome/devtools_client_impl.h"
13 #include "chrome/test/chromedriver/chrome/log.h" 14 #include "chrome/test/chromedriver/chrome/log.h"
14 #include "chrome/test/chromedriver/chrome/status.h" 15 #include "chrome/test/chromedriver/chrome/status.h"
15 #include "chrome/test/chromedriver/chrome/stub_devtools_client.h" 16 #include "chrome/test/chromedriver/chrome/stub_devtools_client.h"
17 #include "chrome/test/chromedriver/session.h"
16 #include "testing/gtest/include/gtest/gtest.h" 18 #include "testing/gtest/include/gtest/gtest.h"
17 19
18 namespace { 20 namespace {
19 21
22 struct DevToolsCommand {
23 DevToolsCommand(const std::string& in_method,
24 base::DictionaryValue* in_params)
25 : method(in_method) {
26 params.reset(in_params);
27 }
28 ~DevToolsCommand() {}
29
30 std::string method;
31 scoped_ptr<base::DictionaryValue> params;
32 };
33
20 class FakeDevToolsClient : public StubDevToolsClient { 34 class FakeDevToolsClient : public StubDevToolsClient {
21 public: 35 public:
22 explicit FakeDevToolsClient(const std::string& id) 36 explicit FakeDevToolsClient(const std::string& id)
23 : id_(id), listener_(NULL) {} 37 : id_(id), listener_(NULL), command_index_(0) {}
24 virtual ~FakeDevToolsClient() {} 38 virtual ~FakeDevToolsClient() {}
25 39
26 std::string PopSentCommand() { 40 bool PopSentCommand(DevToolsCommand** out_command) {
27 std::string command; 41 if (sent_commands_.size() > command_index_) {
28 if (!sent_command_queue_.empty()) { 42 *out_command = sent_commands_.get().at(command_index_++);
29 command = sent_command_queue_.front(); 43 return true;
30 sent_command_queue_.pop_front();
31 } 44 }
32 return command; 45 return false;
33 } 46 }
34 47
35 Status TriggerEvent(const std::string& method) { 48 Status TriggerEvent(const std::string& method) {
36 base::DictionaryValue empty_params; 49 base::DictionaryValue empty_params;
37 return listener_->OnEvent(this, method, empty_params); 50 return listener_->OnEvent(this, method, empty_params);
38 } 51 }
39 52
53 Status TriggerEvent(const std::string& method,
54 const base::DictionaryValue& params) {
55 return listener_->OnEvent(this, method, params);
56 }
57
40 // Overridden from DevToolsClient: 58 // Overridden from DevToolsClient:
41 virtual Status ConnectIfNecessary() OVERRIDE { 59 virtual Status ConnectIfNecessary() OVERRIDE {
42 return listener_->OnConnected(this); 60 return listener_->OnConnected(this);
43 } 61 }
44 62
45 virtual Status SendCommandAndGetResult( 63 virtual Status SendCommandAndGetResult(
46 const std::string& method, 64 const std::string& method,
47 const base::DictionaryValue& params, 65 const base::DictionaryValue& params,
48 scoped_ptr<base::DictionaryValue>* result) OVERRIDE { 66 scoped_ptr<base::DictionaryValue>* result) OVERRIDE {
49 sent_command_queue_.push_back(method); 67 sent_commands_.push_back(new DevToolsCommand(method,
68 params.DeepCopy()));
50 return Status(kOk); 69 return Status(kOk);
51 } 70 }
52 71
53 virtual void AddListener(DevToolsEventListener* listener) OVERRIDE { 72 virtual void AddListener(DevToolsEventListener* listener) OVERRIDE {
54 CHECK(!listener_); 73 CHECK(!listener_);
55 listener_ = listener; 74 listener_ = listener;
56 } 75 }
57 76
58 virtual const std::string& GetId() OVERRIDE { 77 virtual const std::string& GetId() OVERRIDE {
59 return id_; 78 return id_;
60 } 79 }
61 80
62 private: 81 private:
63 const std::string id_; // WebView id. 82 const std::string id_; // WebView id.
64 std::list<std::string> sent_command_queue_; // Commands that were sent. 83 ScopedVector<DevToolsCommand> sent_commands_; // Commands that were sent.
65 DevToolsEventListener* listener_; // The fake allows only one event listener. 84 DevToolsEventListener* listener_; // The fake allows only one event listener.
85 size_t command_index_;
66 }; 86 };
67 87
68 struct LogEntry { 88 struct LogEntry {
69 const base::Time timestamp; 89 const base::Time timestamp;
70 const Log::Level level; 90 const Log::Level level;
71 const std::string source; 91 const std::string source;
72 const std::string message; 92 const std::string message;
73 93
74 LogEntry(const base::Time& timestamp, 94 LogEntry(const base::Time& timestamp,
75 Log::Level level, 95 Log::Level level,
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
114 if (!value->GetAsDictionary(&dict)) { 134 if (!value->GetAsDictionary(&dict)) {
115 SCOPED_TRACE("JSON object is not a dictionary"); 135 SCOPED_TRACE("JSON object is not a dictionary");
116 ADD_FAILURE(); 136 ADD_FAILURE();
117 return scoped_ptr<base::DictionaryValue>(); 137 return scoped_ptr<base::DictionaryValue>();
118 } 138 }
119 return scoped_ptr<base::DictionaryValue>(dict->DeepCopy()); 139 return scoped_ptr<base::DictionaryValue>(dict->DeepCopy());
120 } 140 }
121 141
122 void ValidateLogEntry(const LogEntry *entry, 142 void ValidateLogEntry(const LogEntry *entry,
123 const std::string& expected_webview, 143 const std::string& expected_webview,
124 const std::string& expected_method) { 144 const std::string& expected_method,
145 const base::DictionaryValue& expected_params) {
125 EXPECT_EQ(Log::kInfo, entry->level); 146 EXPECT_EQ(Log::kInfo, entry->level);
126 EXPECT_LT(0, entry->timestamp.ToTimeT()); 147 EXPECT_LT(0, entry->timestamp.ToTimeT());
127 148
128 scoped_ptr<base::DictionaryValue> message(ParseDictionary(entry->message)); 149 scoped_ptr<base::DictionaryValue> message(ParseDictionary(entry->message));
129 std::string webview; 150 std::string webview;
130 EXPECT_TRUE(message->GetString("webview", &webview)); 151 EXPECT_TRUE(message->GetString("webview", &webview));
131 EXPECT_EQ(expected_webview, webview); 152 EXPECT_EQ(expected_webview, webview);
132 std::string method; 153 std::string method;
133 EXPECT_TRUE(message->GetString("message.method", &method)); 154 EXPECT_TRUE(message->GetString("message.method", &method));
134 EXPECT_EQ(expected_method, method); 155 EXPECT_EQ(expected_method, method);
135 base::DictionaryValue* params; 156 base::DictionaryValue* params;
136 EXPECT_TRUE(message->GetDictionary("message.params", &params)); 157 EXPECT_TRUE(message->GetDictionary("message.params", &params));
137 EXPECT_EQ(0u, params->size()); 158 EXPECT_TRUE(params->Equals(&expected_params));
159 }
160
161 void ValidateLogEntry(const LogEntry *entry,
162 const std::string& expected_webview,
163 const std::string& expected_method) {
164 base::DictionaryValue empty_params;
165 ValidateLogEntry(entry, expected_webview, expected_method, empty_params);
166 }
167
168 void ExpectCommand(FakeDevToolsClient& client, const std::string& method) {
169 DevToolsCommand* cmd;
170 // Use ASSERT so that test fails if no command is returned.
171 ASSERT_TRUE(client.PopSentCommand(&cmd));
172 EXPECT_EQ(method, cmd->method);
138 } 173 }
139 174
140 void ExpectEnableDomains(FakeDevToolsClient& client) { 175 void ExpectEnableDomains(FakeDevToolsClient& client) {
141 EXPECT_EQ("Network.enable", client.PopSentCommand()); 176 ExpectCommand(client, "Network.enable");
142 EXPECT_EQ("Page.enable", client.PopSentCommand()); 177 ExpectCommand(client, "Page.enable");
143 EXPECT_EQ("Timeline.start", client.PopSentCommand()); 178 ExpectCommand(client, "Timeline.start");
144 EXPECT_TRUE(client.PopSentCommand().empty());
145 } 179 }
146 180
147 } // namespace 181 } // namespace
148 182
149 TEST(PerformanceLogger, OneWebView) { 183 TEST(PerformanceLogger, OneWebView) {
150 FakeDevToolsClient client("webview-1"); 184 FakeDevToolsClient client("webview-1");
151 FakeLog log; 185 FakeLog log;
152 PerformanceLogger logger(&log); 186 Session session("test");
187 PerformanceLogger logger(&log, &session);
153 188
154 client.AddListener(&logger); 189 client.AddListener(&logger);
155 logger.OnConnected(&client); 190 logger.OnConnected(&client);
156 ExpectEnableDomains(client); 191 ExpectEnableDomains(client);
157 ASSERT_EQ(kOk, client.TriggerEvent("Network.gaga").code()); 192 ASSERT_EQ(kOk, client.TriggerEvent("Network.gaga").code());
158 ASSERT_EQ(kOk, client.TriggerEvent("Page.ulala").code()); 193 ASSERT_EQ(kOk, client.TriggerEvent("Page.ulala").code());
159 // Ignore -- different domain. 194 // Ignore -- different domain.
160 ASSERT_EQ(kOk, client.TriggerEvent("Console.bad").code()); 195 ASSERT_EQ(kOk, client.TriggerEvent("Console.bad").code());
161 196
162 ASSERT_EQ(2u, log.GetEntries().size()); 197 ASSERT_EQ(2u, log.GetEntries().size());
163 ValidateLogEntry(log.GetEntries()[0], "webview-1", "Network.gaga"); 198 ValidateLogEntry(log.GetEntries()[0], "webview-1", "Network.gaga");
164 ValidateLogEntry(log.GetEntries()[1], "webview-1", "Page.ulala"); 199 ValidateLogEntry(log.GetEntries()[1], "webview-1", "Page.ulala");
165 } 200 }
166 201
167 TEST(PerformanceLogger, TwoWebViews) { 202 TEST(PerformanceLogger, TwoWebViews) {
168 FakeDevToolsClient client1("webview-1"); 203 FakeDevToolsClient client1("webview-1");
169 FakeDevToolsClient client2("webview-2"); 204 FakeDevToolsClient client2("webview-2");
170 FakeLog log; 205 FakeLog log;
171 PerformanceLogger logger(&log); 206 Session session("test");
207 PerformanceLogger logger(&log, &session);
172 208
173 client1.AddListener(&logger); 209 client1.AddListener(&logger);
174 client2.AddListener(&logger); 210 client2.AddListener(&logger);
175 logger.OnConnected(&client1); 211 logger.OnConnected(&client1);
176 logger.OnConnected(&client2); 212 logger.OnConnected(&client2);
177 ExpectEnableDomains(client1); 213 ExpectEnableDomains(client1);
178 ExpectEnableDomains(client2); 214 ExpectEnableDomains(client2);
179 // OnConnected sends the enable command only to that client, not others. 215 // OnConnected sends the enable command only to that client, not others.
180 client1.ConnectIfNecessary(); 216 client1.ConnectIfNecessary();
181 ExpectEnableDomains(client1); 217 ExpectEnableDomains(client1);
182 EXPECT_TRUE(client2.PopSentCommand().empty()); 218 DevToolsCommand* cmd;
219 ASSERT_FALSE(client2.PopSentCommand(&cmd));
183 220
184 ASSERT_EQ(kOk, client1.TriggerEvent("Page.gaga1").code()); 221 ASSERT_EQ(kOk, client1.TriggerEvent("Page.gaga1").code());
185 ASSERT_EQ(kOk, client2.TriggerEvent("Timeline.gaga2").code()); 222 ASSERT_EQ(kOk, client2.TriggerEvent("Timeline.gaga2").code());
186 223
187 ASSERT_EQ(2u, log.GetEntries().size()); 224 ASSERT_EQ(2u, log.GetEntries().size());
188 ValidateLogEntry(log.GetEntries()[0], "webview-1", "Page.gaga1"); 225 ValidateLogEntry(log.GetEntries()[0], "webview-1", "Page.gaga1");
189 ValidateLogEntry(log.GetEntries()[1], "webview-2", "Timeline.gaga2"); 226 ValidateLogEntry(log.GetEntries()[1], "webview-2", "Timeline.gaga2");
190 } 227 }
191 228
192 TEST(PerformanceLogger, PerfLoggingPrefs) { 229 TEST(PerformanceLogger, PerfLoggingPrefs) {
193 FakeDevToolsClient client("webview-1"); 230 FakeDevToolsClient client("webview-1");
194 FakeLog log; 231 FakeLog log;
232 Session session("test");
195 PerfLoggingPrefs prefs; 233 PerfLoggingPrefs prefs;
196 ASSERT_EQ(PerfLoggingPrefs::InspectorDomainStatus::kDefaultEnabled, 234 EXPECT_EQ(PerfLoggingPrefs::InspectorDomainStatus::kDefaultEnabled,
197 prefs.network); 235 prefs.network);
198 prefs.network = PerfLoggingPrefs::InspectorDomainStatus::kExplicitlyDisabled; 236 prefs.network = PerfLoggingPrefs::InspectorDomainStatus::kExplicitlyDisabled;
199 // Trace categories should be ignored until tracing support is implemented. 237 prefs.trace_categories = "benchmark,blink.console";
200 prefs.trace_categories = "benchmark,webkit.console"; 238 PerformanceLogger logger(&log, &session, prefs);
201 PerformanceLogger logger(&log, prefs);
202 239
203 client.AddListener(&logger); 240 client.AddListener(&logger);
204 logger.OnConnected(&client); 241 logger.OnConnected(&client);
205 EXPECT_EQ("Page.enable", client.PopSentCommand()); 242 ExpectCommand(client, "Page.enable");
206 // Trace categories ignored, so Timeline shouldn't be implicitly disabled. 243 // Do not expect Timeline.enable command since specifying trace categories
207 EXPECT_EQ("Timeline.start", client.PopSentCommand()); 244 // implicitly disables Timeline feed.
208 EXPECT_TRUE(client.PopSentCommand().empty()); 245 DevToolsCommand* cmd;
246 ASSERT_FALSE(client.PopSentCommand(&cmd));
209 } 247 }
248
249 namespace {
250
251 class FakeBrowserwideClient : public FakeDevToolsClient {
252 public:
253 FakeBrowserwideClient()
254 : FakeDevToolsClient(DevToolsClientImpl::kBrowserwideDevToolsClientId),
255 events_handled_(false) {}
256 virtual ~FakeBrowserwideClient() {}
257
258 bool events_handled() const {
259 return events_handled_;
260 }
261
262 // Overridden from DevToolsClient:
263 virtual Status HandleEventsUntil(
264 const ConditionalFunc& conditional_func,
265 const base::TimeDelta& timeout) OVERRIDE {
266 TriggerEvent("Tracing.tracingComplete");
267 events_handled_ = true;
268 return Status(kOk);
269 }
270
271 private:
272 bool events_handled_;
273 };
274
275 } // namespace
276
277 TEST(PerformanceLogger, TracingStartStop) {
278 FakeBrowserwideClient client;
279 FakeLog log;
280 Session session("test");
281 PerfLoggingPrefs prefs;
282 prefs.trace_categories = "benchmark,blink.console";
283 PerformanceLogger logger(&log, &session, prefs);
284
285 client.AddListener(&logger);
286 logger.OnConnected(&client);
287 DevToolsCommand* cmd;
288 ASSERT_TRUE(client.PopSentCommand(&cmd));
289 EXPECT_EQ("Tracing.start", cmd->method);
290 std::string expected_cats;
291 EXPECT_TRUE(cmd->params->GetString("categories", &expected_cats));
292 EXPECT_EQ("benchmark,blink.console", expected_cats);
293 int expected_interval = 0;
294 EXPECT_TRUE(cmd->params->GetInteger("bufferUsageReportingInterval",
295 &expected_interval));
296 EXPECT_GT(expected_interval, 0);
297 ASSERT_FALSE(client.PopSentCommand(&cmd));
298
299 EXPECT_FALSE(client.events_handled());
300 // Trigger a dump of the DevTools trace buffer.
301 ASSERT_EQ(kOk, logger.BeforeCommand("GetLog").code());
302 EXPECT_TRUE(client.events_handled());
303 ExpectCommand(client, "Tracing.end");
304 ExpectCommand(client, "Tracing.start"); // Tracing should re-start.
305 ASSERT_FALSE(client.PopSentCommand(&cmd));
306 }
307
308 TEST(PerformanceLogger, RecordTraceEvents) {
309 FakeBrowserwideClient client;
310 FakeLog log;
311 Session session("test");
312 PerfLoggingPrefs prefs;
313 prefs.trace_categories = "benchmark,blink.console";
314 PerformanceLogger logger(&log, &session, prefs);
315
316 client.AddListener(&logger);
317 logger.OnConnected(&client);
318 base::DictionaryValue params;
319 base::ListValue* trace_events = new base::ListValue();
320 base::DictionaryValue* event1 = new base::DictionaryValue();
321 event1->SetString("cat", "foo");
322 trace_events->Append(event1);
323 base::DictionaryValue* event2 = new base::DictionaryValue();
324 event2->SetString("cat", "bar");
325 trace_events->Append(event2);
326 params.Set("value", trace_events);
327 ASSERT_EQ(kOk, client.TriggerEvent("Tracing.dataCollected", params).code());
328
329 ASSERT_EQ(2u, log.GetEntries().size());
330 ValidateLogEntry(log.GetEntries()[0],
331 DevToolsClientImpl::kBrowserwideDevToolsClientId,
332 "Tracing.dataCollected", *event1);
333 ValidateLogEntry(log.GetEntries()[1],
334 DevToolsClientImpl::kBrowserwideDevToolsClientId,
335 "Tracing.dataCollected", *event2);
336 }
337
338 TEST(PerformanceLogger, ShouldRequestTraceEvents) {
339 FakeBrowserwideClient client;
340 FakeLog log;
341 Session session("test");
342 PerfLoggingPrefs prefs;
343 prefs.trace_categories = "benchmark,blink.console";
344 PerformanceLogger logger(&log, &session, prefs);
345
346 client.AddListener(&logger);
347 logger.OnConnected(&client);
348 EXPECT_FALSE(client.events_handled());
349 // Trace events should not be dumped for commands not in whitelist.
350 ASSERT_EQ(kOk, logger.BeforeCommand("Blah").code());
351 EXPECT_FALSE(client.events_handled());
352 ASSERT_EQ(kOk, logger.BeforeCommand("Foo").code());
353 EXPECT_FALSE(client.events_handled());
354 // Trace events should always be dumped for GetLog command.
355 ASSERT_EQ(kOk, logger.BeforeCommand("GetLog").code());
356 EXPECT_TRUE(client.events_handled());
357 }
358
359 TEST(PerformanceLogger, WarnWhenTraceBufferFull) {
360 FakeBrowserwideClient client;
361 FakeLog log;
362 Session session("test");
363 PerfLoggingPrefs prefs;
364 prefs.trace_categories = "benchmark,blink.console";
365 PerformanceLogger logger(&log, &session, prefs);
366
367 client.AddListener(&logger);
368 logger.OnConnected(&client);
369 base::DictionaryValue params;
370 params.SetDouble("value", 1.0);
371 ASSERT_EQ(kOk, client.TriggerEvent("Tracing.bufferUsage", params).code());
372
373 ASSERT_EQ(1u, log.GetEntries().size());
374 LogEntry* entry = log.GetEntries()[0];
375 EXPECT_EQ(Log::kWarning, entry->level);
376 EXPECT_LT(0, entry->timestamp.ToTimeT());
377 scoped_ptr<base::DictionaryValue> message(ParseDictionary(entry->message));
378 std::string webview;
379 EXPECT_TRUE(message->GetString("webview", &webview));
380 EXPECT_EQ(DevToolsClientImpl::kBrowserwideDevToolsClientId, webview);
381 std::string method;
382 EXPECT_TRUE(message->GetString("message.method", &method));
383 EXPECT_EQ("Tracing.bufferUsage", method);
384 base::DictionaryValue* actual_params;
385 EXPECT_TRUE(message->GetDictionary("message.params", &actual_params));
386 EXPECT_TRUE(actual_params->HasKey("error"));
387 }
OLDNEW
« no previous file with comments | « chrome/test/chromedriver/performance_logger.cc ('k') | chrome/test/chromedriver/session_commands.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698