libweave: Update unittests to work with HttpClient
http::Transport is being replaced with HttpClient.
BUG=brillo:1250
TEST='FEATURES=test emerge-gizmo libweave buffet'
Change-Id: Id9dfc68cf40fb61ea7cc2778661797b566172faa
diff --git a/libweave/include/weave/mock_http_client.h b/libweave/include/weave/mock_http_client.h
new file mode 100644
index 0000000..015ed0b
--- /dev/null
+++ b/libweave/include/weave/mock_http_client.h
@@ -0,0 +1,57 @@
+// Copyright 2015 The Chromium OS Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef LIBWEAVE_INCLUDE_WEAVE_MOCK_HTTP_CLIENT_H_
+#define LIBWEAVE_INCLUDE_WEAVE_MOCK_HTTP_CLIENT_H_
+
+#include <weave/http_client.h>
+
+#include <memory>
+#include <string>
+
+#include <gmock/gmock.h>
+
+namespace weave {
+namespace unittests {
+
+class MockHttpClientResponse : public HttpClient::Response {
+ public:
+ MOCK_CONST_METHOD0(GetStatusCode, int());
+ MOCK_CONST_METHOD0(GetContentType, std::string());
+ MOCK_CONST_METHOD0(GetData, const std::string&());
+};
+
+class MockHttpClient : public HttpClient {
+ public:
+ ~MockHttpClient() override = default;
+
+ MOCK_METHOD6(MockSendRequest,
+ Response*(const std::string&,
+ const std::string&,
+ const std::string&,
+ const std::string&,
+ const Headers&,
+ chromeos::ErrorPtr*));
+
+ std::unique_ptr<Response> SendRequestAndBlock(
+ const std::string& method,
+ const std::string& url,
+ const std::string& data,
+ const std::string& mime_type,
+ const Headers& headers,
+ chromeos::ErrorPtr* error) override;
+
+ int SendRequest(const std::string& method,
+ const std::string& url,
+ const std::string& data,
+ const std::string& mime_type,
+ const Headers& headers,
+ const SuccessCallback& success_callback,
+ const ErrorCallback& error_callback) override;
+};
+
+} // namespace unittests
+} // namespace weave
+
+#endif // LIBWEAVE_INCLUDE_WEAVE_MOCK_HTTP_CLIENT_H_
diff --git a/libweave/libweave.gyp b/libweave/libweave.gyp
index 9a1f2b6..be4d1d7 100644
--- a/libweave/libweave.gyp
+++ b/libweave/libweave.gyp
@@ -81,6 +81,7 @@
'sources': [
'src/commands/mock_command.cc',
'src/commands/unittest_utils.cc',
+ 'src/mock_http_client.cc',
],
'includes': ['../common-mk/deps.gypi'],
},
diff --git a/libweave/src/base_api_handler_unittest.cc b/libweave/src/base_api_handler_unittest.cc
index 685aa55..548d0c1 100644
--- a/libweave/src/base_api_handler_unittest.cc
+++ b/libweave/src/base_api_handler_unittest.cc
@@ -6,8 +6,8 @@
#include <base/strings/string_number_conversions.h>
#include <base/values.h>
-#include <chromeos/http/http_transport_fake.h>
#include <gtest/gtest.h>
+#include <weave/mock_http_client.h>
#include "libweave/src/buffet_config.h"
#include "libweave/src/commands/command_manager.h"
@@ -59,7 +59,7 @@
command_manager_, state_manager_,
std::unique_ptr<BuffetConfig>{new BuffetConfig{
std::unique_ptr<StorageInterface>{new MemStorage}}},
- transport_, nullptr, true, nullptr));
+ &http_client_, nullptr, true, nullptr));
handler_.reset(
new BaseApiHandler{dev_reg_.get(), state_manager_, command_manager_});
}
@@ -84,7 +84,7 @@
command_manager_->FindCommand(id)->GetStatus());
}
- std::shared_ptr<chromeos::http::fake::Transport> transport_;
+ StrictMock<unittests::MockHttpClient> http_client_;
std::unique_ptr<DeviceRegistrationInfo> dev_reg_;
std::shared_ptr<CommandManager> command_manager_;
testing::StrictMock<MockStateChangeQueueInterface> mock_state_change_queue_;
diff --git a/libweave/src/device_manager.cc b/libweave/src/device_manager.cc
index 0b8bf88..344c725 100644
--- a/libweave/src/device_manager.cc
+++ b/libweave/src/device_manager.cc
@@ -13,6 +13,7 @@
#include "libweave/src/buffet_config.h"
#include "libweave/src/commands/command_manager.h"
#include "libweave/src/device_registration_info.h"
+#include "libweave/src/http_transport_client.h"
#include "libweave/src/privet/privet_manager.h"
#include "libweave/src/states/state_change_queue.h"
#include "libweave/src/states/state_manager.h"
@@ -50,10 +51,11 @@
std::unique_ptr<BuffetConfig> config{new BuffetConfig{options.state_path}};
config->Load(options.config_path);
+ http_client_.reset(new buffet::HttpTransportClient{transport});
// TODO(avakulenko): Figure out security implications of storing
// device info state data unencrypted.
device_info_.reset(new DeviceRegistrationInfo(
- command_manager_, state_manager_, std::move(config), transport,
+ command_manager_, state_manager_, std::move(config), http_client_.get(),
base::MessageLoop::current()->task_runner(), options.xmpp_enabled,
network));
base_api_handler_.reset(
diff --git a/libweave/src/device_manager.h b/libweave/src/device_manager.h
index 2474281..2e65ffe 100644
--- a/libweave/src/device_manager.h
+++ b/libweave/src/device_manager.h
@@ -8,6 +8,10 @@
#include <base/memory/weak_ptr.h>
#include <weave/device.h>
+namespace buffet {
+class HttpTransportClient;
+} // namespace buffet
+
namespace weave {
class BaseApiHandler;
@@ -45,6 +49,8 @@
void OnWiFiBootstrapStateChanged(weave::WifiSetupState state);
+ // TODO(vitalybuka): Move to buffet.
+ std::unique_ptr<buffet::HttpTransportClient> http_client_;
std::shared_ptr<CommandManager> command_manager_;
std::unique_ptr<StateChangeQueue> state_change_queue_;
std::shared_ptr<StateManager> state_manager_;
diff --git a/libweave/src/device_registration_info.cc b/libweave/src/device_registration_info.cc
index 948b485..bcebaba 100644
--- a/libweave/src/device_registration_info.cc
+++ b/libweave/src/device_registration_info.cc
@@ -29,7 +29,6 @@
#include "libweave/src/commands/command_definition.h"
#include "libweave/src/commands/command_manager.h"
#include "libweave/src/commands/schema_constants.h"
-#include "libweave/src/http_transport_client.h"
#include "libweave/src/notification/xmpp_channel.h"
#include "libweave/src/states/state_manager.h"
#include "libweave/src/utils.h"
@@ -223,12 +222,11 @@
const std::shared_ptr<CommandManager>& command_manager,
const std::shared_ptr<StateManager>& state_manager,
std::unique_ptr<BuffetConfig> config,
- const std::shared_ptr<chromeos::http::Transport>& transport,
+ HttpClient* http_client,
const scoped_refptr<base::SingleThreadTaskRunner>& task_runner,
bool notifications_enabled,
Network* network)
- : http_client_owner_{new buffet::HttpTransportClient{transport}},
- http_client_{http_client_owner_.get()},
+ : http_client_{http_client},
task_runner_{task_runner},
command_manager_{command_manager},
state_manager_{state_manager},
diff --git a/libweave/src/device_registration_info.h b/libweave/src/device_registration_info.h
index dccb6dd..3c8dff3 100644
--- a/libweave/src/device_registration_info.h
+++ b/libweave/src/device_registration_info.h
@@ -43,10 +43,6 @@
class KeyValueStore;
} // namespace chromeos
-namespace buffet {
-class HttpTransportClient;
-} // namespace buffet
-
namespace weave {
class Network;
@@ -70,7 +66,7 @@
const std::shared_ptr<CommandManager>& command_manager,
const std::shared_ptr<StateManager>& state_manager,
std::unique_ptr<BuffetConfig> config,
- const std::shared_ptr<chromeos::http::Transport>& transport,
+ HttpClient* http_client,
const scoped_refptr<base::SingleThreadTaskRunner>& task_runner,
bool notifications_enabled,
weave::Network* network);
@@ -305,9 +301,7 @@
bool connected_to_cloud_{false};
// HTTP transport used for communications.
- // TODO(vitalybuka): Move to buffet.
- std::unique_ptr<buffet::HttpTransportClient> http_client_owner_;
- HttpClient* http_client_;
+ HttpClient* http_client_{nullptr};
scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
// Global command manager.
diff --git a/libweave/src/device_registration_info_unittest.cc b/libweave/src/device_registration_info_unittest.cc
index 7d204bd..d76d9eb 100644
--- a/libweave/src/device_registration_info_unittest.cc
+++ b/libweave/src/device_registration_info_unittest.cc
@@ -10,11 +10,10 @@
#include <base/run_loop.h>
#include <base/values.h>
#include <chromeos/bind_lambda.h>
-#include <chromeos/http/http_request.h>
-#include <chromeos/http/http_transport_fake.h>
#include <chromeos/key_value_store.h>
#include <chromeos/mime_utils.h>
#include <gtest/gtest.h>
+#include <weave/mock_http_client.h>
#include "libweave/src/commands/command_manager.h"
#include "libweave/src/commands/unittest_utils.h"
@@ -23,15 +22,22 @@
#include "libweave/src/storage_impls.h"
using testing::_;
+using testing::AtLeast;
+using testing::Invoke;
+using testing::InvokeWithoutArgs;
+using testing::Mock;
using testing::Return;
+using testing::ReturnRef;
+using testing::ReturnRefOfCopy;
using testing::StrictMock;
+using testing::WithArgs;
namespace weave {
-using chromeos::http::fake::ServerRequest;
-using chromeos::http::fake::ServerResponse;
-using chromeos::http::request_header::kAuthorization;
using unittests::CreateDictionaryValue;
+using unittests::CreateValue;
+using unittests::MockHttpClient;
+using unittests::MockHttpClientResponse;
namespace {
@@ -59,16 +65,7 @@
const char kRobotAccountEmail[] =
"6ed0b3f54f9bd619b942f4ad2441c252@"
"clouddevices.gserviceaccount.com";
-const char kUserAccountAuthCode[] =
- "2/sd_GD1TGFKpJOLJ34-0g5fK0fflp.GlT"
- "I0F5g7hNtFgj5HFGOf8FlGK9eflO";
-const char kUserAccessToken[] =
- "sd56.4.FGDjG_F-gFGF-dFG6gGOG9Dxm5NgdS9"
- "JMx_JLUqhC9bED_YFjLKjlkjLKJlkjLKjlKJea"
- "VZDei530-w0yE2urpQ";
-const char kUserRefreshToken[] =
- "1/zQLKjlKJlkLkLKjLkjLKjLkjLjLkjl0ftc6"
- "cp1nI-GQ";
+
} // namespace test_data
// Add the test device registration information.
@@ -78,101 +75,36 @@
data->SetString("robot_account", test_data::kRobotAccountEmail);
}
-void OAuth2Handler(const ServerRequest& request, ServerResponse* response) {
- base::DictionaryValue json;
- if (request.GetFormField("grant_type") == "refresh_token") {
- // Refresh device access token.
- EXPECT_EQ(test_data::kRefreshToken, request.GetFormField("refresh_token"));
- EXPECT_EQ(test_data::kClientId, request.GetFormField("client_id"));
- EXPECT_EQ(test_data::kClientSecret, request.GetFormField("client_secret"));
- json.SetString("access_token", test_data::kAccessToken);
- } else if (request.GetFormField("grant_type") == "authorization_code") {
- // Obtain access token.
- std::string code = request.GetFormField("code");
- if (code == test_data::kUserAccountAuthCode) {
- // Get user access token.
- EXPECT_EQ(test_data::kClientId, request.GetFormField("client_id"));
- EXPECT_EQ(test_data::kClientSecret,
- request.GetFormField("client_secret"));
- EXPECT_EQ("urn:ietf:wg:oauth:2.0:oob",
- request.GetFormField("redirect_uri"));
- json.SetString("access_token", test_data::kUserAccessToken);
- json.SetString("token_type", "Bearer");
- json.SetString("refresh_token", test_data::kUserRefreshToken);
- } else if (code == test_data::kRobotAccountAuthCode) {
- // Get device access token.
- EXPECT_EQ(test_data::kClientId, request.GetFormField("client_id"));
- EXPECT_EQ(test_data::kClientSecret,
- request.GetFormField("client_secret"));
- EXPECT_EQ("oob", request.GetFormField("redirect_uri"));
- EXPECT_EQ("https://www.googleapis.com/auth/clouddevices",
- request.GetFormField("scope"));
- json.SetString("access_token", test_data::kAccessToken);
- json.SetString("token_type", "Bearer");
- json.SetString("refresh_token", test_data::kRefreshToken);
- } else {
- FAIL() << "Unexpected authorization code";
- }
- } else {
- FAIL() << "Unexpected grant type";
+std::string GetFormField(const std::string& data, const std::string& name) {
+ EXPECT_FALSE(data.empty());
+ for (const auto& i : chromeos::data_encoding::WebParamsDecode(data)) {
+ if (i.first == name)
+ return i.second;
}
- json.SetInteger("expires_in", 3600);
- response->ReplyJson(chromeos::http::status_code::Ok, &json);
+ return {};
}
-void OAuth2HandlerFail(const ServerRequest& request, ServerResponse* response) {
- base::DictionaryValue json;
- EXPECT_EQ("refresh_token", request.GetFormField("grant_type"));
- EXPECT_EQ(test_data::kRefreshToken, request.GetFormField("refresh_token"));
- EXPECT_EQ(test_data::kClientId, request.GetFormField("client_id"));
- EXPECT_EQ(test_data::kClientSecret, request.GetFormField("client_secret"));
- json.SetString("error", "unable_to_authenticate");
- response->ReplyJson(chromeos::http::status_code::BadRequest, &json);
+HttpClient::Response* ReplyWithJson(int status_code, const base::Value& json) {
+ std::string text;
+ base::JSONWriter::WriteWithOptions(
+ json, base::JSONWriter::OPTIONS_PRETTY_PRINT, &text);
+
+ MockHttpClientResponse* response = new StrictMock<MockHttpClientResponse>;
+ EXPECT_CALL(*response, GetStatusCode())
+ .Times(AtLeast(1))
+ .WillRepeatedly(Return(status_code));
+ EXPECT_CALL(*response, GetContentType())
+ .Times(AtLeast(1))
+ .WillRepeatedly(Return("application/json"));
+ EXPECT_CALL(*response, GetData())
+ .Times(AtLeast(1))
+ .WillRepeatedly(ReturnRefOfCopy(text));
+ return response;
}
-void OAuth2HandlerDeregister(const ServerRequest& request,
- ServerResponse* response) {
- base::DictionaryValue json;
- EXPECT_EQ("refresh_token", request.GetFormField("grant_type"));
- EXPECT_EQ(test_data::kRefreshToken, request.GetFormField("refresh_token"));
- EXPECT_EQ(test_data::kClientId, request.GetFormField("client_id"));
- EXPECT_EQ(test_data::kClientSecret, request.GetFormField("client_secret"));
- json.SetString("error", "invalid_grant");
- response->ReplyJson(chromeos::http::status_code::BadRequest, &json);
-}
-
-void DeviceInfoHandler(const ServerRequest& request, ServerResponse* response) {
- std::string auth = "Bearer ";
- auth += test_data::kAccessToken;
- EXPECT_EQ(auth,
- request.GetHeader(chromeos::http::request_header::kAuthorization));
- response->ReplyJson(chromeos::http::status_code::Ok,
- {
- {"channel.supportedType", "xmpp"},
- {"deviceKind", "vendor"},
- {"id", test_data::kDeviceId},
- {"kind", "clouddevices#device"},
- });
-}
-
-void FinalizeTicketHandler(const ServerRequest& request,
- ServerResponse* response) {
- EXPECT_EQ(test_data::kApiKey, request.GetFormField("key"));
- EXPECT_TRUE(request.GetData().empty());
-
- response->ReplyJson(
- chromeos::http::status_code::Ok,
- {
- {"id", test_data::kClaimTicketId},
- {"kind", "clouddevices#registrationTicket"},
- {"oauthClientId", test_data::kClientId},
- {"userEmail", "user@email.com"},
- {"deviceDraft.id", test_data::kDeviceId},
- {"deviceDraft.kind", "clouddevices#device"},
- {"deviceDraft.channel.supportedType", "xmpp"},
- {"robotAccountEmail", test_data::kRobotAccountEmail},
- {"robotAccountAuthorizationCode", test_data::kRobotAccountAuthCode},
- });
+std::pair<std::string, std::string> GetAuthHeader() {
+ return {std::string{"Authorization"},
+ std::string{"Bearer "} + test_data::kAccessToken};
}
} // anonymous namespace
@@ -188,19 +120,14 @@
std::unique_ptr<StorageInterface> storage{new MemStorage};
storage_ = storage.get();
storage->Save(data_);
- transport_ = std::make_shared<chromeos::http::fake::Transport>();
command_manager_ = std::make_shared<CommandManager>();
state_manager_ = std::make_shared<StateManager>(&mock_state_change_queue_);
std::unique_ptr<BuffetConfig> config{new BuffetConfig{std::move(storage)}};
config_ = config.get();
- dev_reg_.reset(new DeviceRegistrationInfo{command_manager_,
- state_manager_,
- std::move(config),
- transport_,
- nullptr,
- true,
- nullptr});
+ dev_reg_.reset(new DeviceRegistrationInfo{command_manager_, state_manager_,
+ std::move(config), &http_client_,
+ nullptr, true, nullptr});
ReloadConfig();
}
@@ -252,10 +179,10 @@
return dev_reg_->registration_status_;
}
+ StrictMock<MockHttpClient> http_client_;
base::DictionaryValue data_;
StorageInterface* storage_{nullptr};
BuffetConfig* config_{nullptr};
- std::shared_ptr<chromeos::http::fake::Transport> transport_;
std::unique_ptr<DeviceRegistrationInfo> dev_reg_;
std::shared_ptr<CommandManager> command_manager_;
StrictMock<MockStateChangeQueueInterface> mock_state_change_queue_;
@@ -298,18 +225,30 @@
TEST_F(DeviceRegistrationInfoTest, HaveRegistrationCredentials) {
EXPECT_FALSE(dev_reg_->HaveRegistrationCredentials());
- EXPECT_EQ(0, transport_->GetRequestCount());
-
SetDefaultDeviceRegistration(&data_);
storage_->Save(data_);
ReloadConfig();
- transport_->AddHandler(dev_reg_->GetOAuthURL("token"),
- chromeos::http::request_type::kPost,
- base::Bind(OAuth2Handler));
- transport_->ResetRequestCount();
+ EXPECT_CALL(http_client_,
+ MockSendRequest("POST", dev_reg_->GetOAuthURL("token"), _,
+ "application/x-www-form-urlencoded",
+ HttpClient::Headers{}, _))
+ .WillOnce(WithArgs<2>(Invoke([](const std::string& data) {
+ EXPECT_EQ("refresh_token", GetFormField(data, "grant_type"));
+ EXPECT_EQ(test_data::kRefreshToken,
+ GetFormField(data, "refresh_token"));
+ EXPECT_EQ(test_data::kClientId, GetFormField(data, "client_id"));
+ EXPECT_EQ(test_data::kClientSecret,
+ GetFormField(data, "client_secret"));
+
+ base::DictionaryValue json;
+ json.SetString("access_token", test_data::kAccessToken);
+ json.SetInteger("expires_in", 3600);
+
+ return ReplyWithJson(200, json);
+ })));
+
EXPECT_TRUE(RefreshAccessToken(nullptr));
- EXPECT_EQ(1, transport_->GetRequestCount());
EXPECT_TRUE(dev_reg_->HaveRegistrationCredentials());
}
@@ -319,13 +258,25 @@
ReloadConfig();
EXPECT_EQ(RegistrationStatus::kConnecting, GetRegistrationStatus());
- transport_->AddHandler(dev_reg_->GetOAuthURL("token"),
- chromeos::http::request_type::kPost,
- base::Bind(OAuth2HandlerFail));
- transport_->ResetRequestCount();
+ EXPECT_CALL(http_client_,
+ MockSendRequest("POST", dev_reg_->GetOAuthURL("token"), _,
+ "application/x-www-form-urlencoded",
+ HttpClient::Headers{}, _))
+ .WillOnce(WithArgs<2>(Invoke([](const std::string& data) {
+ EXPECT_EQ("refresh_token", GetFormField(data, "grant_type"));
+ EXPECT_EQ(test_data::kRefreshToken,
+ GetFormField(data, "refresh_token"));
+ EXPECT_EQ(test_data::kClientId, GetFormField(data, "client_id"));
+ EXPECT_EQ(test_data::kClientSecret,
+ GetFormField(data, "client_secret"));
+
+ base::DictionaryValue json;
+ json.SetString("error", "unable_to_authenticate");
+ return ReplyWithJson(400, json);
+ })));
+
chromeos::ErrorPtr error;
EXPECT_FALSE(RefreshAccessToken(&error));
- EXPECT_EQ(1, transport_->GetRequestCount());
EXPECT_TRUE(error->HasError(kErrorDomainOAuth2, "unable_to_authenticate"));
EXPECT_EQ(RegistrationStatus::kConnecting, GetRegistrationStatus());
}
@@ -336,13 +287,25 @@
ReloadConfig();
EXPECT_EQ(RegistrationStatus::kConnecting, GetRegistrationStatus());
- transport_->AddHandler(dev_reg_->GetOAuthURL("token"),
- chromeos::http::request_type::kPost,
- base::Bind(OAuth2HandlerDeregister));
- transport_->ResetRequestCount();
+ EXPECT_CALL(http_client_,
+ MockSendRequest("POST", dev_reg_->GetOAuthURL("token"), _,
+ "application/x-www-form-urlencoded",
+ HttpClient::Headers{}, _))
+ .WillOnce(WithArgs<2>(Invoke([](const std::string& data) {
+ EXPECT_EQ("refresh_token", GetFormField(data, "grant_type"));
+ EXPECT_EQ(test_data::kRefreshToken,
+ GetFormField(data, "refresh_token"));
+ EXPECT_EQ(test_data::kClientId, GetFormField(data, "client_id"));
+ EXPECT_EQ(test_data::kClientSecret,
+ GetFormField(data, "client_secret"));
+
+ base::DictionaryValue json;
+ json.SetString("error", "invalid_grant");
+ return ReplyWithJson(400, json);
+ })));
+
chromeos::ErrorPtr error;
EXPECT_FALSE(RefreshAccessToken(&error));
- EXPECT_EQ(1, transport_->GetRequestCount());
EXPECT_TRUE(error->HasError(kErrorDomainOAuth2, "invalid_grant"));
EXPECT_EQ(RegistrationStatus::kInvalidCredentials, GetRegistrationStatus());
}
@@ -353,17 +316,25 @@
ReloadConfig();
SetAccessToken();
- transport_->AddHandler(dev_reg_->GetDeviceURL(),
- chromeos::http::request_type::kGet,
- base::Bind(DeviceInfoHandler));
- transport_->ResetRequestCount();
+ EXPECT_CALL(http_client_,
+ MockSendRequest("GET", dev_reg_->GetDeviceURL(), _,
+ "application/json; charset=utf-8",
+ HttpClient::Headers{GetAuthHeader()}, _))
+ .WillOnce(WithArgs<2>(Invoke([](const std::string& data) {
+ base::DictionaryValue json;
+ json.SetString("channel.supportedType", "xmpp");
+ json.SetString("deviceKind", "vendor");
+ json.SetString("id", test_data::kDeviceId);
+ json.SetString("kind", "clouddevices#device");
+ return ReplyWithJson(200, json);
+ })));
+
base::MessageLoopForIO message_loop;
base::RunLoop run_loop;
bool succeeded = false;
- auto on_success = [&run_loop, &succeeded, this](
- const base::DictionaryValue& info) {
- EXPECT_EQ(1, transport_->GetRequestCount());
+ auto on_success = [&run_loop, &succeeded,
+ this](const base::DictionaryValue& info) {
std::string id;
EXPECT_TRUE(info.GetString("id", &id));
EXPECT_EQ(test_data::kDeviceId, id);
@@ -380,72 +351,7 @@
}
TEST_F(DeviceRegistrationInfoTest, RegisterDevice) {
- auto update_ticket = [](const ServerRequest& request,
- ServerResponse* response) {
- EXPECT_EQ(test_data::kApiKey, request.GetFormField("key"));
- auto json = request.GetDataAsJson();
- EXPECT_NE(nullptr, json.get());
- std::string value;
- EXPECT_TRUE(json->GetString("id", &value));
- EXPECT_EQ(test_data::kClaimTicketId, value);
- EXPECT_TRUE(json->GetString("deviceDraft.channel.supportedType", &value));
- EXPECT_EQ("pull", value);
- EXPECT_TRUE(json->GetString("oauthClientId", &value));
- EXPECT_EQ(test_data::kClientId, value);
- EXPECT_TRUE(json->GetString("deviceDraft.deviceKind", &value));
- EXPECT_EQ("vendor", value);
- EXPECT_TRUE(json->GetString("deviceDraft.description", &value));
- EXPECT_EQ("Easy to clean", value);
- EXPECT_TRUE(json->GetString("deviceDraft.location", &value));
- EXPECT_EQ("Kitchen", value);
- EXPECT_TRUE(json->GetString("deviceDraft.modelManifestId", &value));
- EXPECT_EQ("AAAAA", value);
- EXPECT_TRUE(json->GetString("deviceDraft.name", &value));
- EXPECT_EQ("Coffee Pot", value);
- base::DictionaryValue* commandDefs = nullptr;
- EXPECT_TRUE(json->GetDictionary("deviceDraft.commandDefs", &commandDefs));
- EXPECT_FALSE(commandDefs->empty());
-
- auto expected = R"({
- 'base': {
- 'reboot': {
- 'parameters': {
- 'delay': {
- 'minimum': 10,
- 'type': 'integer'
- }
- },
- 'minimalRole': 'user'
- }
- },
- 'robot': {
- '_jump': {
- 'parameters': {
- '_height': {
- 'type': 'integer'
- }
- },
- 'minimalRole': 'user'
- }
- }
- })";
- EXPECT_JSON_EQ(expected, *commandDefs);
-
- base::DictionaryValue json_resp;
- json_resp.SetString("id", test_data::kClaimTicketId);
- json_resp.SetString("kind", "clouddevices#registrationTicket");
- json_resp.SetString("oauthClientId", test_data::kClientId);
- base::DictionaryValue* device_draft = nullptr;
- EXPECT_TRUE(json->GetDictionary("deviceDraft", &device_draft));
- device_draft = device_draft->DeepCopy();
- device_draft->SetString("id", test_data::kDeviceId);
- device_draft->SetString("kind", "clouddevices#device");
- json_resp.Set("deviceDraft", device_draft);
-
- response->ReplyJson(chromeos::http::status_code::Ok, &json_resp);
- };
-
- auto json_base = unittests::CreateDictionaryValue(R"({
+ auto json_base = CreateDictionaryValue(R"({
'base': {
'reboot': {
'parameters': {'delay': 'integer'},
@@ -460,7 +366,7 @@
}
})");
EXPECT_TRUE(command_manager_->LoadBaseCommands(*json_base, nullptr));
- auto json_cmds = unittests::CreateDictionaryValue(R"({
+ auto json_cmds = CreateDictionaryValue(R"({
'base': {
'reboot': {
'parameters': {'delay': {'minimum': 10}},
@@ -478,24 +384,124 @@
})");
EXPECT_TRUE(command_manager_->LoadCommands(*json_cmds, "", nullptr));
- transport_->AddHandler(
- dev_reg_->GetServiceURL(std::string("registrationTickets/") +
- test_data::kClaimTicketId),
- chromeos::http::request_type::kPatch, base::Bind(update_ticket));
- std::string ticket_url = dev_reg_->GetServiceURL(
- "registrationTickets/" + std::string(test_data::kClaimTicketId));
- transport_->AddHandler(ticket_url + "/finalize",
- chromeos::http::request_type::kPost,
- base::Bind(FinalizeTicketHandler));
+ std::string ticket_url = dev_reg_->GetServiceURL("registrationTickets/") +
+ test_data::kClaimTicketId;
+ EXPECT_CALL(http_client_,
+ MockSendRequest(
+ "PATCH", ticket_url + "?key=" + test_data::kApiKey, _,
+ "application/json; charset=utf-8", HttpClient::Headers{}, _))
+ .WillOnce(WithArgs<2>(Invoke([](const std::string& data) {
+ auto json = unittests::CreateDictionaryValue(data);
+ EXPECT_NE(nullptr, json.get());
+ std::string value;
+ EXPECT_TRUE(json->GetString("id", &value));
+ EXPECT_EQ(test_data::kClaimTicketId, value);
+ EXPECT_TRUE(
+ json->GetString("deviceDraft.channel.supportedType", &value));
+ EXPECT_EQ("pull", value);
+ EXPECT_TRUE(json->GetString("oauthClientId", &value));
+ EXPECT_EQ(test_data::kClientId, value);
+ EXPECT_TRUE(json->GetString("deviceDraft.deviceKind", &value));
+ EXPECT_EQ("vendor", value);
+ EXPECT_TRUE(json->GetString("deviceDraft.description", &value));
+ EXPECT_EQ("Easy to clean", value);
+ EXPECT_TRUE(json->GetString("deviceDraft.location", &value));
+ EXPECT_EQ("Kitchen", value);
+ EXPECT_TRUE(json->GetString("deviceDraft.modelManifestId", &value));
+ EXPECT_EQ("AAAAA", value);
+ EXPECT_TRUE(json->GetString("deviceDraft.name", &value));
+ EXPECT_EQ("Coffee Pot", value);
+ base::DictionaryValue* commandDefs = nullptr;
+ EXPECT_TRUE(
+ json->GetDictionary("deviceDraft.commandDefs", &commandDefs));
+ EXPECT_FALSE(commandDefs->empty());
- transport_->AddHandler(dev_reg_->GetOAuthURL("token"),
- chromeos::http::request_type::kPost,
- base::Bind(OAuth2Handler));
+ auto expected = R"({
+ 'base': {
+ 'reboot': {
+ 'parameters': {
+ 'delay': {
+ 'minimum': 10,
+ 'type': 'integer'
+ }
+ },
+ 'minimalRole': 'user'
+ }
+ },
+ 'robot': {
+ '_jump': {
+ 'parameters': {
+ '_height': {
+ 'type': 'integer'
+ }
+ },
+ 'minimalRole': 'user'
+ }
+ }
+ })";
+ EXPECT_JSON_EQ(expected, *commandDefs);
+
+ base::DictionaryValue json_resp;
+ json_resp.SetString("id", test_data::kClaimTicketId);
+ json_resp.SetString("kind", "clouddevices#registrationTicket");
+ json_resp.SetString("oauthClientId", test_data::kClientId);
+ base::DictionaryValue* device_draft = nullptr;
+ EXPECT_TRUE(json->GetDictionary("deviceDraft", &device_draft));
+ device_draft = device_draft->DeepCopy();
+ device_draft->SetString("id", test_data::kDeviceId);
+ device_draft->SetString("kind", "clouddevices#device");
+ json_resp.Set("deviceDraft", device_draft);
+
+ return ReplyWithJson(200, json_resp);
+ })));
+
+ EXPECT_CALL(http_client_,
+ MockSendRequest(
+ "POST", ticket_url + "/finalize?key=" + test_data::kApiKey,
+ "", _, HttpClient::Headers{}, _))
+ .WillOnce(InvokeWithoutArgs([]() {
+ base::DictionaryValue json;
+ json.SetString("id", test_data::kClaimTicketId);
+ json.SetString("kind", "clouddevices#registrationTicket");
+ json.SetString("oauthClientId", test_data::kClientId);
+ json.SetString("userEmail", "user@email.com");
+ json.SetString("deviceDraft.id", test_data::kDeviceId);
+ json.SetString("deviceDraft.kind", "clouddevices#device");
+ json.SetString("deviceDraft.channel.supportedType", "xmpp");
+ json.SetString("robotAccountEmail", test_data::kRobotAccountEmail);
+ json.SetString("robotAccountAuthorizationCode",
+ test_data::kRobotAccountAuthCode);
+ return ReplyWithJson(200, json);
+ }));
+
+ EXPECT_CALL(http_client_,
+ MockSendRequest("POST", dev_reg_->GetOAuthURL("token"), _,
+ "application/x-www-form-urlencoded",
+ HttpClient::Headers{}, _))
+ .WillOnce(WithArgs<2>(Invoke([](const std::string& data) {
+ EXPECT_EQ("authorization_code", GetFormField(data, "grant_type"));
+ EXPECT_EQ(test_data::kRobotAccountAuthCode, GetFormField(data, "code"));
+ EXPECT_EQ(test_data::kClientId, GetFormField(data, "client_id"));
+ EXPECT_EQ(test_data::kClientSecret,
+ GetFormField(data, "client_secret"));
+
+ EXPECT_EQ("oob", GetFormField(data, "redirect_uri"));
+ EXPECT_EQ("https://www.googleapis.com/auth/clouddevices",
+ GetFormField(data, "scope"));
+
+ base::DictionaryValue json;
+ json.SetString("access_token", test_data::kAccessToken);
+ json.SetString("token_type", "Bearer");
+ json.SetString("refresh_token", test_data::kRefreshToken);
+ json.SetInteger("expires_in", 3600);
+
+ return ReplyWithJson(200, json);
+ })));
+
std::string device_id =
dev_reg_->RegisterDevice(test_data::kClaimTicketId, nullptr);
EXPECT_EQ(test_data::kDeviceId, device_id);
- EXPECT_EQ(3, transport_->GetRequestCount());
EXPECT_EQ(RegistrationStatus::kConnecting, GetRegistrationStatus());
// Validate the device info saved to storage...
@@ -512,8 +518,8 @@
}
TEST_F(DeviceRegistrationInfoTest, OOBRegistrationStatus) {
- // After we've been initialized, we should be either offline or unregistered,
- // depending on whether or not we've found credentials.
+ // After we've been initialized, we should be either offline or
+ // unregistered, depending on whether or not we've found credentials.
EXPECT_EQ(RegistrationStatus::kUnconfigured, GetRegistrationStatus());
// Put some credentials into our state, make sure we call that offline.
SetDefaultDeviceRegistration(&data_);
@@ -528,7 +534,7 @@
ReloadConfig();
SetAccessToken();
- auto json_cmds = unittests::CreateDictionaryValue(R"({
+ auto json_cmds = CreateDictionaryValue(R"({
'robot': {
'_jump': {
'parameters': {'_height': 'integer'},
@@ -542,7 +548,7 @@
const std::string command_url = dev_reg_->GetServiceURL("commands/1234");
- auto commands_json = unittests::CreateValue(R"([{
+ auto commands_json = CreateValue(R"([{
'name':'robot._jump',
'id':'1234',
'parameters': {'_height': 100},
@@ -555,55 +561,52 @@
auto command = command_manager_->FindCommand("1234");
ASSERT_NE(nullptr, command);
- // UpdateCommand when setting command results.
- auto update_command_results = [](const ServerRequest& request,
- ServerResponse* response) {
- EXPECT_EQ(R"({"results":{"status":"Ok"}})",
- request.GetDataAsNormalizedJsonString());
- response->ReplyJson(chromeos::http::status_code::Ok,
- chromeos::http::FormFieldList{});
- };
-
- transport_->AddHandler(command_url, chromeos::http::request_type::kPatch,
- base::Bind(update_command_results));
-
+ EXPECT_CALL(http_client_,
+ MockSendRequest("PATCH", command_url, _,
+ "application/json; charset=utf-8",
+ HttpClient::Headers{GetAuthHeader()}, _))
+ .WillOnce(WithArgs<2>(Invoke([](const std::string& data) {
+ EXPECT_JSON_EQ(R"({"results":{"status":"Ok"}})",
+ *CreateDictionaryValue(data));
+ base::DictionaryValue json;
+ return ReplyWithJson(200, json);
+ })));
EXPECT_TRUE(
command->SetResults(*CreateDictionaryValue("{'status': 'Ok'}"), nullptr));
+ Mock::VerifyAndClearExpectations(&http_client_);
- // UpdateCommand when setting command progress.
- int count = 0; // This will be called twice...
- auto update_command_progress = [&count](const ServerRequest& request,
- ServerResponse* response) {
- if (count++ == 0) {
- EXPECT_EQ(R"({"state":"inProgress"})",
- request.GetDataAsNormalizedJsonString());
- } else {
- EXPECT_EQ(R"({"progress":{"progress":18}})",
- request.GetDataAsNormalizedJsonString());
- }
- response->ReplyJson(chromeos::http::status_code::Ok,
- chromeos::http::FormFieldList{});
- };
+ EXPECT_CALL(http_client_,
+ MockSendRequest("PATCH", command_url, _,
+ "application/json; charset=utf-8",
+ HttpClient::Headers{GetAuthHeader()}, _))
+ .WillOnce(WithArgs<2>(Invoke([](const std::string& data) {
+ EXPECT_JSON_EQ(R"({"state":"inProgress"})",
+ *CreateDictionaryValue(data));
+ base::DictionaryValue json;
+ return ReplyWithJson(200, json);
+ })))
+ .WillOnce(WithArgs<2>(Invoke([](const std::string& data) {
+ EXPECT_JSON_EQ(R"({"progress":{"progress":18}})",
+ *CreateDictionaryValue(data));
+ base::DictionaryValue json;
+ return ReplyWithJson(200, json);
+ })));
+ EXPECT_TRUE(
+ command->SetProgress(*CreateDictionaryValue("{'progress':18}"), nullptr));
+ Mock::VerifyAndClearExpectations(&http_client_);
- transport_->AddHandler(command_url, chromeos::http::request_type::kPatch,
- base::Bind(update_command_progress));
-
- EXPECT_TRUE(command->SetProgress(*CreateDictionaryValue("{'progress': 18}"),
- nullptr));
-
- // UpdateCommand when changing command status.
- auto update_command_state = [](const ServerRequest& request,
- ServerResponse* response) {
- EXPECT_EQ(R"({"state":"cancelled"})",
- request.GetDataAsNormalizedJsonString());
- response->ReplyJson(chromeos::http::status_code::Ok,
- chromeos::http::FormFieldList{});
- };
-
- transport_->AddHandler(command_url, chromeos::http::request_type::kPatch,
- base::Bind(update_command_state));
-
+ EXPECT_CALL(http_client_,
+ MockSendRequest("PATCH", command_url, _,
+ "application/json; charset=utf-8",
+ HttpClient::Headers{GetAuthHeader()}, _))
+ .WillOnce(WithArgs<2>(Invoke([](const std::string& data) {
+ EXPECT_JSON_EQ(R"({"state":"cancelled"})",
+ *CreateDictionaryValue(data));
+ base::DictionaryValue json;
+ return ReplyWithJson(200, json);
+ })));
command->Cancel();
+ Mock::VerifyAndClearExpectations(&http_client_);
}
} // namespace weave
diff --git a/libweave/src/mock_http_client.cc b/libweave/src/mock_http_client.cc
new file mode 100644
index 0000000..d4307a4
--- /dev/null
+++ b/libweave/src/mock_http_client.cc
@@ -0,0 +1,43 @@
+// Copyright 2015 The Chromium OS Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <weave/mock_http_client.h>
+
+#include <memory>
+#include <string>
+
+namespace weave {
+namespace unittests {
+
+std::unique_ptr<HttpClient::Response> MockHttpClient::SendRequestAndBlock(
+ const std::string& method,
+ const std::string& url,
+ const std::string& data,
+ const std::string& mime_type,
+ const Headers& headers,
+ chromeos::ErrorPtr* error) {
+ return std::unique_ptr<Response>{
+ MockSendRequest(method, url, data, mime_type, headers, error)};
+}
+
+int MockHttpClient::SendRequest(const std::string& method,
+ const std::string& url,
+ const std::string& data,
+ const std::string& mime_type,
+ const Headers& headers,
+ const SuccessCallback& success_callback,
+ const ErrorCallback& error_callback) {
+ chromeos::ErrorPtr error;
+ std::unique_ptr<Response> response{
+ MockSendRequest(method, url, data, mime_type, headers, &error)};
+ if (response) {
+ success_callback.Run(0, *response);
+ } else {
+ error_callback.Run(0, error.get());
+ }
+ return 0;
+}
+
+} // namespace unittests
+} // namespace weave