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