12a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 22a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 32a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// found in the LICENSE file. 42a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 52a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <list> 62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <string> 72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/bind.h" 92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/compiler_specific.h" 102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/json/json_reader.h" 112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/json/json_writer.h" 122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/memory/scoped_ptr.h" 13868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/stringprintf.h" 142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/values.h" 152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/test/chromedriver/chrome/devtools_client_impl.h" 162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/test/chromedriver/chrome/devtools_event_listener.h" 172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/test/chromedriver/chrome/status.h" 182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/test/chromedriver/net/sync_websocket.h" 192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/test/chromedriver/net/sync_websocket_factory.h" 202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h" 217dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "url/gurl.h" 222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace { 242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)Status CloserFunc() { 262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return Status(kOk); 272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class MockSyncWebSocket : public SyncWebSocket { 302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) public: 312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) MockSyncWebSocket() : connected_(false), id_(-1), queued_messages_(1) {} 322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) virtual ~MockSyncWebSocket() {} 332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) virtual bool IsConnected() OVERRIDE { 352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return connected_; 362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) virtual bool Connect(const GURL& url) OVERRIDE { 392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_STREQ("http://url/", url.possibly_invalid_spec().c_str()); 402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) connected_ = true; 412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return true; 422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) virtual bool Send(const std::string& message) OVERRIDE { 452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_TRUE(connected_); 462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_ptr<base::Value> value(base::JSONReader::Read(message)); 472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::DictionaryValue* dict = NULL; 482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_TRUE(value->GetAsDictionary(&dict)); 492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!dict) 502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_TRUE(dict->GetInteger("id", &id_)); 522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::string method; 532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_TRUE(dict->GetString("method", &method)); 542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_STREQ("method", method.c_str()); 552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::DictionaryValue* params = NULL; 562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_TRUE(dict->GetDictionary("params", ¶ms)); 572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!params) 582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int param = -1; 602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_TRUE(params->GetInteger("param", ¶m)); 612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_EQ(1, param); 622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return true; 632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 65868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) virtual SyncWebSocket::StatusCode ReceiveNextMessage( 66868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) std::string* message, 67868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) const base::TimeDelta& timeout) OVERRIDE { 68424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) if (timeout <= base::TimeDelta()) 69424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) return SyncWebSocket::kTimeout; 702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::DictionaryValue response; 712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) response.SetInteger("id", id_); 722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::DictionaryValue result; 732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) result.SetInteger("param", 1); 742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) response.Set("result", result.DeepCopy()); 752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::JSONWriter::Write(&response, message); 762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) --queued_messages_; 77868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return SyncWebSocket::kOk; 782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) virtual bool HasNextMessage() OVERRIDE { 812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return queued_messages_ > 0; 822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) protected: 852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool connected_; 862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int id_; 872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int queued_messages_; 882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}; 892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)template <typename T> 912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)scoped_ptr<SyncWebSocket> CreateMockSyncWebSocket() { 922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return scoped_ptr<SyncWebSocket>(new T()); 932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 95868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)class DevToolsClientImplTest : public testing::Test { 96868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) protected: 97868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) DevToolsClientImplTest() : long_timeout_(base::TimeDelta::FromMinutes(5)) {} 98868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 99868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) const base::TimeDelta long_timeout_; 100868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}; 101868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} // namespace 1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 104868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)TEST_F(DevToolsClientImplTest, SendCommand) { 1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SyncWebSocketFactory factory = 1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Bind(&CreateMockSyncWebSocket<MockSyncWebSocket>); 107c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DevToolsClientImpl client(factory, "http://url", "id", 10858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) base::Bind(&CloserFunc)); 1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ASSERT_EQ(kOk, client.ConnectIfNecessary().code()); 1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::DictionaryValue params; 1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) params.SetInteger("param", 1); 1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ASSERT_EQ(kOk, client.SendCommand("method", params).code()); 1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 115868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)TEST_F(DevToolsClientImplTest, SendCommandAndGetResult) { 1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SyncWebSocketFactory factory = 1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Bind(&CreateMockSyncWebSocket<MockSyncWebSocket>); 118c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DevToolsClientImpl client(factory, "http://url", "id", 11958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) base::Bind(&CloserFunc)); 1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ASSERT_EQ(kOk, client.ConnectIfNecessary().code()); 1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::DictionaryValue params; 1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) params.SetInteger("param", 1); 1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_ptr<base::DictionaryValue> result; 1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Status status = client.SendCommandAndGetResult("method", params, &result); 1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ASSERT_EQ(kOk, status.code()); 1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::string json; 1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::JSONWriter::Write(result.get(), &json); 1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ASSERT_STREQ("{\"param\":1}", json.c_str()); 1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace { 1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class MockSyncWebSocket2 : public SyncWebSocket { 1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) public: 1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) MockSyncWebSocket2() {} 1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) virtual ~MockSyncWebSocket2() {} 1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) virtual bool IsConnected() OVERRIDE { 1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) virtual bool Connect(const GURL& url) OVERRIDE { 1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) virtual bool Send(const std::string& message) OVERRIDE { 1472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_TRUE(false); 1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 1492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 151868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) virtual SyncWebSocket::StatusCode ReceiveNextMessage( 152868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) std::string* message, 153868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) const base::TimeDelta& timeout) OVERRIDE { 1542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_TRUE(false); 155868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return SyncWebSocket::kDisconnected; 1562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) virtual bool HasNextMessage() OVERRIDE { 1592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return true; 1602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}; 1622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} // namespace 1642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 165868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)TEST_F(DevToolsClientImplTest, ConnectIfNecessaryConnectFails) { 1662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SyncWebSocketFactory factory = 1672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Bind(&CreateMockSyncWebSocket<MockSyncWebSocket2>); 168c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DevToolsClientImpl client(factory, "http://url", "id", 16958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) base::Bind(&CloserFunc)); 1702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ASSERT_EQ(kDisconnected, client.ConnectIfNecessary().code()); 1712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace { 1742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class MockSyncWebSocket3 : public SyncWebSocket { 1762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) public: 1772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) MockSyncWebSocket3() : connected_(false) {} 1782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) virtual ~MockSyncWebSocket3() {} 1792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) virtual bool IsConnected() OVERRIDE { 1812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return connected_; 1822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) virtual bool Connect(const GURL& url) OVERRIDE { 1852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) connected_ = true; 1862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return true; 1872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) virtual bool Send(const std::string& message) OVERRIDE { 1902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 1912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 193868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) virtual SyncWebSocket::StatusCode ReceiveNextMessage( 194868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) std::string* message, 195868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) const base::TimeDelta& timeout) OVERRIDE { 1962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_TRUE(false); 197868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return SyncWebSocket::kDisconnected; 1982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) virtual bool HasNextMessage() OVERRIDE { 2012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return true; 2022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 2032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) private: 2052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool connected_; 2062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}; 2072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} // namespace 2092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 210868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)TEST_F(DevToolsClientImplTest, SendCommandSendFails) { 2112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SyncWebSocketFactory factory = 2122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Bind(&CreateMockSyncWebSocket<MockSyncWebSocket3>); 213c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DevToolsClientImpl client(factory, "http://url", "id", 21458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) base::Bind(&CloserFunc)); 2152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ASSERT_EQ(kOk, client.ConnectIfNecessary().code()); 2162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::DictionaryValue params; 2172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ASSERT_TRUE(client.SendCommand("method", params).IsError()); 2182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace { 2212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class MockSyncWebSocket4 : public SyncWebSocket { 2232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) public: 2242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) MockSyncWebSocket4() : connected_(false) {} 2252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) virtual ~MockSyncWebSocket4() {} 2262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) virtual bool IsConnected() OVERRIDE { 2282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return connected_; 2292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 2302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) virtual bool Connect(const GURL& url) OVERRIDE { 2322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) connected_ = true; 2332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return true; 2342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 2352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) virtual bool Send(const std::string& message) OVERRIDE { 2372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return true; 2382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 2392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 240868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) virtual SyncWebSocket::StatusCode ReceiveNextMessage( 241868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) std::string* message, 242868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) const base::TimeDelta& timeout) OVERRIDE { 243868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return SyncWebSocket::kDisconnected; 2442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 2452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) virtual bool HasNextMessage() OVERRIDE { 2472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return true; 2482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 2492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) private: 2512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool connected_; 2522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}; 2532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} // namespace 2552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 256868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)TEST_F(DevToolsClientImplTest, SendCommandReceiveNextMessageFails) { 2572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SyncWebSocketFactory factory = 2582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Bind(&CreateMockSyncWebSocket<MockSyncWebSocket4>); 259c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DevToolsClientImpl client(factory, "http://url", "id", 26058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) base::Bind(&CloserFunc)); 2612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ASSERT_EQ(kOk, client.ConnectIfNecessary().code()); 2622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::DictionaryValue params; 2632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ASSERT_TRUE(client.SendCommand("method", params).IsError()); 2642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace { 2672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class FakeSyncWebSocket : public SyncWebSocket { 2692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) public: 2702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) FakeSyncWebSocket() : connected_(false) {} 2712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) virtual ~FakeSyncWebSocket() {} 2722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) virtual bool IsConnected() OVERRIDE { 2742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return connected_; 2752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 2762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) virtual bool Connect(const GURL& url) OVERRIDE { 2782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_FALSE(connected_); 2792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) connected_ = true; 2802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return true; 2812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 2822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) virtual bool Send(const std::string& message) OVERRIDE { 2842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return true; 2852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 2862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 287868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) virtual SyncWebSocket::StatusCode ReceiveNextMessage( 288868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) std::string* message, 289868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) const base::TimeDelta& timeout) OVERRIDE { 290868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return SyncWebSocket::kOk; 2912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 2922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) virtual bool HasNextMessage() OVERRIDE { 2942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return true; 2952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 2962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) private: 2982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool connected_; 2992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}; 3002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool ReturnCommand( 3022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const std::string& message, 3032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int expected_id, 3042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) internal::InspectorMessageType* type, 3052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) internal::InspectorEvent* event, 3062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) internal::InspectorCommandResponse* command_response) { 3072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) *type = internal::kCommandResponseMessageType; 3082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) command_response->id = expected_id; 3092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) command_response->result.reset(new base::DictionaryValue()); 3102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return true; 3112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 3122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool ReturnBadResponse( 3142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const std::string& message, 3152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int expected_id, 3162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) internal::InspectorMessageType* type, 3172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) internal::InspectorEvent* event, 3182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) internal::InspectorCommandResponse* command_response) { 3192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) *type = internal::kCommandResponseMessageType; 3202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) command_response->id = expected_id; 3212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) command_response->result.reset(new base::DictionaryValue()); 3222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 3232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 3242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool ReturnCommandBadId( 3262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const std::string& message, 3272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int expected_id, 3282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) internal::InspectorMessageType* type, 3292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) internal::InspectorEvent* event, 3302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) internal::InspectorCommandResponse* command_response) { 3312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) *type = internal::kCommandResponseMessageType; 3322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) command_response->id = expected_id + 100; 3332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) command_response->result.reset(new base::DictionaryValue()); 3342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return true; 3352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 3362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool ReturnCommandError( 3382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const std::string& message, 3392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int expected_id, 3402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) internal::InspectorMessageType* type, 3412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) internal::InspectorEvent* event, 3422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) internal::InspectorCommandResponse* command_response) { 3432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) *type = internal::kCommandResponseMessageType; 3442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) command_response->id = expected_id; 3452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) command_response->error = "err"; 3462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return true; 3472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 3482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class MockListener : public DevToolsEventListener { 3502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) public: 3512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) MockListener() : called_(false) {} 3522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) virtual ~MockListener() { 3532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_TRUE(called_); 3542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 3552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 356c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) virtual Status OnConnected(DevToolsClient* client) OVERRIDE { 3572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return Status(kOk); 3582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 3592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 360868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) virtual Status OnEvent(DevToolsClient* client, 361868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) const std::string& method, 362868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) const base::DictionaryValue& params) OVERRIDE { 3632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) called_ = true; 3642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_STREQ("method", method.c_str()); 3652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_TRUE(params.HasKey("key")); 366868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return Status(kOk); 3672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 3682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) private: 3702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool called_; 3712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}; 3722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool ReturnEventThenResponse( 3742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool* first, 3752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const std::string& message, 3762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int expected_id, 3772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) internal::InspectorMessageType* type, 3782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) internal::InspectorEvent* event, 3792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) internal::InspectorCommandResponse* command_response) { 3802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (*first) { 3812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) *type = internal::kEventMessageType; 3822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) event->method = "method"; 3832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) event->params.reset(new base::DictionaryValue()); 3842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) event->params->SetInteger("key", 1); 3852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else { 3862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) *type = internal::kCommandResponseMessageType; 3872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) command_response->id = expected_id; 3882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::DictionaryValue params; 3892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) command_response->result.reset(new base::DictionaryValue()); 3902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) command_response->result->SetInteger("key", 2); 3912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 3922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) *first = false; 3932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return true; 3942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 3952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool ReturnEvent( 3972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const std::string& message, 3982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int expected_id, 3992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) internal::InspectorMessageType* type, 4002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) internal::InspectorEvent* event, 4012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) internal::InspectorCommandResponse* command_response) { 4022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) *type = internal::kEventMessageType; 4032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) event->method = "method"; 4042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) event->params.reset(new base::DictionaryValue()); 4052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) event->params->SetInteger("key", 1); 4062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return true; 4072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 4082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool ReturnOutOfOrderResponses( 4102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int* recurse_count, 4112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DevToolsClient* client, 4122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const std::string& message, 4132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int expected_id, 4142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) internal::InspectorMessageType* type, 4152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) internal::InspectorEvent* event, 4162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) internal::InspectorCommandResponse* command_response) { 4172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int key = 0; 4182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::DictionaryValue params; 4192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) params.SetInteger("param", 1); 4202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) switch ((*recurse_count)++) { 4212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) case 0: 4222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) client->SendCommand("method", params); 4232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) *type = internal::kEventMessageType; 4242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) event->method = "method"; 4252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) event->params.reset(new base::DictionaryValue()); 4262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) event->params->SetInteger("key", 1); 4272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return true; 4282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) case 1: 4292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) command_response->id = expected_id - 1; 4302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) key = 2; 4312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) break; 4322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) case 2: 4332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) command_response->id = expected_id; 4342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) key = 3; 4352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) break; 4362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 4372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) *type = internal::kCommandResponseMessageType; 4382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) command_response->result.reset(new base::DictionaryValue()); 4392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) command_response->result->SetInteger("key", key); 4402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return true; 4412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 4422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool ReturnError( 4442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const std::string& message, 4452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int expected_id, 4462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) internal::InspectorMessageType* type, 4472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) internal::InspectorEvent* event, 4482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) internal::InspectorCommandResponse* command_response) { 4492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 4502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 4512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)Status AlwaysTrue(bool* is_met) { 4532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) *is_met = true; 4542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return Status(kOk); 4552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 4562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)Status AlwaysError(bool* is_met) { 4582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return Status(kUnknownError); 4592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 4602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} // namespace 4622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 463868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)TEST_F(DevToolsClientImplTest, SendCommandOnlyConnectsOnce) { 4642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SyncWebSocketFactory factory = 4652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Bind(&CreateMockSyncWebSocket<FakeSyncWebSocket>); 466c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DevToolsClientImpl client(factory, "http://url", "id", 46758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) base::Bind(&CloserFunc), 4682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Bind(&ReturnCommand)); 4692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ASSERT_EQ(kOk, client.ConnectIfNecessary().code()); 4702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::DictionaryValue params; 4712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ASSERT_TRUE(client.SendCommand("method", params).IsOk()); 4722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ASSERT_TRUE(client.SendCommand("method", params).IsOk()); 4732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 4742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 475868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)TEST_F(DevToolsClientImplTest, SendCommandBadResponse) { 4762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SyncWebSocketFactory factory = 4772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Bind(&CreateMockSyncWebSocket<FakeSyncWebSocket>); 478c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DevToolsClientImpl client(factory, "http://url", "id", 47958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) base::Bind(&CloserFunc), 4802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Bind(&ReturnBadResponse)); 4812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ASSERT_EQ(kOk, client.ConnectIfNecessary().code()); 4822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::DictionaryValue params; 4832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ASSERT_TRUE(client.SendCommand("method", params).IsError()); 4842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 4852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 486868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)TEST_F(DevToolsClientImplTest, SendCommandBadId) { 4872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SyncWebSocketFactory factory = 4882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Bind(&CreateMockSyncWebSocket<FakeSyncWebSocket>); 489c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DevToolsClientImpl client(factory, "http://url", "id", 49058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) base::Bind(&CloserFunc), 4912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Bind(&ReturnCommandBadId)); 4922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ASSERT_EQ(kOk, client.ConnectIfNecessary().code()); 4932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::DictionaryValue params; 4942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ASSERT_TRUE(client.SendCommand("method", params).IsError()); 4952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 4962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 497868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)TEST_F(DevToolsClientImplTest, SendCommandResponseError) { 4982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SyncWebSocketFactory factory = 4992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Bind(&CreateMockSyncWebSocket<FakeSyncWebSocket>); 500c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DevToolsClientImpl client(factory, "http://url", "id", 50158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) base::Bind(&CloserFunc), 5022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Bind(&ReturnCommandError)); 5032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ASSERT_EQ(kOk, client.ConnectIfNecessary().code()); 5042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::DictionaryValue params; 5052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ASSERT_TRUE(client.SendCommand("method", params).IsError()); 5062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 5072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 508868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)TEST_F(DevToolsClientImplTest, SendCommandEventBeforeResponse) { 5092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SyncWebSocketFactory factory = 5102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Bind(&CreateMockSyncWebSocket<FakeSyncWebSocket>); 5112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) MockListener listener; 5122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool first = true; 513c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DevToolsClientImpl client(factory, "http://url", "id", 51458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) base::Bind(&CloserFunc), 5152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Bind(&ReturnEventThenResponse, &first)); 5162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) client.AddListener(&listener); 5172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ASSERT_EQ(kOk, client.ConnectIfNecessary().code()); 5182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::DictionaryValue params; 5192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_ptr<base::DictionaryValue> result; 5202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ASSERT_TRUE(client.SendCommandAndGetResult("method", params, &result).IsOk()); 5212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ASSERT_TRUE(result); 5222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int key; 5232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ASSERT_TRUE(result->GetInteger("key", &key)); 5242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ASSERT_EQ(2, key); 5252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 5262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 5272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST(ParseInspectorMessage, NonJson) { 5282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) internal::InspectorMessageType type; 5292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) internal::InspectorEvent event; 5302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) internal::InspectorCommandResponse response; 5312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ASSERT_FALSE(internal::ParseInspectorMessage( 5322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) "hi", 0, &type, &event, &response)); 5332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 5342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 5352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST(ParseInspectorMessage, NeitherCommandNorEvent) { 5362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) internal::InspectorMessageType type; 5372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) internal::InspectorEvent event; 5382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) internal::InspectorCommandResponse response; 5392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ASSERT_FALSE(internal::ParseInspectorMessage( 5402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) "{}", 0, &type, &event, &response)); 5412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 5422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 5432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST(ParseInspectorMessage, EventNoParams) { 5442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) internal::InspectorMessageType type; 5452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) internal::InspectorEvent event; 5462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) internal::InspectorCommandResponse response; 5472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ASSERT_TRUE(internal::ParseInspectorMessage( 5482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) "{\"method\":\"method\"}", 0, &type, &event, &response)); 5492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ASSERT_EQ(internal::kEventMessageType, type); 5502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ASSERT_STREQ("method", event.method.c_str()); 5512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ASSERT_TRUE(event.params->IsType(base::Value::TYPE_DICTIONARY)); 5522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 5532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 5542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST(ParseInspectorMessage, EventWithParams) { 5552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) internal::InspectorMessageType type; 5562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) internal::InspectorEvent event; 5572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) internal::InspectorCommandResponse response; 5582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ASSERT_TRUE(internal::ParseInspectorMessage( 5592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) "{\"method\":\"method\",\"params\":{\"key\":100}}", 5602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 0, &type, &event, &response)); 5612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ASSERT_EQ(internal::kEventMessageType, type); 5622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ASSERT_STREQ("method", event.method.c_str()); 5632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int key; 5642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ASSERT_TRUE(event.params->GetInteger("key", &key)); 5652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ASSERT_EQ(100, key); 5662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 5672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 5682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST(ParseInspectorMessage, CommandNoErrorOrResult) { 5692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) internal::InspectorMessageType type; 5702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) internal::InspectorEvent event; 5712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) internal::InspectorCommandResponse response; 5725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // As per Chromium issue 392577, DevTools does not necessarily return a 5735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // "result" dictionary for every valid response. If neither "error" nor 5745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // "result" keys are present, a blank result dictionary should be inferred. 5755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ASSERT_TRUE(internal::ParseInspectorMessage( 5762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) "{\"id\":1}", 0, &type, &event, &response)); 5775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ASSERT_TRUE(response.result->empty()); 5782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 5792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 5802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST(ParseInspectorMessage, CommandError) { 5812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) internal::InspectorMessageType type; 5822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) internal::InspectorEvent event; 5832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) internal::InspectorCommandResponse response; 5842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ASSERT_TRUE(internal::ParseInspectorMessage( 5852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) "{\"id\":1,\"error\":{}}", 0, &type, &event, &response)); 5862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ASSERT_EQ(internal::kCommandResponseMessageType, type); 5872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ASSERT_EQ(1, response.id); 5882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ASSERT_TRUE(response.error.length()); 5892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ASSERT_FALSE(response.result); 5902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 5912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 5922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST(ParseInspectorMessage, Command) { 5932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) internal::InspectorMessageType type; 5942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) internal::InspectorEvent event; 5952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) internal::InspectorCommandResponse response; 5962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ASSERT_TRUE(internal::ParseInspectorMessage( 5972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) "{\"id\":1,\"result\":{\"key\":1}}", 0, &type, &event, &response)); 5982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ASSERT_EQ(internal::kCommandResponseMessageType, type); 5992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ASSERT_EQ(1, response.id); 6002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ASSERT_FALSE(response.error.length()); 6012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int key; 6022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ASSERT_TRUE(response.result->GetInteger("key", &key)); 6032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ASSERT_EQ(1, key); 6042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 6052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 606868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)TEST_F(DevToolsClientImplTest, HandleEventsUntil) { 6072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) MockListener listener; 6082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SyncWebSocketFactory factory = 6092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Bind(&CreateMockSyncWebSocket<MockSyncWebSocket>); 610c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DevToolsClientImpl client(factory, "http://url", "id", 61158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) base::Bind(&CloserFunc), 6122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Bind(&ReturnEvent)); 6132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) client.AddListener(&listener); 6142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ASSERT_EQ(kOk, client.ConnectIfNecessary().code()); 615868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) Status status = client.HandleEventsUntil(base::Bind(&AlwaysTrue), 616868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) long_timeout_); 6172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ASSERT_EQ(kOk, status.code()); 6182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 6192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 620868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)TEST_F(DevToolsClientImplTest, HandleEventsUntilTimeout) { 621868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) SyncWebSocketFactory factory = 622868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) base::Bind(&CreateMockSyncWebSocket<MockSyncWebSocket>); 623868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) DevToolsClientImpl client(factory, "http://url", "id", 62458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) base::Bind(&CloserFunc), 625868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) base::Bind(&ReturnEvent)); 626868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) ASSERT_EQ(kOk, client.ConnectIfNecessary().code()); 627868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) Status status = client.HandleEventsUntil(base::Bind(&AlwaysTrue), 628868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) base::TimeDelta()); 629868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) ASSERT_EQ(kTimeout, status.code()); 630868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)} 631868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 632868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)TEST_F(DevToolsClientImplTest, WaitForNextEventCommand) { 6332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SyncWebSocketFactory factory = 6342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Bind(&CreateMockSyncWebSocket<MockSyncWebSocket>); 635c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DevToolsClientImpl client(factory, "http://url", "id", 63658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) base::Bind(&CloserFunc), 6372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Bind(&ReturnCommand)); 6382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ASSERT_EQ(kOk, client.ConnectIfNecessary().code()); 639868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) Status status = client.HandleEventsUntil(base::Bind(&AlwaysTrue), 640868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) long_timeout_); 6412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ASSERT_EQ(kUnknownError, status.code()); 6422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 6432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 644868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)TEST_F(DevToolsClientImplTest, WaitForNextEventError) { 6452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SyncWebSocketFactory factory = 6462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Bind(&CreateMockSyncWebSocket<MockSyncWebSocket>); 647c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DevToolsClientImpl client(factory, "http://url", "id", 64858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) base::Bind(&CloserFunc), 6492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Bind(&ReturnError)); 6502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ASSERT_EQ(kOk, client.ConnectIfNecessary().code()); 651868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) Status status = client.HandleEventsUntil(base::Bind(&AlwaysTrue), 652868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) long_timeout_); 6532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ASSERT_EQ(kUnknownError, status.code()); 6542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 6552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 656868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)TEST_F(DevToolsClientImplTest, WaitForNextEventConditionalFuncReturnsError) { 6572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SyncWebSocketFactory factory = 6582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Bind(&CreateMockSyncWebSocket<MockSyncWebSocket>); 659c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DevToolsClientImpl client(factory, "http://url", "id", 66058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) base::Bind(&CloserFunc), 6612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Bind(&ReturnEvent)); 6622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ASSERT_EQ(kOk, client.ConnectIfNecessary().code()); 663868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) Status status = client.HandleEventsUntil(base::Bind(&AlwaysError), 664868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) long_timeout_); 6652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ASSERT_EQ(kUnknownError, status.code()); 6662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 6672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 668868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)TEST_F(DevToolsClientImplTest, NestedCommandsWithOutOfOrderResults) { 6692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SyncWebSocketFactory factory = 6702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Bind(&CreateMockSyncWebSocket<MockSyncWebSocket>); 6712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int recurse_count = 0; 672c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DevToolsClientImpl client(factory, "http://url", "id", 67358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) base::Bind(&CloserFunc)); 6742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ASSERT_EQ(kOk, client.ConnectIfNecessary().code()); 6752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) client.SetParserFuncForTesting( 6762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Bind(&ReturnOutOfOrderResponses, &recurse_count, &client)); 6772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::DictionaryValue params; 6782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) params.SetInteger("param", 1); 6792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_ptr<base::DictionaryValue> result; 6802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ASSERT_TRUE(client.SendCommandAndGetResult("method", params, &result).IsOk()); 6812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ASSERT_TRUE(result); 6822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int key; 6832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ASSERT_TRUE(result->GetInteger("key", &key)); 6842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ASSERT_EQ(2, key); 6852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 6862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 6872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace { 6882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 6892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class OnConnectedListener : public DevToolsEventListener { 6902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) public: 6912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) OnConnectedListener(const std::string& method, DevToolsClient* client) 6922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) : method_(method), 6932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) client_(client), 6942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) on_connected_called_(false), 6952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) on_event_called_(false) { 6962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) client_->AddListener(this); 6972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 6982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) virtual ~OnConnectedListener() {} 6992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 7002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) void VerifyCalled() { 7012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_TRUE(on_connected_called_); 7022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_TRUE(on_event_called_); 7032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 7042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 705c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) virtual Status OnConnected(DevToolsClient* client) OVERRIDE { 706c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) EXPECT_EQ(client_, client); 707c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) EXPECT_STREQ("onconnected-id", client->GetId().c_str()); 7082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_FALSE(on_connected_called_); 7092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_FALSE(on_event_called_); 7102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) on_connected_called_ = true; 7112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::DictionaryValue params; 7122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return client_->SendCommand(method_, params); 7132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 7142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 715868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) virtual Status OnEvent(DevToolsClient* client, 716868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) const std::string& method, 717868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) const base::DictionaryValue& params) OVERRIDE { 718c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) EXPECT_EQ(client_, client); 719c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) EXPECT_STREQ("onconnected-id", client->GetId().c_str()); 7202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_TRUE(on_connected_called_); 7212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) on_event_called_ = true; 722868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return Status(kOk); 7232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 7242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 7252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) private: 7262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::string method_; 7272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DevToolsClient* client_; 7282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool on_connected_called_; 7292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool on_event_called_; 7302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}; 7312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 7322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class OnConnectedSyncWebSocket : public SyncWebSocket { 7332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) public: 7342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) OnConnectedSyncWebSocket() : connected_(false) {} 7352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) virtual ~OnConnectedSyncWebSocket() {} 7362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 7372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) virtual bool IsConnected() OVERRIDE { 7382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return connected_; 7392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 7402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 7412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) virtual bool Connect(const GURL& url) OVERRIDE { 7422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) connected_ = true; 7432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return true; 7442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 7452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 7462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) virtual bool Send(const std::string& message) OVERRIDE { 7472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_TRUE(connected_); 7482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_ptr<base::Value> value(base::JSONReader::Read(message)); 7492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::DictionaryValue* dict = NULL; 7502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_TRUE(value->GetAsDictionary(&dict)); 7512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!dict) 7522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 7532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int id; 7542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_TRUE(dict->GetInteger("id", &id)); 7552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::string method; 7562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_TRUE(dict->GetString("method", &method)); 7572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 7582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::DictionaryValue response; 7592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) response.SetInteger("id", id); 7602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) response.Set("result", new base::DictionaryValue()); 7612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::string json_response; 7622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::JSONWriter::Write(&response, &json_response); 7632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) queued_response_.push_back(json_response); 7642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 7652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Push one event. 7662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::DictionaryValue event; 7672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) event.SetString("method", "updateEvent"); 7682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) event.Set("params", new base::DictionaryValue()); 7692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::string json_event; 7702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::JSONWriter::Write(&event, &json_event); 7712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) queued_response_.push_back(json_event); 7722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 7732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return true; 7742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 7752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 776868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) virtual SyncWebSocket::StatusCode ReceiveNextMessage( 777868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) std::string* message, 778868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) const base::TimeDelta& timeout) OVERRIDE { 7792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (queued_response_.empty()) 780868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return SyncWebSocket::kDisconnected; 7812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) *message = queued_response_.front(); 7822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) queued_response_.pop_front(); 783868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return SyncWebSocket::kOk; 7842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 7852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 7862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) virtual bool HasNextMessage() OVERRIDE { 7872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return !queued_response_.empty(); 7882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 7892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 7902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) private: 7912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool connected_; 7922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::list<std::string> queued_response_; 7932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}; 7942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 7952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} // namespace 7962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 797868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)TEST_F(DevToolsClientImplTest, ProcessOnConnectedFirstOnCommand) { 7982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SyncWebSocketFactory factory = 7992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Bind(&CreateMockSyncWebSocket<OnConnectedSyncWebSocket>); 800c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DevToolsClientImpl client(factory, "http://url", "onconnected-id", 80158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) base::Bind(&CloserFunc)); 8022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) OnConnectedListener listener1("DOM.getDocument", &client); 8032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) OnConnectedListener listener2("Runtime.enable", &client); 8042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) OnConnectedListener listener3("Page.enable", &client); 8052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ASSERT_EQ(kOk, client.ConnectIfNecessary().code()); 8062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::DictionaryValue params; 8072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_EQ(kOk, client.SendCommand("Runtime.execute", params).code()); 8082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) listener1.VerifyCalled(); 8092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) listener2.VerifyCalled(); 8102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) listener3.VerifyCalled(); 8112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 8122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 813868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)TEST_F(DevToolsClientImplTest, ProcessOnConnectedFirstOnHandleEventsUntil) { 8142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SyncWebSocketFactory factory = 8152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Bind(&CreateMockSyncWebSocket<OnConnectedSyncWebSocket>); 816c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DevToolsClientImpl client(factory, "http://url", "onconnected-id", 81758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) base::Bind(&CloserFunc)); 8182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) OnConnectedListener listener1("DOM.getDocument", &client); 8192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) OnConnectedListener listener2("Runtime.enable", &client); 8202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) OnConnectedListener listener3("Page.enable", &client); 8212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ASSERT_EQ(kOk, client.ConnectIfNecessary().code()); 8222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_EQ(kOk, client.HandleReceivedEvents().code()); 8232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) listener1.VerifyCalled(); 8242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) listener2.VerifyCalled(); 8252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) listener3.VerifyCalled(); 8262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 8272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 8282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace { 8292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 8302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class MockSyncWebSocket5 : public SyncWebSocket { 8312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) public: 8322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) MockSyncWebSocket5() : request_no_(0) {} 8332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) virtual ~MockSyncWebSocket5() {} 8342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 8352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) virtual bool IsConnected() OVERRIDE { 8362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return true; 8372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 8382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 8392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) virtual bool Connect(const GURL& url) OVERRIDE { 8402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return true; 8412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 8422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 8432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) virtual bool Send(const std::string& message) OVERRIDE { 8442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return true; 8452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 8462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 847868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) virtual SyncWebSocket::StatusCode ReceiveNextMessage( 848868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) std::string* message, 849868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) const base::TimeDelta& timeout) OVERRIDE { 8502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (request_no_ == 0) { 8512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) *message = "{\"method\": \"m\", \"params\": {}}"; 8522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else { 8532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) *message = base::StringPrintf( 8542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) "{\"result\": {}, \"id\": %d}", request_no_); 8552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 8562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) request_no_++; 857868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return SyncWebSocket::kOk; 8582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 8592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 8602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) virtual bool HasNextMessage() OVERRIDE { 8612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 8622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 8632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 8642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) private: 8652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int request_no_; 8662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}; 8672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 8682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class OtherEventListener : public DevToolsEventListener { 8692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) public: 8702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) OtherEventListener() : received_event_(false) {} 8712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) virtual ~OtherEventListener() {} 8722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 873c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) virtual Status OnConnected(DevToolsClient* client) OVERRIDE { 8742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return Status(kOk); 8752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 876868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) virtual Status OnEvent(DevToolsClient* client, 877868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) const std::string& method, 878868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) const base::DictionaryValue& params) OVERRIDE { 8792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) received_event_ = true; 880868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return Status(kOk); 8812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 8822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 8832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool received_event_; 8842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}; 8852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 8862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class OnEventListener : public DevToolsEventListener { 8872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) public: 8882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) OnEventListener(DevToolsClient* client, 8892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) OtherEventListener* other_listener) 8902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) : client_(client), 8912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) other_listener_(other_listener) {} 8922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) virtual ~OnEventListener() {} 8932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 894c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) virtual Status OnConnected(DevToolsClient* client) OVERRIDE { 895c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) EXPECT_EQ(client_, client); 8962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return Status(kOk); 8972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 8982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 899868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) virtual Status OnEvent(DevToolsClient* client, 900868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) const std::string& method, 901868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) const base::DictionaryValue& params) OVERRIDE { 902868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) EXPECT_EQ(client_, client); 9032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) client_->SendCommand("method", params); 9042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_TRUE(other_listener_->received_event_); 905868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return Status(kOk); 9062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 9072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 9082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) private: 9092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DevToolsClient* client_; 9102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) OtherEventListener* other_listener_; 9112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}; 9122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 9132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} // namespace 9142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 915868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)TEST_F(DevToolsClientImplTest, ProcessOnEventFirst) { 9162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SyncWebSocketFactory factory = 9172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Bind(&CreateMockSyncWebSocket<MockSyncWebSocket5>); 918c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DevToolsClientImpl client(factory, "http://url", "id", 91958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) base::Bind(&CloserFunc)); 9202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) OtherEventListener listener2; 9212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) OnEventListener listener1(&client, &listener2); 9222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) client.AddListener(&listener1); 9232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) client.AddListener(&listener2); 9242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::DictionaryValue params; 9252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_EQ(kOk, client.SendCommand("method", params).code()); 9262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 9272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 9282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace { 9292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 9302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class DisconnectedSyncWebSocket : public MockSyncWebSocket { 9312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) public: 9322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DisconnectedSyncWebSocket() : connection_count_(0), command_count_(0) {} 9332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) virtual ~DisconnectedSyncWebSocket() {} 9342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 9352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) virtual bool Connect(const GURL& url) OVERRIDE { 9362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) connection_count_++; 9372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) connected_ = connection_count_ != 2; 9382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return connected_; 9392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 9402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 9412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) virtual bool Send(const std::string& message) OVERRIDE { 9422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) command_count_++; 9432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (command_count_ == 1) { 9442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) connected_ = false; 9452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 9462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 9472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return MockSyncWebSocket::Send(message); 9482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 9492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 9502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) private: 9512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int connection_count_; 9522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int command_count_; 9532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}; 9542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 9552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)Status CheckCloserFuncCalled(bool* is_called) { 9562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) *is_called = true; 9572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return Status(kOk); 9582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 9592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 9602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} // namespace 9612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 962868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)TEST_F(DevToolsClientImplTest, Reconnect) { 9632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SyncWebSocketFactory factory = 9642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Bind(&CreateMockSyncWebSocket<DisconnectedSyncWebSocket>); 9652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool is_called = false; 96690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) DevToolsClientImpl client(factory, 96790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) "http://url", 96890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) "id", 96958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) base::Bind(&CheckCloserFuncCalled, &is_called)); 9702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ASSERT_FALSE(is_called); 9712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ASSERT_EQ(kOk, client.ConnectIfNecessary().code()); 9722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ASSERT_FALSE(is_called); 9732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::DictionaryValue params; 9742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) params.SetInteger("param", 1); 9752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) is_called = false; 9762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ASSERT_EQ(kDisconnected, client.SendCommand("method", params).code()); 9772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ASSERT_FALSE(is_called); 9782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ASSERT_EQ(kDisconnected, client.HandleReceivedEvents().code()); 9792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ASSERT_FALSE(is_called); 9802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ASSERT_EQ(kOk, client.ConnectIfNecessary().code()); 9812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ASSERT_TRUE(is_called); 9822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) is_called = false; 9832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ASSERT_EQ(kOk, client.SendCommand("method", params).code()); 9842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ASSERT_FALSE(is_called); 9852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 98690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 98790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)namespace { 98890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 98990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)class MockSyncWebSocket6 : public SyncWebSocket { 99090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) public: 99190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) explicit MockSyncWebSocket6(std::list<std::string>* messages) 99290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) : messages_(messages) {} 99390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) virtual ~MockSyncWebSocket6() {} 99490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 99590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) virtual bool IsConnected() OVERRIDE { return true; } 99690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 99790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) virtual bool Connect(const GURL& url) OVERRIDE { return true; } 99890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 99990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) virtual bool Send(const std::string& message) OVERRIDE { return true; } 100090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 1001868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) virtual SyncWebSocket::StatusCode ReceiveNextMessage( 1002868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) std::string* message, 1003868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) const base::TimeDelta& timeout) OVERRIDE { 100490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (messages_->empty()) 1005868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return SyncWebSocket::kDisconnected; 100690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) *message = messages_->front(); 100790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) messages_->pop_front(); 1008868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return SyncWebSocket::kOk; 100990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 101090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 101190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) virtual bool HasNextMessage() OVERRIDE { return messages_->size(); } 101290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 101390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) private: 101490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) std::list<std::string>* messages_; 101590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}; 101690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 101790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)class MockDevToolsEventListener : public DevToolsEventListener { 101890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) public: 101990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) MockDevToolsEventListener() : id_(1) {} 102090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) virtual ~MockDevToolsEventListener() {} 102190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 102290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) virtual Status OnConnected(DevToolsClient* client) OVERRIDE { 102390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) return Status(kOk); 102490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 102590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 1026868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) virtual Status OnEvent(DevToolsClient* client, 1027868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) const std::string& method, 1028868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) const base::DictionaryValue& params) OVERRIDE { 102990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) id_++; 103090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) Status status = client->SendCommand("hello", params); 103190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) id_--; 103290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (id_ == 3) { 103390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) EXPECT_EQ(kUnexpectedAlertOpen, status.code()); 103490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } else { 103590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) EXPECT_EQ(kOk, status.code()); 103690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 1037868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return Status(kOk); 103890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 103990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 104090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) private: 104190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) int id_; 104290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}; 104390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 104490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)scoped_ptr<SyncWebSocket> CreateMockSyncWebSocket6( 104590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) std::list<std::string>* messages) { 104690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) return scoped_ptr<MockSyncWebSocket6>(new MockSyncWebSocket6(messages)) 104790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) .PassAs<SyncWebSocket>(); 104890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} 104990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 105090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} // namespace 105190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 1052868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)TEST_F(DevToolsClientImplTest, BlockedByAlert) { 105390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) std::list<std::string> msgs; 105490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) SyncWebSocketFactory factory = base::Bind(&CreateMockSyncWebSocket6, &msgs); 105590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) DevToolsClientImpl client( 105658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) factory, "http://url", "id", base::Bind(&CloserFunc)); 105790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) msgs.push_back( 105890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) "{\"method\": \"Page.javascriptDialogOpening\", \"params\": {}}"); 105990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) msgs.push_back("{\"id\": 2, \"result\": {}}"); 106090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) base::DictionaryValue params; 106190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) ASSERT_EQ(kUnexpectedAlertOpen, 106290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) client.SendCommand("first", params).code()); 106390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} 106490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 1065868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)TEST_F(DevToolsClientImplTest, CorrectlyDeterminesWhichIsBlockedByAlert) { 106690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // OUT | IN 106790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // FirstEvent 106890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // hello (id=1) 106990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // SecondEvent 107090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // hello (id=2) 107190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // ThirdEvent 107290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // hello (id=3) 107390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // FourthEvent 107490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // hello (id=4) 107590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // response for 1 107690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // alert 107790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // hello (id=5) 107890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // round trip command (id=6) 107990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // response for 2 108090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // response for 4 108190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // response for 5 108290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // response for 6 108390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) std::list<std::string> msgs; 108490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) SyncWebSocketFactory factory = base::Bind(&CreateMockSyncWebSocket6, &msgs); 108590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) DevToolsClientImpl client( 108658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) factory, "http://url", "id", base::Bind(&CloserFunc)); 108790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) MockDevToolsEventListener listener; 108890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) client.AddListener(&listener); 108990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) msgs.push_back("{\"method\": \"FirstEvent\", \"params\": {}}"); 109090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) msgs.push_back("{\"method\": \"SecondEvent\", \"params\": {}}"); 109190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) msgs.push_back("{\"method\": \"ThirdEvent\", \"params\": {}}"); 109290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) msgs.push_back("{\"method\": \"FourthEvent\", \"params\": {}}"); 109390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) msgs.push_back("{\"id\": 1, \"result\": {}}"); 109490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) msgs.push_back( 109590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) "{\"method\": \"Page.javascriptDialogOpening\", \"params\": {}}"); 109690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) msgs.push_back("{\"id\": 2, \"result\": {}}"); 109790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) msgs.push_back("{\"id\": 4, \"result\": {}}"); 109890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) msgs.push_back("{\"id\": 5, \"result\": {}}"); 109990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) msgs.push_back("{\"id\": 6, \"result\": {}}"); 110090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) ASSERT_EQ(kOk, client.HandleReceivedEvents().code()); 110190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} 110290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 110390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)namespace { 110490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 110590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)class MockCommandListener : public DevToolsEventListener { 110690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) public: 110790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) MockCommandListener() {} 110890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) virtual ~MockCommandListener() {} 110990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 1110868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) virtual Status OnEvent(DevToolsClient* client, 1111868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) const std::string& method, 1112868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) const base::DictionaryValue& params) OVERRIDE { 111390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) msgs_.push_back(method); 1114868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return Status(kOk); 111590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 111690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 111790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) virtual Status OnCommandSuccess(DevToolsClient* client, 111890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) const std::string& method) OVERRIDE { 111990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) msgs_.push_back(method); 112090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (!callback_.is_null()) 112190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) callback_.Run(client); 112290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) return Status(kOk); 112390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 112490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 112590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) base::Callback<void(DevToolsClient*)> callback_; 112690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) std::list<std::string> msgs_; 112790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}; 112890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 112990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void HandleReceivedEvents(DevToolsClient* client) { 113090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) EXPECT_EQ(kOk, client->HandleReceivedEvents().code()); 113190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} 113290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 113390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} // namespace 113490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 1135868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)TEST_F(DevToolsClientImplTest, ReceivesCommandResponse) { 113690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) std::list<std::string> msgs; 113790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) SyncWebSocketFactory factory = base::Bind(&CreateMockSyncWebSocket6, &msgs); 113890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) DevToolsClientImpl client( 113958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) factory, "http://url", "id", base::Bind(&CloserFunc)); 114090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) MockCommandListener listener1; 114190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) listener1.callback_ = base::Bind(&HandleReceivedEvents); 114290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) MockCommandListener listener2; 114390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) client.AddListener(&listener1); 114490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) client.AddListener(&listener2); 114590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) msgs.push_back("{\"id\": 1, \"result\": {}}"); 114690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) msgs.push_back("{\"method\": \"event\", \"params\": {}}"); 114790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) base::DictionaryValue params; 114890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) ASSERT_EQ(kOk, client.SendCommand("cmd", params).code()); 114990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) ASSERT_EQ(2u, listener2.msgs_.size()); 115090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) ASSERT_EQ("cmd", listener2.msgs_.front()); 115190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) ASSERT_EQ("event", listener2.msgs_.back()); 115290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} 1153