| OLD | NEW |
| (Empty) |
| 1 // Copyright (c) 2012 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 <list> | |
| 6 #include <string> | |
| 7 | |
| 8 #include "base/bind.h" | |
| 9 #include "base/compiler_specific.h" | |
| 10 #include "base/json/json_reader.h" | |
| 11 #include "base/json/json_writer.h" | |
| 12 #include "base/memory/scoped_ptr.h" | |
| 13 #include "base/values.h" | |
| 14 #include "chrome/test/chromedriver/devtools_client_impl.h" | |
| 15 #include "chrome/test/chromedriver/devtools_event_listener.h" | |
| 16 #include "chrome/test/chromedriver/net/sync_websocket.h" | |
| 17 #include "chrome/test/chromedriver/net/sync_websocket_factory.h" | |
| 18 #include "chrome/test/chromedriver/status.h" | |
| 19 #include "googleurl/src/gurl.h" | |
| 20 #include "testing/gtest/include/gtest/gtest.h" | |
| 21 | |
| 22 namespace { | |
| 23 | |
| 24 Status CloserFunc() { | |
| 25 return Status(kOk); | |
| 26 } | |
| 27 | |
| 28 class MockSyncWebSocket : public SyncWebSocket { | |
| 29 public: | |
| 30 MockSyncWebSocket() : connected_(false), id_(-1), queued_messages_(1) {} | |
| 31 virtual ~MockSyncWebSocket() {} | |
| 32 | |
| 33 virtual bool IsConnected() OVERRIDE { | |
| 34 return connected_; | |
| 35 } | |
| 36 | |
| 37 virtual bool Connect(const GURL& url) OVERRIDE { | |
| 38 EXPECT_STREQ("http://url/", url.possibly_invalid_spec().c_str()); | |
| 39 connected_ = true; | |
| 40 return true; | |
| 41 } | |
| 42 | |
| 43 virtual bool Send(const std::string& message) OVERRIDE { | |
| 44 EXPECT_TRUE(connected_); | |
| 45 scoped_ptr<base::Value> value(base::JSONReader::Read(message)); | |
| 46 base::DictionaryValue* dict = NULL; | |
| 47 EXPECT_TRUE(value->GetAsDictionary(&dict)); | |
| 48 if (!dict) | |
| 49 return false; | |
| 50 EXPECT_TRUE(dict->GetInteger("id", &id_)); | |
| 51 std::string method; | |
| 52 EXPECT_TRUE(dict->GetString("method", &method)); | |
| 53 EXPECT_STREQ("method", method.c_str()); | |
| 54 base::DictionaryValue* params = NULL; | |
| 55 EXPECT_TRUE(dict->GetDictionary("params", ¶ms)); | |
| 56 if (!params) | |
| 57 return false; | |
| 58 int param = -1; | |
| 59 EXPECT_TRUE(params->GetInteger("param", ¶m)); | |
| 60 EXPECT_EQ(1, param); | |
| 61 return true; | |
| 62 } | |
| 63 | |
| 64 virtual bool ReceiveNextMessage(std::string* message) OVERRIDE { | |
| 65 base::DictionaryValue response; | |
| 66 response.SetInteger("id", id_); | |
| 67 base::DictionaryValue result; | |
| 68 result.SetInteger("param", 1); | |
| 69 response.Set("result", result.DeepCopy()); | |
| 70 base::JSONWriter::Write(&response, message); | |
| 71 --queued_messages_; | |
| 72 return true; | |
| 73 } | |
| 74 | |
| 75 virtual bool HasNextMessage() OVERRIDE { | |
| 76 return queued_messages_ > 0; | |
| 77 } | |
| 78 | |
| 79 protected: | |
| 80 bool connected_; | |
| 81 int id_; | |
| 82 int queued_messages_; | |
| 83 }; | |
| 84 | |
| 85 template <typename T> | |
| 86 scoped_ptr<SyncWebSocket> CreateMockSyncWebSocket() { | |
| 87 return scoped_ptr<SyncWebSocket>(new T()); | |
| 88 } | |
| 89 | |
| 90 } // namespace | |
| 91 | |
| 92 TEST(DevToolsClientImpl, SendCommand) { | |
| 93 SyncWebSocketFactory factory = | |
| 94 base::Bind(&CreateMockSyncWebSocket<MockSyncWebSocket>); | |
| 95 DevToolsClientImpl client(factory, "http://url", base::Bind(&CloserFunc)); | |
| 96 ASSERT_EQ(kOk, client.ConnectIfNecessary().code()); | |
| 97 base::DictionaryValue params; | |
| 98 params.SetInteger("param", 1); | |
| 99 ASSERT_EQ(kOk, client.SendCommand("method", params).code()); | |
| 100 } | |
| 101 | |
| 102 TEST(DevToolsClientImpl, SendCommandAndGetResult) { | |
| 103 SyncWebSocketFactory factory = | |
| 104 base::Bind(&CreateMockSyncWebSocket<MockSyncWebSocket>); | |
| 105 DevToolsClientImpl client(factory, "http://url", base::Bind(&CloserFunc)); | |
| 106 ASSERT_EQ(kOk, client.ConnectIfNecessary().code()); | |
| 107 base::DictionaryValue params; | |
| 108 params.SetInteger("param", 1); | |
| 109 scoped_ptr<base::DictionaryValue> result; | |
| 110 Status status = client.SendCommandAndGetResult("method", params, &result); | |
| 111 ASSERT_EQ(kOk, status.code()); | |
| 112 std::string json; | |
| 113 base::JSONWriter::Write(result.get(), &json); | |
| 114 ASSERT_STREQ("{\"param\":1}", json.c_str()); | |
| 115 } | |
| 116 | |
| 117 namespace { | |
| 118 | |
| 119 class MockSyncWebSocket2 : public SyncWebSocket { | |
| 120 public: | |
| 121 MockSyncWebSocket2() {} | |
| 122 virtual ~MockSyncWebSocket2() {} | |
| 123 | |
| 124 virtual bool IsConnected() OVERRIDE { | |
| 125 return false; | |
| 126 } | |
| 127 | |
| 128 virtual bool Connect(const GURL& url) OVERRIDE { | |
| 129 return false; | |
| 130 } | |
| 131 | |
| 132 virtual bool Send(const std::string& message) OVERRIDE { | |
| 133 EXPECT_TRUE(false); | |
| 134 return false; | |
| 135 } | |
| 136 | |
| 137 virtual bool ReceiveNextMessage(std::string* message) OVERRIDE { | |
| 138 EXPECT_TRUE(false); | |
| 139 return false; | |
| 140 } | |
| 141 | |
| 142 virtual bool HasNextMessage() OVERRIDE { | |
| 143 return true; | |
| 144 } | |
| 145 }; | |
| 146 | |
| 147 } // namespace | |
| 148 | |
| 149 TEST(DevToolsClientImpl, ConnectIfNecessaryConnectFails) { | |
| 150 SyncWebSocketFactory factory = | |
| 151 base::Bind(&CreateMockSyncWebSocket<MockSyncWebSocket2>); | |
| 152 DevToolsClientImpl client(factory, "http://url", base::Bind(&CloserFunc)); | |
| 153 ASSERT_EQ(kDisconnected, client.ConnectIfNecessary().code()); | |
| 154 } | |
| 155 | |
| 156 namespace { | |
| 157 | |
| 158 class MockSyncWebSocket3 : public SyncWebSocket { | |
| 159 public: | |
| 160 MockSyncWebSocket3() : connected_(false) {} | |
| 161 virtual ~MockSyncWebSocket3() {} | |
| 162 | |
| 163 virtual bool IsConnected() OVERRIDE { | |
| 164 return connected_; | |
| 165 } | |
| 166 | |
| 167 virtual bool Connect(const GURL& url) OVERRIDE { | |
| 168 connected_ = true; | |
| 169 return true; | |
| 170 } | |
| 171 | |
| 172 virtual bool Send(const std::string& message) OVERRIDE { | |
| 173 return false; | |
| 174 } | |
| 175 | |
| 176 virtual bool ReceiveNextMessage(std::string* message) OVERRIDE { | |
| 177 EXPECT_TRUE(false); | |
| 178 return false; | |
| 179 } | |
| 180 | |
| 181 virtual bool HasNextMessage() OVERRIDE { | |
| 182 return true; | |
| 183 } | |
| 184 | |
| 185 private: | |
| 186 bool connected_; | |
| 187 }; | |
| 188 | |
| 189 } // namespace | |
| 190 | |
| 191 TEST(DevToolsClientImpl, SendCommandSendFails) { | |
| 192 SyncWebSocketFactory factory = | |
| 193 base::Bind(&CreateMockSyncWebSocket<MockSyncWebSocket3>); | |
| 194 DevToolsClientImpl client(factory, "http://url", base::Bind(&CloserFunc)); | |
| 195 ASSERT_EQ(kOk, client.ConnectIfNecessary().code()); | |
| 196 base::DictionaryValue params; | |
| 197 ASSERT_TRUE(client.SendCommand("method", params).IsError()); | |
| 198 } | |
| 199 | |
| 200 namespace { | |
| 201 | |
| 202 class MockSyncWebSocket4 : public SyncWebSocket { | |
| 203 public: | |
| 204 MockSyncWebSocket4() : connected_(false) {} | |
| 205 virtual ~MockSyncWebSocket4() {} | |
| 206 | |
| 207 virtual bool IsConnected() OVERRIDE { | |
| 208 return connected_; | |
| 209 } | |
| 210 | |
| 211 virtual bool Connect(const GURL& url) OVERRIDE { | |
| 212 connected_ = true; | |
| 213 return true; | |
| 214 } | |
| 215 | |
| 216 virtual bool Send(const std::string& message) OVERRIDE { | |
| 217 return true; | |
| 218 } | |
| 219 | |
| 220 virtual bool ReceiveNextMessage(std::string* message) OVERRIDE { | |
| 221 return false; | |
| 222 } | |
| 223 | |
| 224 virtual bool HasNextMessage() OVERRIDE { | |
| 225 return true; | |
| 226 } | |
| 227 | |
| 228 private: | |
| 229 bool connected_; | |
| 230 }; | |
| 231 | |
| 232 } // namespace | |
| 233 | |
| 234 TEST(DevToolsClientImpl, SendCommandReceiveNextMessageFails) { | |
| 235 SyncWebSocketFactory factory = | |
| 236 base::Bind(&CreateMockSyncWebSocket<MockSyncWebSocket4>); | |
| 237 DevToolsClientImpl client(factory, "http://url", base::Bind(&CloserFunc)); | |
| 238 ASSERT_EQ(kOk, client.ConnectIfNecessary().code()); | |
| 239 base::DictionaryValue params; | |
| 240 ASSERT_TRUE(client.SendCommand("method", params).IsError()); | |
| 241 } | |
| 242 | |
| 243 namespace { | |
| 244 | |
| 245 class FakeSyncWebSocket : public SyncWebSocket { | |
| 246 public: | |
| 247 FakeSyncWebSocket() : connected_(false) {} | |
| 248 virtual ~FakeSyncWebSocket() {} | |
| 249 | |
| 250 virtual bool IsConnected() OVERRIDE { | |
| 251 return connected_; | |
| 252 } | |
| 253 | |
| 254 virtual bool Connect(const GURL& url) OVERRIDE { | |
| 255 EXPECT_FALSE(connected_); | |
| 256 connected_ = true; | |
| 257 return true; | |
| 258 } | |
| 259 | |
| 260 virtual bool Send(const std::string& message) OVERRIDE { | |
| 261 return true; | |
| 262 } | |
| 263 | |
| 264 virtual bool ReceiveNextMessage(std::string* message) OVERRIDE { | |
| 265 return true; | |
| 266 } | |
| 267 | |
| 268 virtual bool HasNextMessage() OVERRIDE { | |
| 269 return true; | |
| 270 } | |
| 271 | |
| 272 private: | |
| 273 bool connected_; | |
| 274 }; | |
| 275 | |
| 276 bool ReturnCommand( | |
| 277 const std::string& message, | |
| 278 int expected_id, | |
| 279 internal::InspectorMessageType* type, | |
| 280 internal::InspectorEvent* event, | |
| 281 internal::InspectorCommandResponse* command_response) { | |
| 282 *type = internal::kCommandResponseMessageType; | |
| 283 command_response->id = expected_id; | |
| 284 command_response->result.reset(new base::DictionaryValue()); | |
| 285 return true; | |
| 286 } | |
| 287 | |
| 288 bool ReturnBadResponse( | |
| 289 const std::string& message, | |
| 290 int expected_id, | |
| 291 internal::InspectorMessageType* type, | |
| 292 internal::InspectorEvent* event, | |
| 293 internal::InspectorCommandResponse* command_response) { | |
| 294 *type = internal::kCommandResponseMessageType; | |
| 295 command_response->id = expected_id; | |
| 296 command_response->result.reset(new base::DictionaryValue()); | |
| 297 return false; | |
| 298 } | |
| 299 | |
| 300 bool ReturnCommandBadId( | |
| 301 const std::string& message, | |
| 302 int expected_id, | |
| 303 internal::InspectorMessageType* type, | |
| 304 internal::InspectorEvent* event, | |
| 305 internal::InspectorCommandResponse* command_response) { | |
| 306 *type = internal::kCommandResponseMessageType; | |
| 307 command_response->id = expected_id + 100; | |
| 308 command_response->result.reset(new base::DictionaryValue()); | |
| 309 return true; | |
| 310 } | |
| 311 | |
| 312 bool ReturnCommandError( | |
| 313 const std::string& message, | |
| 314 int expected_id, | |
| 315 internal::InspectorMessageType* type, | |
| 316 internal::InspectorEvent* event, | |
| 317 internal::InspectorCommandResponse* command_response) { | |
| 318 *type = internal::kCommandResponseMessageType; | |
| 319 command_response->id = expected_id; | |
| 320 command_response->error = "err"; | |
| 321 return true; | |
| 322 } | |
| 323 | |
| 324 class MockListener : public DevToolsEventListener { | |
| 325 public: | |
| 326 MockListener() : called_(false) {} | |
| 327 virtual ~MockListener() { | |
| 328 EXPECT_TRUE(called_); | |
| 329 } | |
| 330 | |
| 331 virtual Status OnConnected() OVERRIDE { | |
| 332 return Status(kOk); | |
| 333 } | |
| 334 | |
| 335 virtual void OnEvent(const std::string& method, | |
| 336 const base::DictionaryValue& params) OVERRIDE { | |
| 337 called_ = true; | |
| 338 EXPECT_STREQ("method", method.c_str()); | |
| 339 EXPECT_TRUE(params.HasKey("key")); | |
| 340 } | |
| 341 | |
| 342 private: | |
| 343 bool called_; | |
| 344 }; | |
| 345 | |
| 346 bool ReturnEventThenResponse( | |
| 347 bool* first, | |
| 348 const std::string& message, | |
| 349 int expected_id, | |
| 350 internal::InspectorMessageType* type, | |
| 351 internal::InspectorEvent* event, | |
| 352 internal::InspectorCommandResponse* command_response) { | |
| 353 if (*first) { | |
| 354 *type = internal::kEventMessageType; | |
| 355 event->method = "method"; | |
| 356 event->params.reset(new base::DictionaryValue()); | |
| 357 event->params->SetInteger("key", 1); | |
| 358 } else { | |
| 359 *type = internal::kCommandResponseMessageType; | |
| 360 command_response->id = expected_id; | |
| 361 base::DictionaryValue params; | |
| 362 command_response->result.reset(new base::DictionaryValue()); | |
| 363 command_response->result->SetInteger("key", 2); | |
| 364 } | |
| 365 *first = false; | |
| 366 return true; | |
| 367 } | |
| 368 | |
| 369 bool ReturnEvent( | |
| 370 const std::string& message, | |
| 371 int expected_id, | |
| 372 internal::InspectorMessageType* type, | |
| 373 internal::InspectorEvent* event, | |
| 374 internal::InspectorCommandResponse* command_response) { | |
| 375 *type = internal::kEventMessageType; | |
| 376 event->method = "method"; | |
| 377 event->params.reset(new base::DictionaryValue()); | |
| 378 event->params->SetInteger("key", 1); | |
| 379 return true; | |
| 380 } | |
| 381 | |
| 382 bool ReturnOutOfOrderResponses( | |
| 383 int* recurse_count, | |
| 384 DevToolsClient* client, | |
| 385 const std::string& message, | |
| 386 int expected_id, | |
| 387 internal::InspectorMessageType* type, | |
| 388 internal::InspectorEvent* event, | |
| 389 internal::InspectorCommandResponse* command_response) { | |
| 390 int key = 0; | |
| 391 base::DictionaryValue params; | |
| 392 params.SetInteger("param", 1); | |
| 393 switch ((*recurse_count)++) { | |
| 394 case 0: | |
| 395 client->SendCommand("method", params); | |
| 396 *type = internal::kEventMessageType; | |
| 397 event->method = "method"; | |
| 398 event->params.reset(new base::DictionaryValue()); | |
| 399 event->params->SetInteger("key", 1); | |
| 400 return true; | |
| 401 case 1: | |
| 402 command_response->id = expected_id - 1; | |
| 403 key = 2; | |
| 404 break; | |
| 405 case 2: | |
| 406 command_response->id = expected_id; | |
| 407 key = 3; | |
| 408 break; | |
| 409 } | |
| 410 *type = internal::kCommandResponseMessageType; | |
| 411 command_response->result.reset(new base::DictionaryValue()); | |
| 412 command_response->result->SetInteger("key", key); | |
| 413 return true; | |
| 414 } | |
| 415 | |
| 416 bool ReturnError( | |
| 417 const std::string& message, | |
| 418 int expected_id, | |
| 419 internal::InspectorMessageType* type, | |
| 420 internal::InspectorEvent* event, | |
| 421 internal::InspectorCommandResponse* command_response) { | |
| 422 return false; | |
| 423 } | |
| 424 | |
| 425 Status AlwaysTrue(bool* is_met) { | |
| 426 *is_met = true; | |
| 427 return Status(kOk); | |
| 428 } | |
| 429 | |
| 430 Status AlwaysError(bool* is_met) { | |
| 431 return Status(kUnknownError); | |
| 432 } | |
| 433 | |
| 434 } // namespace | |
| 435 | |
| 436 TEST(DevToolsClientImpl, SendCommandOnlyConnectsOnce) { | |
| 437 SyncWebSocketFactory factory = | |
| 438 base::Bind(&CreateMockSyncWebSocket<FakeSyncWebSocket>); | |
| 439 DevToolsClientImpl client(factory, "http://url", base::Bind(&CloserFunc), | |
| 440 base::Bind(&ReturnCommand)); | |
| 441 ASSERT_EQ(kOk, client.ConnectIfNecessary().code()); | |
| 442 base::DictionaryValue params; | |
| 443 ASSERT_TRUE(client.SendCommand("method", params).IsOk()); | |
| 444 ASSERT_TRUE(client.SendCommand("method", params).IsOk()); | |
| 445 } | |
| 446 | |
| 447 TEST(DevToolsClientImpl, SendCommandBadResponse) { | |
| 448 SyncWebSocketFactory factory = | |
| 449 base::Bind(&CreateMockSyncWebSocket<FakeSyncWebSocket>); | |
| 450 DevToolsClientImpl client(factory, "http://url", base::Bind(&CloserFunc), | |
| 451 base::Bind(&ReturnBadResponse)); | |
| 452 ASSERT_EQ(kOk, client.ConnectIfNecessary().code()); | |
| 453 base::DictionaryValue params; | |
| 454 ASSERT_TRUE(client.SendCommand("method", params).IsError()); | |
| 455 } | |
| 456 | |
| 457 TEST(DevToolsClientImpl, SendCommandBadId) { | |
| 458 SyncWebSocketFactory factory = | |
| 459 base::Bind(&CreateMockSyncWebSocket<FakeSyncWebSocket>); | |
| 460 DevToolsClientImpl client(factory, "http://url", base::Bind(&CloserFunc), | |
| 461 base::Bind(&ReturnCommandBadId)); | |
| 462 ASSERT_EQ(kOk, client.ConnectIfNecessary().code()); | |
| 463 base::DictionaryValue params; | |
| 464 ASSERT_TRUE(client.SendCommand("method", params).IsError()); | |
| 465 } | |
| 466 | |
| 467 TEST(DevToolsClientImpl, SendCommandResponseError) { | |
| 468 SyncWebSocketFactory factory = | |
| 469 base::Bind(&CreateMockSyncWebSocket<FakeSyncWebSocket>); | |
| 470 DevToolsClientImpl client(factory, "http://url", base::Bind(&CloserFunc), | |
| 471 base::Bind(&ReturnCommandError)); | |
| 472 ASSERT_EQ(kOk, client.ConnectIfNecessary().code()); | |
| 473 base::DictionaryValue params; | |
| 474 ASSERT_TRUE(client.SendCommand("method", params).IsError()); | |
| 475 } | |
| 476 | |
| 477 TEST(DevToolsClientImpl, SendCommandEventBeforeResponse) { | |
| 478 SyncWebSocketFactory factory = | |
| 479 base::Bind(&CreateMockSyncWebSocket<FakeSyncWebSocket>); | |
| 480 MockListener listener; | |
| 481 bool first = true; | |
| 482 DevToolsClientImpl client(factory, "http://url", base::Bind(&CloserFunc), | |
| 483 base::Bind(&ReturnEventThenResponse, &first)); | |
| 484 client.AddListener(&listener); | |
| 485 ASSERT_EQ(kOk, client.ConnectIfNecessary().code()); | |
| 486 base::DictionaryValue params; | |
| 487 scoped_ptr<base::DictionaryValue> result; | |
| 488 ASSERT_TRUE(client.SendCommandAndGetResult("method", params, &result).IsOk()); | |
| 489 ASSERT_TRUE(result); | |
| 490 int key; | |
| 491 ASSERT_TRUE(result->GetInteger("key", &key)); | |
| 492 ASSERT_EQ(2, key); | |
| 493 } | |
| 494 | |
| 495 TEST(ParseInspectorMessage, NonJson) { | |
| 496 internal::InspectorMessageType type; | |
| 497 internal::InspectorEvent event; | |
| 498 internal::InspectorCommandResponse response; | |
| 499 ASSERT_FALSE(internal::ParseInspectorMessage( | |
| 500 "hi", 0, &type, &event, &response)); | |
| 501 } | |
| 502 | |
| 503 TEST(ParseInspectorMessage, NeitherCommandNorEvent) { | |
| 504 internal::InspectorMessageType type; | |
| 505 internal::InspectorEvent event; | |
| 506 internal::InspectorCommandResponse response; | |
| 507 ASSERT_FALSE(internal::ParseInspectorMessage( | |
| 508 "{}", 0, &type, &event, &response)); | |
| 509 } | |
| 510 | |
| 511 TEST(ParseInspectorMessage, EventNoParams) { | |
| 512 internal::InspectorMessageType type; | |
| 513 internal::InspectorEvent event; | |
| 514 internal::InspectorCommandResponse response; | |
| 515 ASSERT_TRUE(internal::ParseInspectorMessage( | |
| 516 "{\"method\":\"method\"}", 0, &type, &event, &response)); | |
| 517 ASSERT_EQ(internal::kEventMessageType, type); | |
| 518 ASSERT_STREQ("method", event.method.c_str()); | |
| 519 ASSERT_TRUE(event.params->IsType(base::Value::TYPE_DICTIONARY)); | |
| 520 } | |
| 521 | |
| 522 TEST(ParseInspectorMessage, EventWithParams) { | |
| 523 internal::InspectorMessageType type; | |
| 524 internal::InspectorEvent event; | |
| 525 internal::InspectorCommandResponse response; | |
| 526 ASSERT_TRUE(internal::ParseInspectorMessage( | |
| 527 "{\"method\":\"method\",\"params\":{\"key\":100}}", | |
| 528 0, &type, &event, &response)); | |
| 529 ASSERT_EQ(internal::kEventMessageType, type); | |
| 530 ASSERT_STREQ("method", event.method.c_str()); | |
| 531 int key; | |
| 532 ASSERT_TRUE(event.params->GetInteger("key", &key)); | |
| 533 ASSERT_EQ(100, key); | |
| 534 } | |
| 535 | |
| 536 TEST(ParseInspectorMessage, CommandNoErrorOrResult) { | |
| 537 internal::InspectorMessageType type; | |
| 538 internal::InspectorEvent event; | |
| 539 internal::InspectorCommandResponse response; | |
| 540 ASSERT_FALSE(internal::ParseInspectorMessage( | |
| 541 "{\"id\":1}", 0, &type, &event, &response)); | |
| 542 } | |
| 543 | |
| 544 TEST(ParseInspectorMessage, CommandError) { | |
| 545 internal::InspectorMessageType type; | |
| 546 internal::InspectorEvent event; | |
| 547 internal::InspectorCommandResponse response; | |
| 548 ASSERT_TRUE(internal::ParseInspectorMessage( | |
| 549 "{\"id\":1,\"error\":{}}", 0, &type, &event, &response)); | |
| 550 ASSERT_EQ(internal::kCommandResponseMessageType, type); | |
| 551 ASSERT_EQ(1, response.id); | |
| 552 ASSERT_TRUE(response.error.length()); | |
| 553 ASSERT_FALSE(response.result); | |
| 554 } | |
| 555 | |
| 556 TEST(ParseInspectorMessage, Command) { | |
| 557 internal::InspectorMessageType type; | |
| 558 internal::InspectorEvent event; | |
| 559 internal::InspectorCommandResponse response; | |
| 560 ASSERT_TRUE(internal::ParseInspectorMessage( | |
| 561 "{\"id\":1,\"result\":{\"key\":1}}", 0, &type, &event, &response)); | |
| 562 ASSERT_EQ(internal::kCommandResponseMessageType, type); | |
| 563 ASSERT_EQ(1, response.id); | |
| 564 ASSERT_FALSE(response.error.length()); | |
| 565 int key; | |
| 566 ASSERT_TRUE(response.result->GetInteger("key", &key)); | |
| 567 ASSERT_EQ(1, key); | |
| 568 } | |
| 569 | |
| 570 TEST(DevToolsClientImpl, HandleEventsUntil) { | |
| 571 MockListener listener; | |
| 572 SyncWebSocketFactory factory = | |
| 573 base::Bind(&CreateMockSyncWebSocket<MockSyncWebSocket>); | |
| 574 DevToolsClientImpl client(factory, "http://url", base::Bind(&CloserFunc), | |
| 575 base::Bind(&ReturnEvent)); | |
| 576 client.AddListener(&listener); | |
| 577 ASSERT_EQ(kOk, client.ConnectIfNecessary().code()); | |
| 578 Status status = client.HandleEventsUntil(base::Bind(&AlwaysTrue)); | |
| 579 ASSERT_EQ(kOk, status.code()); | |
| 580 } | |
| 581 | |
| 582 TEST(DevToolsClientImpl, WaitForNextEventCommand) { | |
| 583 SyncWebSocketFactory factory = | |
| 584 base::Bind(&CreateMockSyncWebSocket<MockSyncWebSocket>); | |
| 585 DevToolsClientImpl client(factory, "http://url", base::Bind(&CloserFunc), | |
| 586 base::Bind(&ReturnCommand)); | |
| 587 ASSERT_EQ(kOk, client.ConnectIfNecessary().code()); | |
| 588 Status status = client.HandleEventsUntil(base::Bind(&AlwaysTrue)); | |
| 589 ASSERT_EQ(kUnknownError, status.code()); | |
| 590 } | |
| 591 | |
| 592 TEST(DevToolsClientImpl, WaitForNextEventError) { | |
| 593 SyncWebSocketFactory factory = | |
| 594 base::Bind(&CreateMockSyncWebSocket<MockSyncWebSocket>); | |
| 595 DevToolsClientImpl client(factory, "http://url", base::Bind(&CloserFunc), | |
| 596 base::Bind(&ReturnError)); | |
| 597 ASSERT_EQ(kOk, client.ConnectIfNecessary().code()); | |
| 598 Status status = client.HandleEventsUntil(base::Bind(&AlwaysTrue)); | |
| 599 ASSERT_EQ(kUnknownError, status.code()); | |
| 600 } | |
| 601 | |
| 602 TEST(DevToolsClientImpl, WaitForNextEventConditionalFuncReturnsError) { | |
| 603 SyncWebSocketFactory factory = | |
| 604 base::Bind(&CreateMockSyncWebSocket<MockSyncWebSocket>); | |
| 605 DevToolsClientImpl client(factory, "http://url", base::Bind(&CloserFunc), | |
| 606 base::Bind(&ReturnEvent)); | |
| 607 ASSERT_EQ(kOk, client.ConnectIfNecessary().code()); | |
| 608 Status status = client.HandleEventsUntil(base::Bind(&AlwaysError)); | |
| 609 ASSERT_EQ(kUnknownError, status.code()); | |
| 610 } | |
| 611 | |
| 612 TEST(DevToolsClientImpl, NestedCommandsWithOutOfOrderResults) { | |
| 613 SyncWebSocketFactory factory = | |
| 614 base::Bind(&CreateMockSyncWebSocket<MockSyncWebSocket>); | |
| 615 int recurse_count = 0; | |
| 616 DevToolsClientImpl client(factory, "http://url", base::Bind(&CloserFunc)); | |
| 617 ASSERT_EQ(kOk, client.ConnectIfNecessary().code()); | |
| 618 client.SetParserFuncForTesting( | |
| 619 base::Bind(&ReturnOutOfOrderResponses, &recurse_count, &client)); | |
| 620 base::DictionaryValue params; | |
| 621 params.SetInteger("param", 1); | |
| 622 scoped_ptr<base::DictionaryValue> result; | |
| 623 ASSERT_TRUE(client.SendCommandAndGetResult("method", params, &result).IsOk()); | |
| 624 ASSERT_TRUE(result); | |
| 625 int key; | |
| 626 ASSERT_TRUE(result->GetInteger("key", &key)); | |
| 627 ASSERT_EQ(2, key); | |
| 628 } | |
| 629 | |
| 630 namespace { | |
| 631 | |
| 632 class OnConnectedListener : public DevToolsEventListener { | |
| 633 public: | |
| 634 OnConnectedListener(const std::string& method, DevToolsClient* client) | |
| 635 : method_(method), | |
| 636 client_(client), | |
| 637 on_connected_called_(false), | |
| 638 on_event_called_(false) { | |
| 639 client_->AddListener(this); | |
| 640 } | |
| 641 virtual ~OnConnectedListener() {} | |
| 642 | |
| 643 void VerifyCalled() { | |
| 644 EXPECT_TRUE(on_connected_called_); | |
| 645 EXPECT_TRUE(on_event_called_); | |
| 646 } | |
| 647 | |
| 648 virtual Status OnConnected() OVERRIDE { | |
| 649 EXPECT_FALSE(on_connected_called_); | |
| 650 EXPECT_FALSE(on_event_called_); | |
| 651 on_connected_called_ = true; | |
| 652 base::DictionaryValue params; | |
| 653 return client_->SendCommand(method_, params); | |
| 654 } | |
| 655 | |
| 656 virtual void OnEvent(const std::string& method, | |
| 657 const base::DictionaryValue& params) OVERRIDE { | |
| 658 EXPECT_TRUE(on_connected_called_); | |
| 659 on_event_called_ = true; | |
| 660 } | |
| 661 | |
| 662 private: | |
| 663 std::string method_; | |
| 664 DevToolsClient* client_; | |
| 665 bool on_connected_called_; | |
| 666 bool on_event_called_; | |
| 667 }; | |
| 668 | |
| 669 class OnConnectedSyncWebSocket : public SyncWebSocket { | |
| 670 public: | |
| 671 OnConnectedSyncWebSocket() : connected_(false) {} | |
| 672 virtual ~OnConnectedSyncWebSocket() {} | |
| 673 | |
| 674 virtual bool IsConnected() OVERRIDE { | |
| 675 return connected_; | |
| 676 } | |
| 677 | |
| 678 virtual bool Connect(const GURL& url) OVERRIDE { | |
| 679 connected_ = true; | |
| 680 return true; | |
| 681 } | |
| 682 | |
| 683 virtual bool Send(const std::string& message) OVERRIDE { | |
| 684 EXPECT_TRUE(connected_); | |
| 685 scoped_ptr<base::Value> value(base::JSONReader::Read(message)); | |
| 686 base::DictionaryValue* dict = NULL; | |
| 687 EXPECT_TRUE(value->GetAsDictionary(&dict)); | |
| 688 if (!dict) | |
| 689 return false; | |
| 690 int id; | |
| 691 EXPECT_TRUE(dict->GetInteger("id", &id)); | |
| 692 std::string method; | |
| 693 EXPECT_TRUE(dict->GetString("method", &method)); | |
| 694 | |
| 695 base::DictionaryValue response; | |
| 696 response.SetInteger("id", id); | |
| 697 response.Set("result", new base::DictionaryValue()); | |
| 698 std::string json_response; | |
| 699 base::JSONWriter::Write(&response, &json_response); | |
| 700 queued_response_.push_back(json_response); | |
| 701 | |
| 702 // Push one event. | |
| 703 base::DictionaryValue event; | |
| 704 event.SetString("method", "updateEvent"); | |
| 705 event.Set("params", new base::DictionaryValue()); | |
| 706 std::string json_event; | |
| 707 base::JSONWriter::Write(&event, &json_event); | |
| 708 queued_response_.push_back(json_event); | |
| 709 | |
| 710 return true; | |
| 711 } | |
| 712 | |
| 713 virtual bool ReceiveNextMessage(std::string* message) OVERRIDE { | |
| 714 if (queued_response_.empty()) | |
| 715 return false; | |
| 716 *message = queued_response_.front(); | |
| 717 queued_response_.pop_front(); | |
| 718 return true; | |
| 719 } | |
| 720 | |
| 721 virtual bool HasNextMessage() OVERRIDE { | |
| 722 return !queued_response_.empty(); | |
| 723 } | |
| 724 | |
| 725 private: | |
| 726 bool connected_; | |
| 727 std::list<std::string> queued_response_; | |
| 728 }; | |
| 729 | |
| 730 } // namespace | |
| 731 | |
| 732 TEST(DevToolsClientImpl, ProcessOnConnectedFirstOnCommand) { | |
| 733 SyncWebSocketFactory factory = | |
| 734 base::Bind(&CreateMockSyncWebSocket<OnConnectedSyncWebSocket>); | |
| 735 DevToolsClientImpl client(factory, "http://url", base::Bind(&CloserFunc)); | |
| 736 OnConnectedListener listener1("DOM.getDocument", &client); | |
| 737 OnConnectedListener listener2("Runtime.enable", &client); | |
| 738 OnConnectedListener listener3("Page.enable", &client); | |
| 739 ASSERT_EQ(kOk, client.ConnectIfNecessary().code()); | |
| 740 base::DictionaryValue params; | |
| 741 EXPECT_EQ(kOk, client.SendCommand("Runtime.execute", params).code()); | |
| 742 listener1.VerifyCalled(); | |
| 743 listener2.VerifyCalled(); | |
| 744 listener3.VerifyCalled(); | |
| 745 } | |
| 746 | |
| 747 TEST(DevToolsClientImpl, ProcessOnConnectedFirstOnHandleEventsUntil) { | |
| 748 SyncWebSocketFactory factory = | |
| 749 base::Bind(&CreateMockSyncWebSocket<OnConnectedSyncWebSocket>); | |
| 750 DevToolsClientImpl client(factory, "http://url", base::Bind(&CloserFunc)); | |
| 751 OnConnectedListener listener1("DOM.getDocument", &client); | |
| 752 OnConnectedListener listener2("Runtime.enable", &client); | |
| 753 OnConnectedListener listener3("Page.enable", &client); | |
| 754 ASSERT_EQ(kOk, client.ConnectIfNecessary().code()); | |
| 755 EXPECT_EQ(kOk, client.HandleReceivedEvents().code()); | |
| 756 listener1.VerifyCalled(); | |
| 757 listener2.VerifyCalled(); | |
| 758 listener3.VerifyCalled(); | |
| 759 } | |
| 760 | |
| 761 namespace { | |
| 762 | |
| 763 class DisconnectedSyncWebSocket : public MockSyncWebSocket { | |
| 764 public: | |
| 765 DisconnectedSyncWebSocket() : connection_count_(0), command_count_(0) {} | |
| 766 virtual ~DisconnectedSyncWebSocket() {} | |
| 767 | |
| 768 virtual bool Connect(const GURL& url) OVERRIDE { | |
| 769 connection_count_++; | |
| 770 connected_ = connection_count_ != 2; | |
| 771 return connected_; | |
| 772 } | |
| 773 | |
| 774 virtual bool Send(const std::string& message) OVERRIDE { | |
| 775 command_count_++; | |
| 776 if (command_count_ == 1) { | |
| 777 connected_ = false; | |
| 778 return false; | |
| 779 } | |
| 780 return MockSyncWebSocket::Send(message); | |
| 781 } | |
| 782 | |
| 783 private: | |
| 784 int connection_count_; | |
| 785 int command_count_; | |
| 786 }; | |
| 787 | |
| 788 Status CheckCloserFuncCalled(bool* is_called) { | |
| 789 *is_called = true; | |
| 790 return Status(kOk); | |
| 791 } | |
| 792 | |
| 793 } // namespace | |
| 794 | |
| 795 TEST(DevToolsClientImpl, Reconnect) { | |
| 796 SyncWebSocketFactory factory = | |
| 797 base::Bind(&CreateMockSyncWebSocket<DisconnectedSyncWebSocket>); | |
| 798 bool is_called = false; | |
| 799 DevToolsClientImpl client(factory, "http://url", | |
| 800 base::Bind(&CheckCloserFuncCalled, &is_called)); | |
| 801 ASSERT_FALSE(is_called); | |
| 802 ASSERT_EQ(kOk, client.ConnectIfNecessary().code()); | |
| 803 ASSERT_FALSE(is_called); | |
| 804 base::DictionaryValue params; | |
| 805 params.SetInteger("param", 1); | |
| 806 is_called = false; | |
| 807 ASSERT_EQ(kDisconnected, client.SendCommand("method", params).code()); | |
| 808 ASSERT_FALSE(is_called); | |
| 809 ASSERT_EQ(kDisconnected, client.HandleReceivedEvents().code()); | |
| 810 ASSERT_FALSE(is_called); | |
| 811 ASSERT_EQ(kOk, client.ConnectIfNecessary().code()); | |
| 812 ASSERT_TRUE(is_called); | |
| 813 is_called = false; | |
| 814 ASSERT_EQ(kOk, client.SendCommand("method", params).code()); | |
| 815 ASSERT_FALSE(is_called); | |
| 816 } | |
| OLD | NEW |