1 // Copyright (c) 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include <list>
6 #include <string>
7
8 #include "base/compiler_specific.h"
9 #include "base/memory/scoped_ptr.h"
10 #include "base/values.h"
11 #include "chrome/test/chromedriver/chrome/devtools_client.h"
12 #include "chrome/test/chromedriver/chrome/status.h"
13 #include "chrome/test/chromedriver/chrome/web_view_impl.h"
14 #include "testing/gtest/include/gtest/gtest.h"
15
16 namespace {
17
18 class FakeDevToolsClient : public DevToolsClient {
19 public:
FakeDevToolsClient()20 FakeDevToolsClient() : id_("fake-id"), status_(kOk) {}
~FakeDevToolsClient()21 virtual ~FakeDevToolsClient() {}
22
set_status(const Status & status)23 void set_status(const Status& status) {
24 status_ = status;
25 }
set_result(const base::DictionaryValue & result)26 void set_result(const base::DictionaryValue& result) {
27 result_.Clear();
28 result_.MergeDictionary(&result);
29 }
30
31 // Overridden from DevToolsClient:
GetId()32 virtual const std::string& GetId() OVERRIDE {
33 return id_;
34 }
WasCrashed()35 virtual bool WasCrashed() OVERRIDE {
36 return false;
37 }
ConnectIfNecessary()38 virtual Status ConnectIfNecessary() OVERRIDE {
39 return Status(kOk);
40 }
SendCommand(const std::string & method,const base::DictionaryValue & params)41 virtual Status SendCommand(const std::string& method,
42 const base::DictionaryValue& params) OVERRIDE {
43 return SendCommandAndGetResult(method, params, NULL);
44 }
SendCommandAndGetResult(const std::string & method,const base::DictionaryValue & params,scoped_ptr<base::DictionaryValue> * result)45 virtual Status SendCommandAndGetResult(
46 const std::string& method,
47 const base::DictionaryValue& params,
48 scoped_ptr<base::DictionaryValue>* result) OVERRIDE {
49 if (status_.IsError())
50 return status_;
51 result->reset(result_.DeepCopy());
52 return Status(kOk);
53 }
AddListener(DevToolsEventListener * listener)54 virtual void AddListener(DevToolsEventListener* listener) OVERRIDE {}
HandleEventsUntil(const ConditionalFunc & conditional_func,const base::TimeDelta & timeout)55 virtual Status HandleEventsUntil(
56 const ConditionalFunc& conditional_func,
57 const base::TimeDelta& timeout) OVERRIDE {
58 return Status(kOk);
59 }
HandleReceivedEvents()60 virtual Status HandleReceivedEvents() OVERRIDE {
61 return Status(kOk);
62 }
63
64 private:
65 const std::string id_;
66 Status status_;
67 base::DictionaryValue result_;
68 };
69
AssertEvalFails(const base::DictionaryValue & command_result)70 void AssertEvalFails(const base::DictionaryValue& command_result) {
71 scoped_ptr<base::DictionaryValue> result;
72 FakeDevToolsClient client;
73 client.set_result(command_result);
74 Status status = internal::EvaluateScript(
75 &client, 0, std::string(), internal::ReturnByValue, &result);
76 ASSERT_EQ(kUnknownError, status.code());
77 ASSERT_FALSE(result);
78 }
79
80 } // namespace
81
TEST(EvaluateScript,CommandError)82 TEST(EvaluateScript, CommandError) {
83 scoped_ptr<base::DictionaryValue> result;
84 FakeDevToolsClient client;
85 client.set_status(Status(kUnknownError));
86 Status status = internal::EvaluateScript(
87 &client, 0, std::string(), internal::ReturnByValue, &result);
88 ASSERT_EQ(kUnknownError, status.code());
89 ASSERT_FALSE(result);
90 }
91
TEST(EvaluateScript,MissingWasThrown)92 TEST(EvaluateScript, MissingWasThrown) {
93 base::DictionaryValue dict;
94 ASSERT_NO_FATAL_FAILURE(AssertEvalFails(dict));
95 }
96
TEST(EvaluateScript,MissingResult)97 TEST(EvaluateScript, MissingResult) {
98 base::DictionaryValue dict;
99 dict.SetBoolean("wasThrown", false);
100 ASSERT_NO_FATAL_FAILURE(AssertEvalFails(dict));
101 }
102
TEST(EvaluateScript,Throws)103 TEST(EvaluateScript, Throws) {
104 base::DictionaryValue dict;
105 dict.SetBoolean("wasThrown", true);
106 dict.SetString("result.type", "undefined");
107 ASSERT_NO_FATAL_FAILURE(AssertEvalFails(dict));
108 }
109
TEST(EvaluateScript,Ok)110 TEST(EvaluateScript, Ok) {
111 scoped_ptr<base::DictionaryValue> result;
112 base::DictionaryValue dict;
113 dict.SetBoolean("wasThrown", false);
114 dict.SetInteger("result.key", 100);
115 FakeDevToolsClient client;
116 client.set_result(dict);
117 ASSERT_TRUE(internal::EvaluateScript(
118 &client, 0, std::string(), internal::ReturnByValue, &result).IsOk());
119 ASSERT_TRUE(result);
120 ASSERT_TRUE(result->HasKey("key"));
121 }
122
TEST(EvaluateScriptAndGetValue,MissingType)123 TEST(EvaluateScriptAndGetValue, MissingType) {
124 scoped_ptr<base::Value> result;
125 FakeDevToolsClient client;
126 base::DictionaryValue dict;
127 dict.SetBoolean("wasThrown", false);
128 dict.SetInteger("result.value", 1);
129 client.set_result(dict);
130 ASSERT_TRUE(internal::EvaluateScriptAndGetValue(
131 &client, 0, std::string(), &result).IsError());
132 }
133
TEST(EvaluateScriptAndGetValue,Undefined)134 TEST(EvaluateScriptAndGetValue, Undefined) {
135 scoped_ptr<base::Value> result;
136 FakeDevToolsClient client;
137 base::DictionaryValue dict;
138 dict.SetBoolean("wasThrown", false);
139 dict.SetString("result.type", "undefined");
140 client.set_result(dict);
141 Status status =
142 internal::EvaluateScriptAndGetValue(&client, 0, std::string(), &result);
143 ASSERT_EQ(kOk, status.code());
144 ASSERT_TRUE(result && result->IsType(base::Value::TYPE_NULL));
145 }
146
TEST(EvaluateScriptAndGetValue,Ok)147 TEST(EvaluateScriptAndGetValue, Ok) {
148 scoped_ptr<base::Value> result;
149 FakeDevToolsClient client;
150 base::DictionaryValue dict;
151 dict.SetBoolean("wasThrown", false);
152 dict.SetString("result.type", "integer");
153 dict.SetInteger("result.value", 1);
154 client.set_result(dict);
155 Status status =
156 internal::EvaluateScriptAndGetValue(&client, 0, std::string(), &result);
157 ASSERT_EQ(kOk, status.code());
158 int value;
159 ASSERT_TRUE(result && result->GetAsInteger(&value));
160 ASSERT_EQ(1, value);
161 }
162
TEST(EvaluateScriptAndGetObject,NoObject)163 TEST(EvaluateScriptAndGetObject, NoObject) {
164 FakeDevToolsClient client;
165 base::DictionaryValue dict;
166 dict.SetBoolean("wasThrown", false);
167 dict.SetString("result.type", "integer");
168 client.set_result(dict);
169 bool got_object;
170 std::string object_id;
171 ASSERT_TRUE(internal::EvaluateScriptAndGetObject(
172 &client, 0, std::string(), &got_object, &object_id).IsOk());
173 ASSERT_FALSE(got_object);
174 ASSERT_TRUE(object_id.empty());
175 }
176
TEST(EvaluateScriptAndGetObject,Ok)177 TEST(EvaluateScriptAndGetObject, Ok) {
178 FakeDevToolsClient client;
179 base::DictionaryValue dict;
180 dict.SetBoolean("wasThrown", false);
181 dict.SetString("result.objectId", "id");
182 client.set_result(dict);
183 bool got_object;
184 std::string object_id;
185 ASSERT_TRUE(internal::EvaluateScriptAndGetObject(
186 &client, 0, std::string(), &got_object, &object_id).IsOk());
187 ASSERT_TRUE(got_object);
188 ASSERT_STREQ("id", object_id.c_str());
189 }
190
TEST(ParseCallFunctionResult,NotDict)191 TEST(ParseCallFunctionResult, NotDict) {
192 scoped_ptr<base::Value> result;
193 base::FundamentalValue value(1);
194 ASSERT_NE(kOk, internal::ParseCallFunctionResult(value, &result).code());
195 }
196
TEST(ParseCallFunctionResult,Ok)197 TEST(ParseCallFunctionResult, Ok) {
198 scoped_ptr<base::Value> result;
199 base::DictionaryValue dict;
200 dict.SetInteger("status", 0);
201 dict.SetInteger("value", 1);
202 Status status = internal::ParseCallFunctionResult(dict, &result);
203 ASSERT_EQ(kOk, status.code());
204 int value;
205 ASSERT_TRUE(result && result->GetAsInteger(&value));
206 ASSERT_EQ(1, value);
207 }
208
TEST(ParseCallFunctionResult,ScriptError)209 TEST(ParseCallFunctionResult, ScriptError) {
210 scoped_ptr<base::Value> result;
211 base::DictionaryValue dict;
212 dict.SetInteger("status", 1);
213 dict.SetInteger("value", 1);
214 Status status = internal::ParseCallFunctionResult(dict, &result);
215 ASSERT_EQ(1, status.code());
216 ASSERT_FALSE(result);
217 }
218