14615e0d5aa416ab1a8596bde68f71f7ebe431b86Vitaly Buka// Copyright 2015 The Weave Authors. All rights reserved.
28e34d391dada2fc3255fecd724f6302e7952be51Alex Vakulenko// Use of this source code is governed by a BSD-style license that can be
38e34d391dada2fc3255fecd724f6302e7952be51Alex Vakulenko// found in the LICENSE file.
48e34d391dada2fc3255fecd724f6302e7952be51Alex Vakulenko
52d16dfa768282b29f3fd5a905b52e3393a083e0dStefan Sauer#include "src/device_registration_info.h"
6f6cbe3237efde97bb7e282a9777ff9b50e196a81Alex Deymo
78e34d391dada2fc3255fecd724f6302e7952be51Alex Vakulenko#include <base/json/json_reader.h>
89e2f8cda5fb177d7dc8d43011eea3829427e34cdAlex Vakulenko#include <base/json/json_writer.h>
98e34d391dada2fc3255fecd724f6302e7952be51Alex Vakulenko#include <base/values.h>
108e34d391dada2fc3255fecd724f6302e7952be51Alex Vakulenko#include <gtest/gtest.h>
11ff1d1862455e0e1aea2dffedf505eea5fdce2c6cVitaly Buka#include <weave/provider/test/fake_task_runner.h>
121e3636732171afb8cceb9e5cb835ec6a93787dbaVitaly Buka#include <weave/provider/test/mock_config_store.h>
131e3636732171afb8cceb9e5cb835ec6a93787dbaVitaly Buka#include <weave/provider/test/mock_http_client.h>
148a05bebb95f5f3f9bf6b72bd9e58b6ba6b8c9bddAlex Vakulenko#include <weave/test/unittest_utils.h>
158e34d391dada2fc3255fecd724f6302e7952be51Alex Vakulenko
162d16dfa768282b29f3fd5a905b52e3393a083e0dStefan Sauer#include "src/bind_lambda.h"
17d91d625f29b752be035c5fb49bb29d7ee85fcb90Alex Vakulenko#include "src/component_manager_impl.h"
182d16dfa768282b29f3fd5a905b52e3393a083e0dStefan Sauer#include "src/http_constants.h"
1972d8d1611efb8c0dd87d466e971bea9468b7c3a1Vitaly Buka#include "src/privet/auth_manager.h"
2072d8d1611efb8c0dd87d466e971bea9468b7c3a1Vitaly Buka#include "src/test/mock_clock.h"
218e34d391dada2fc3255fecd724f6302e7952be51Alex Vakulenko
226b61e5728bb6b014d16f9606a428deb6cbbbd10cVitaly Bukausing testing::_;
231020618923f7bf3066c8d36bbfe0a855eb58a974Vitaly Bukausing testing::AtLeast;
2472d8d1611efb8c0dd87d466e971bea9468b7c3a1Vitaly Bukausing testing::HasSubstr;
251020618923f7bf3066c8d36bbfe0a855eb58a974Vitaly Bukausing testing::Invoke;
261020618923f7bf3066c8d36bbfe0a855eb58a974Vitaly Bukausing testing::InvokeWithoutArgs;
271020618923f7bf3066c8d36bbfe0a855eb58a974Vitaly Bukausing testing::Mock;
286b61e5728bb6b014d16f9606a428deb6cbbbd10cVitaly Bukausing testing::Return;
291020618923f7bf3066c8d36bbfe0a855eb58a974Vitaly Bukausing testing::ReturnRef;
301020618923f7bf3066c8d36bbfe0a855eb58a974Vitaly Bukausing testing::ReturnRefOfCopy;
31c11a17d59330e6356f9da62e5b4a7ecf6a726665Vitaly Bukausing testing::SaveArg;
326b61e5728bb6b014d16f9606a428deb6cbbbd10cVitaly Bukausing testing::StrictMock;
331020618923f7bf3066c8d36bbfe0a855eb58a974Vitaly Bukausing testing::WithArgs;
346b61e5728bb6b014d16f9606a428deb6cbbbd10cVitaly Buka
35b6f015a1ef3caffbc2af53184c0ec5342e42e048Vitaly Bukanamespace weave {
3632005de69ecb92f5507aef03bf363d925d7a682fVitaly Buka
370f6b2eccc9ca4aa35cf0ee1e3ac7bc6edc38f0a4Vitaly Bukausing test::CreateDictionaryValue;
380f6b2eccc9ca4aa35cf0ee1e3ac7bc6edc38f0a4Vitaly Bukausing test::CreateValue;
391e3636732171afb8cceb9e5cb835ec6a93787dbaVitaly Bukausing provider::test::MockHttpClient;
401e3636732171afb8cceb9e5cb835ec6a93787dbaVitaly Bukausing provider::test::MockHttpClientResponse;
411e3636732171afb8cceb9e5cb835ec6a93787dbaVitaly Bukausing provider::HttpClient;
42cca20933927304b0e297c810a7abdacbdba61785Alex Vakulenko
438e34d391dada2fc3255fecd724f6302e7952be51Alex Vakulenkonamespace {
448e34d391dada2fc3255fecd724f6302e7952be51Alex Vakulenko
458e34d391dada2fc3255fecd724f6302e7952be51Alex Vakulenkonamespace test_data {
468e34d391dada2fc3255fecd724f6302e7952be51Alex Vakulenko
473b8fbc546262ac5335e9ddfd219c195b224a4427Vitaly Bukaconst char kXmppEndpoint[] = "xmpp.server.com:1234";
48a647c857f3098b366b379bde308d051f6a9aac2fVitaly Bukaconst char kServiceURL[] = "http://gcd.server.com/";
49a647c857f3098b366b379bde308d051f6a9aac2fVitaly Bukaconst char kOAuthURL[] = "http://oauth.server.com/";
50a647c857f3098b366b379bde308d051f6a9aac2fVitaly Bukaconst char kApiKey[] = "GOadRdTf9FERf0k4w6EFOof56fUJ3kFDdFL3d7f";
51a647c857f3098b366b379bde308d051f6a9aac2fVitaly Bukaconst char kClientId[] =
52a647c857f3098b366b379bde308d051f6a9aac2fVitaly Buka    "123543821385-sfjkjshdkjhfk234sdfsdfkskd"
53a647c857f3098b366b379bde308d051f6a9aac2fVitaly Buka    "fkjh7f.apps.googleusercontent.com";
54a647c857f3098b366b379bde308d051f6a9aac2fVitaly Bukaconst char kClientSecret[] = "5sdGdGlfolGlrFKfdFlgP6FG";
556a9d0e2cd473382d37a2cf11acdfa63c1038392eVitaly Bukaconst char kCloudId[] = "4a7ea2d1-b331-1e1f-b206-e863c7635196";
5672d8d1611efb8c0dd87d466e971bea9468b7c3a1Vitaly Bukaconst char kDeviceId[] = "f6885e46-b432-42d7-86a5-d759bfb61f62";
57a647c857f3098b366b379bde308d051f6a9aac2fVitaly Bukaconst char kClaimTicketId[] = "RTcUE";
58a647c857f3098b366b379bde308d051f6a9aac2fVitaly Bukaconst char kAccessToken[] =
59a647c857f3098b366b379bde308d051f6a9aac2fVitaly Buka    "ya29.1.AADtN_V-dLUM-sVZ0qVjG9Dxm5NgdS9J"
60a647c857f3098b366b379bde308d051f6a9aac2fVitaly Buka    "Mx_JLUqhC9bED_YFjzHZtYt65ZzXCS35NMAeaVZ"
61a647c857f3098b366b379bde308d051f6a9aac2fVitaly Buka    "Dei530-w0yE2urpQ";
62a647c857f3098b366b379bde308d051f6a9aac2fVitaly Bukaconst char kRefreshToken[] =
63a647c857f3098b366b379bde308d051f6a9aac2fVitaly Buka    "1/zQmxR6PKNvhcxf9SjXUrCjcmCrcqRKXctc6cp"
64a647c857f3098b366b379bde308d051f6a9aac2fVitaly Buka    "1nI-GQ";
65a647c857f3098b366b379bde308d051f6a9aac2fVitaly Bukaconst char kRobotAccountAuthCode[] =
66a647c857f3098b366b379bde308d051f6a9aac2fVitaly Buka    "4/Mf_ujEhPejVhOq-OxW9F5cSOnWzx."
67a647c857f3098b366b379bde308d051f6a9aac2fVitaly Buka    "YgciVjTYGscRshQV0ieZDAqiTIjMigI";
68a647c857f3098b366b379bde308d051f6a9aac2fVitaly Bukaconst char kRobotAccountEmail[] =
69a647c857f3098b366b379bde308d051f6a9aac2fVitaly Buka    "6ed0b3f54f9bd619b942f4ad2441c252@"
70a647c857f3098b366b379bde308d051f6a9aac2fVitaly Buka    "clouddevices.gserviceaccount.com";
7172d8d1611efb8c0dd87d466e971bea9468b7c3a1Vitaly Bukaconst char kAuthInfo[] = R"({
72f3fd9c30d383b8f0fc4d4d6cefd172a5fa1200c4Vitaly Buka  "localAuthInfo": {
73f3fd9c30d383b8f0fc4d4d6cefd172a5fa1200c4Vitaly Buka    "certFingerprint":
74f3fd9c30d383b8f0fc4d4d6cefd172a5fa1200c4Vitaly Buka    "FQY6BEINDjw3FgsmYChRWgMzMhc4TC8uG0UUUFhdDz0=",
75f3fd9c30d383b8f0fc4d4d6cefd172a5fa1200c4Vitaly Buka    "localId": "f6885e46-b432-42d7-86a5-d759bfb61f62"
76f3fd9c30d383b8f0fc4d4d6cefd172a5fa1200c4Vitaly Buka  }
7772d8d1611efb8c0dd87d466e971bea9468b7c3a1Vitaly Buka})";
781020618923f7bf3066c8d36bbfe0a855eb58a974Vitaly Buka
798e34d391dada2fc3255fecd724f6302e7952be51Alex Vakulenko}  // namespace test_data
808e34d391dada2fc3255fecd724f6302e7952be51Alex Vakulenko
811020618923f7bf3066c8d36bbfe0a855eb58a974Vitaly Bukastd::string GetFormField(const std::string& data, const std::string& name) {
821020618923f7bf3066c8d36bbfe0a855eb58a974Vitaly Buka  EXPECT_FALSE(data.empty());
837d55639775947b7b34b33702a886aac385f35102Vitaly Buka  for (const auto& i : WebParamsDecode(data)) {
841020618923f7bf3066c8d36bbfe0a855eb58a974Vitaly Buka    if (i.first == name)
851020618923f7bf3066c8d36bbfe0a855eb58a974Vitaly Buka      return i.second;
868e34d391dada2fc3255fecd724f6302e7952be51Alex Vakulenko  }
871020618923f7bf3066c8d36bbfe0a855eb58a974Vitaly Buka  return {};
8824d189fbf5b5ee787831f9905a30bf7383453322Nathan Bullock}
8924d189fbf5b5ee787831f9905a30bf7383453322Nathan Bullock
9017280378dc037c09342604c2a75dddbc669706f2Vitaly Bukastd::unique_ptr<HttpClient::Response> ReplyWithJson(int status_code,
9117280378dc037c09342604c2a75dddbc669706f2Vitaly Buka                                                    const base::Value& json) {
921020618923f7bf3066c8d36bbfe0a855eb58a974Vitaly Buka  std::string text;
931020618923f7bf3066c8d36bbfe0a855eb58a974Vitaly Buka  base::JSONWriter::WriteWithOptions(
941020618923f7bf3066c8d36bbfe0a855eb58a974Vitaly Buka      json, base::JSONWriter::OPTIONS_PRETTY_PRINT, &text);
951020618923f7bf3066c8d36bbfe0a855eb58a974Vitaly Buka
9617280378dc037c09342604c2a75dddbc669706f2Vitaly Buka  std::unique_ptr<MockHttpClientResponse> response{
9717280378dc037c09342604c2a75dddbc669706f2Vitaly Buka      new StrictMock<MockHttpClientResponse>};
981020618923f7bf3066c8d36bbfe0a855eb58a974Vitaly Buka  EXPECT_CALL(*response, GetStatusCode())
991020618923f7bf3066c8d36bbfe0a855eb58a974Vitaly Buka      .Times(AtLeast(1))
1001020618923f7bf3066c8d36bbfe0a855eb58a974Vitaly Buka      .WillRepeatedly(Return(status_code));
1011020618923f7bf3066c8d36bbfe0a855eb58a974Vitaly Buka  EXPECT_CALL(*response, GetContentType())
1021020618923f7bf3066c8d36bbfe0a855eb58a974Vitaly Buka      .Times(AtLeast(1))
103815b603b59bebac4407322af61a822413ad421f6Vitaly Buka      .WillRepeatedly(Return(http::kJsonUtf8));
1041020618923f7bf3066c8d36bbfe0a855eb58a974Vitaly Buka  EXPECT_CALL(*response, GetData())
1051020618923f7bf3066c8d36bbfe0a855eb58a974Vitaly Buka      .Times(AtLeast(1))
1064774df2734a2b74f16047983751673388b6cb5b5Vitaly Buka      .WillRepeatedly(Return(text));
10717280378dc037c09342604c2a75dddbc669706f2Vitaly Buka  return std::move(response);
10824d189fbf5b5ee787831f9905a30bf7383453322Nathan Bullock}
10924d189fbf5b5ee787831f9905a30bf7383453322Nathan Bullock
1101020618923f7bf3066c8d36bbfe0a855eb58a974Vitaly Bukastd::pair<std::string, std::string> GetAuthHeader() {
111815b603b59bebac4407322af61a822413ad421f6Vitaly Buka  return {http::kAuthorization,
112815b603b59bebac4407322af61a822413ad421f6Vitaly Buka          std::string("Bearer ") + test_data::kAccessToken};
113815b603b59bebac4407322af61a822413ad421f6Vitaly Buka}
114815b603b59bebac4407322af61a822413ad421f6Vitaly Buka
115815b603b59bebac4407322af61a822413ad421f6Vitaly Bukastd::pair<std::string, std::string> GetJsonHeader() {
116815b603b59bebac4407322af61a822413ad421f6Vitaly Buka  return {http::kContentType, http::kJsonUtf8};
117815b603b59bebac4407322af61a822413ad421f6Vitaly Buka}
118815b603b59bebac4407322af61a822413ad421f6Vitaly Buka
119815b603b59bebac4407322af61a822413ad421f6Vitaly Bukastd::pair<std::string, std::string> GetFormHeader() {
120815b603b59bebac4407322af61a822413ad421f6Vitaly Buka  return {http::kContentType, http::kWwwFormUrlEncoded};
1218e34d391dada2fc3255fecd724f6302e7952be51Alex Vakulenko}
1228e34d391dada2fc3255fecd724f6302e7952be51Alex Vakulenko
1238e34d391dada2fc3255fecd724f6302e7952be51Alex Vakulenko}  // anonymous namespace
1248e34d391dada2fc3255fecd724f6302e7952be51Alex Vakulenko
1258e34d391dada2fc3255fecd724f6302e7952be51Alex Vakulenkoclass DeviceRegistrationInfoTest : public ::testing::Test {
1268e34d391dada2fc3255fecd724f6302e7952be51Alex Vakulenko protected:
1275a9e718e5299c72094d1bcfd988d7e44831e9d07Alex Vakulenko  void SetUp() override {
12872d8d1611efb8c0dd87d466e971bea9468b7c3a1Vitaly Buka    EXPECT_CALL(clock_, Now())
12972d8d1611efb8c0dd87d466e971bea9468b7c3a1Vitaly Buka        .WillRepeatedly(Return(base::Time::FromTimeT(1450000000)));
130c11a17d59330e6356f9da62e5b4a7ecf6a726665Vitaly Buka    ReloadDefaults();
131ee7a3af2e8ab08e0a71a407f2bfa8d3ca78b0f79Vitaly Buka  }
132ee7a3af2e8ab08e0a71a407f2bfa8d3ca78b0f79Vitaly Buka
133c11a17d59330e6356f9da62e5b4a7ecf6a726665Vitaly Buka  void ReloadDefaults() {
134c11a17d59330e6356f9da62e5b4a7ecf6a726665Vitaly Buka    EXPECT_CALL(config_store_, LoadDefaults(_))
135c11a17d59330e6356f9da62e5b4a7ecf6a726665Vitaly Buka        .WillOnce(Invoke([](Settings* settings) {
136c11a17d59330e6356f9da62e5b4a7ecf6a726665Vitaly Buka          settings->client_id = test_data::kClientId;
137c11a17d59330e6356f9da62e5b4a7ecf6a726665Vitaly Buka          settings->client_secret = test_data::kClientSecret;
138c11a17d59330e6356f9da62e5b4a7ecf6a726665Vitaly Buka          settings->api_key = test_data::kApiKey;
139a05eadb5a34b90e3aec184c41b9e3481e18902b3Vitaly Buka          settings->oem_name = "Coffee Pot Maker";
140a05eadb5a34b90e3aec184c41b9e3481e18902b3Vitaly Buka          settings->model_name = "Pot v1";
141c11a17d59330e6356f9da62e5b4a7ecf6a726665Vitaly Buka          settings->name = "Coffee Pot";
142c11a17d59330e6356f9da62e5b4a7ecf6a726665Vitaly Buka          settings->description = "Easy to clean";
143c11a17d59330e6356f9da62e5b4a7ecf6a726665Vitaly Buka          settings->location = "Kitchen";
144b624bc47fb70294185478e4c758657a54b859cb1Vitaly Buka          settings->local_anonymous_access_role = AuthScope::kViewer;
145c11a17d59330e6356f9da62e5b4a7ecf6a726665Vitaly Buka          settings->model_id = "AAAAA";
146c11a17d59330e6356f9da62e5b4a7ecf6a726665Vitaly Buka          settings->oauth_url = test_data::kOAuthURL;
147c11a17d59330e6356f9da62e5b4a7ecf6a726665Vitaly Buka          settings->service_url = test_data::kServiceURL;
1483b8fbc546262ac5335e9ddfd219c195b224a4427Vitaly Buka          settings->xmpp_endpoint = test_data::kXmppEndpoint;
149c11a17d59330e6356f9da62e5b4a7ecf6a726665Vitaly Buka          return true;
150c11a17d59330e6356f9da62e5b4a7ecf6a726665Vitaly Buka        }));
1513d6b55295d49240a8e3575ffd8561231074714a9Vitaly Buka    config_.reset(new Config{&config_store_});
1523d6b55295d49240a8e3575ffd8561231074714a9Vitaly Buka    dev_reg_.reset(new DeviceRegistrationInfo{
1533d6b55295d49240a8e3575ffd8561231074714a9Vitaly Buka        config_.get(), &component_manager_, &task_runner_, &http_client_,
1543d6b55295d49240a8e3575ffd8561231074714a9Vitaly Buka        nullptr, &auth_});
155ee7a3af2e8ab08e0a71a407f2bfa8d3ca78b0f79Vitaly Buka    dev_reg_->Start();
156ee7a3af2e8ab08e0a71a407f2bfa8d3ca78b0f79Vitaly Buka  }
157ee7a3af2e8ab08e0a71a407f2bfa8d3ca78b0f79Vitaly Buka
1580a8ab9973e1fdf6b41d8f7b49529c9bd97a9071cVitaly Buka  void ReloadSettings(bool registered = true) {
159c11a17d59330e6356f9da62e5b4a7ecf6a726665Vitaly Buka    base::DictionaryValue dict;
1600a8ab9973e1fdf6b41d8f7b49529c9bd97a9071cVitaly Buka    dict.SetInteger("version", 1);
1610a8ab9973e1fdf6b41d8f7b49529c9bd97a9071cVitaly Buka    if (registered) {
1620a8ab9973e1fdf6b41d8f7b49529c9bd97a9071cVitaly Buka      dict.SetString("refresh_token", test_data::kRefreshToken);
1630a8ab9973e1fdf6b41d8f7b49529c9bd97a9071cVitaly Buka      dict.SetString("cloud_id", test_data::kCloudId);
1640a8ab9973e1fdf6b41d8f7b49529c9bd97a9071cVitaly Buka      dict.SetString("robot_account", test_data::kRobotAccountEmail);
1650a8ab9973e1fdf6b41d8f7b49529c9bd97a9071cVitaly Buka    }
16672d8d1611efb8c0dd87d466e971bea9468b7c3a1Vitaly Buka    dict.SetString("device_id", test_data::kDeviceId);
167c11a17d59330e6356f9da62e5b4a7ecf6a726665Vitaly Buka    std::string json_string;
168c11a17d59330e6356f9da62e5b4a7ecf6a726665Vitaly Buka    base::JSONWriter::WriteWithOptions(
169c11a17d59330e6356f9da62e5b4a7ecf6a726665Vitaly Buka        dict, base::JSONWriter::OPTIONS_PRETTY_PRINT, &json_string);
170c11a17d59330e6356f9da62e5b4a7ecf6a726665Vitaly Buka    EXPECT_CALL(config_store_, LoadSettings()).WillOnce(Return(json_string));
171c11a17d59330e6356f9da62e5b4a7ecf6a726665Vitaly Buka    ReloadDefaults();
172c11a17d59330e6356f9da62e5b4a7ecf6a726665Vitaly Buka  }
173c11a17d59330e6356f9da62e5b4a7ecf6a726665Vitaly Buka
174ee7a3af2e8ab08e0a71a407f2bfa8d3ca78b0f79Vitaly Buka  void PublishCommands(const base::ListValue& commands) {
175747634273144e0df7b37475375ad4790b6a7b0e8Vitaly Buka    dev_reg_->PublishCommands(commands, nullptr);
176ee7a3af2e8ab08e0a71a407f2bfa8d3ca78b0f79Vitaly Buka  }
177ee7a3af2e8ab08e0a71a407f2bfa8d3ca78b0f79Vitaly Buka
1780801a1f20a0c8f34130d567cd3b7dcbd2be9cb3cVitaly Buka  bool RefreshAccessToken(ErrorPtr* error) const {
179266b2b15731ff30ada2cb9cf040c465e774b6e09Alex Vakulenko    bool succeeded = false;
180747634273144e0df7b37475375ad4790b6a7b0e8Vitaly Buka    auto callback = [&succeeded, &error](ErrorPtr in_error) {
181747634273144e0df7b37475375ad4790b6a7b0e8Vitaly Buka      if (error) {
182f7f52d4707c007bb9255bd80b23ac3428c6fc2e0Vitaly Buka        *error = std::move(in_error);
183747634273144e0df7b37475375ad4790b6a7b0e8Vitaly Buka        return;
184747634273144e0df7b37475375ad4790b6a7b0e8Vitaly Buka      }
185747634273144e0df7b37475375ad4790b6a7b0e8Vitaly Buka      succeeded = true;
186266b2b15731ff30ada2cb9cf040c465e774b6e09Alex Vakulenko    };
187747634273144e0df7b37475375ad4790b6a7b0e8Vitaly Buka    dev_reg_->RefreshAccessToken(base::Bind(callback));
188266b2b15731ff30ada2cb9cf040c465e774b6e09Alex Vakulenko    return succeeded;
189266b2b15731ff30ada2cb9cf040c465e774b6e09Alex Vakulenko  }
190266b2b15731ff30ada2cb9cf040c465e774b6e09Alex Vakulenko
191a647c857f3098b366b379bde308d051f6a9aac2fVitaly Buka  void SetAccessToken() { dev_reg_->access_token_ = test_data::kAccessToken; }
192ee7a3af2e8ab08e0a71a407f2bfa8d3ca78b0f79Vitaly Buka
193c3c6dab99bb333417756817d154cd99ae71f4668Vitaly Buka  GcdState GetGcdState() const { return dev_reg_->GetGcdState(); }
1948e34d391dada2fc3255fecd724f6302e7952be51Alex Vakulenko
195672634b8b0ed31891fb48e02dce75b6aead0be27Vitaly Buka  bool HaveRegistrationCredentials() const {
196672634b8b0ed31891fb48e02dce75b6aead0be27Vitaly Buka    return dev_reg_->HaveRegistrationCredentials();
197672634b8b0ed31891fb48e02dce75b6aead0be27Vitaly Buka  }
198672634b8b0ed31891fb48e02dce75b6aead0be27Vitaly Buka
199ff1d1862455e0e1aea2dffedf505eea5fdce2c6cVitaly Buka  provider::test::FakeTaskRunner task_runner_;
2001e3636732171afb8cceb9e5cb835ec6a93787dbaVitaly Buka  provider::test::MockConfigStore config_store_;
2011020618923f7bf3066c8d36bbfe0a855eb58a974Vitaly Buka  StrictMock<MockHttpClient> http_client_;
20245109440ce6618aa8bb5084466ba2c4f1a8e2660Alex Vakulenko  base::DictionaryValue data_;
2033d6b55295d49240a8e3575ffd8561231074714a9Vitaly Buka  std::unique_ptr<Config> config_;
20472d8d1611efb8c0dd87d466e971bea9468b7c3a1Vitaly Buka  test::MockClock clock_;
20572d8d1611efb8c0dd87d466e971bea9468b7c3a1Vitaly Buka  privet::AuthManager auth_{
20672d8d1611efb8c0dd87d466e971bea9468b7c3a1Vitaly Buka      {68, 52, 36, 95, 74, 89, 25, 2, 31, 5, 65, 87, 64, 32, 17, 26, 8, 73, 57,
20772d8d1611efb8c0dd87d466e971bea9468b7c3a1Vitaly Buka       16, 33, 82, 71, 10, 72, 62, 45, 1, 77, 97, 70, 24},
20872d8d1611efb8c0dd87d466e971bea9468b7c3a1Vitaly Buka      {21, 6, 58, 4, 66, 13, 14, 60, 55, 22, 11, 38, 96, 40, 81, 90, 3, 51, 50,
20972d8d1611efb8c0dd87d466e971bea9468b7c3a1Vitaly Buka       23, 56, 76, 47, 46, 27, 69, 20, 80, 88, 93, 15, 61},
2100bc02ede1d7ac6b0ed264b8891844d15bdb4733eVitaly Buka      {},
21172d8d1611efb8c0dd87d466e971bea9468b7c3a1Vitaly Buka      &clock_};
21245109440ce6618aa8bb5084466ba2c4f1a8e2660Alex Vakulenko  std::unique_ptr<DeviceRegistrationInfo> dev_reg_;
21398d1fee994302f5e2ad7a7b60de2f2d74f35408bAlex Vakulenko  ComponentManagerImpl component_manager_{&task_runner_};
2148e34d391dada2fc3255fecd724f6302e7952be51Alex Vakulenko};
2158e34d391dada2fc3255fecd724f6302e7952be51Alex Vakulenko
2168e34d391dada2fc3255fecd724f6302e7952be51Alex VakulenkoTEST_F(DeviceRegistrationInfoTest, GetServiceURL) {
21745109440ce6618aa8bb5084466ba2c4f1a8e2660Alex Vakulenko  EXPECT_EQ(test_data::kServiceURL, dev_reg_->GetServiceURL());
2188e34d391dada2fc3255fecd724f6302e7952be51Alex Vakulenko  std::string url = test_data::kServiceURL;
2198e34d391dada2fc3255fecd724f6302e7952be51Alex Vakulenko  url += "registrationTickets";
22045109440ce6618aa8bb5084466ba2c4f1a8e2660Alex Vakulenko  EXPECT_EQ(url, dev_reg_->GetServiceURL("registrationTickets"));
2218e34d391dada2fc3255fecd724f6302e7952be51Alex Vakulenko  url += "?key=";
2228e34d391dada2fc3255fecd724f6302e7952be51Alex Vakulenko  url += test_data::kApiKey;
223a647c857f3098b366b379bde308d051f6a9aac2fVitaly Buka  EXPECT_EQ(url, dev_reg_->GetServiceURL("registrationTickets",
224a647c857f3098b366b379bde308d051f6a9aac2fVitaly Buka                                         {{"key", test_data::kApiKey}}));
2258e34d391dada2fc3255fecd724f6302e7952be51Alex Vakulenko  url += "&restart=true";
226a647c857f3098b366b379bde308d051f6a9aac2fVitaly Buka  EXPECT_EQ(url, dev_reg_->GetServiceURL(
227a647c857f3098b366b379bde308d051f6a9aac2fVitaly Buka                     "registrationTickets",
228a647c857f3098b366b379bde308d051f6a9aac2fVitaly Buka                     {
229a647c857f3098b366b379bde308d051f6a9aac2fVitaly Buka                         {"key", test_data::kApiKey}, {"restart", "true"},
230a647c857f3098b366b379bde308d051f6a9aac2fVitaly Buka                     }));
2318e34d391dada2fc3255fecd724f6302e7952be51Alex Vakulenko}
2328e34d391dada2fc3255fecd724f6302e7952be51Alex Vakulenko
2338e34d391dada2fc3255fecd724f6302e7952be51Alex VakulenkoTEST_F(DeviceRegistrationInfoTest, GetOAuthURL) {
23445109440ce6618aa8bb5084466ba2c4f1a8e2660Alex Vakulenko  EXPECT_EQ(test_data::kOAuthURL, dev_reg_->GetOAuthURL());
2358e34d391dada2fc3255fecd724f6302e7952be51Alex Vakulenko  std::string url = test_data::kOAuthURL;
23688272d5b9e88dfd253c18aea4792fe57ee51696dVitaly Buka  url += "auth?redirect_uri=urn%3Aietf%3Awg%3Aoauth%3A2.0%3Aoob&";
2378e34d391dada2fc3255fecd724f6302e7952be51Alex Vakulenko  url += "response_type=code&";
2388e34d391dada2fc3255fecd724f6302e7952be51Alex Vakulenko  url += "client_id=";
2398e34d391dada2fc3255fecd724f6302e7952be51Alex Vakulenko  url += test_data::kClientId;
240a647c857f3098b366b379bde308d051f6a9aac2fVitaly Buka  EXPECT_EQ(url, dev_reg_->GetOAuthURL(
241c27390d203688b847378944d5ae0ec8f1938c598Vitaly Buka                     "auth", {{"redirect_uri", "urn:ietf:wg:oauth:2.0:oob"},
242c27390d203688b847378944d5ae0ec8f1938c598Vitaly Buka                              {"response_type", "code"},
243c27390d203688b847378944d5ae0ec8f1938c598Vitaly Buka                              {"client_id", test_data::kClientId}}));
2448e34d391dada2fc3255fecd724f6302e7952be51Alex Vakulenko}
2458e34d391dada2fc3255fecd724f6302e7952be51Alex Vakulenko
246266b2b15731ff30ada2cb9cf040c465e774b6e09Alex VakulenkoTEST_F(DeviceRegistrationInfoTest, HaveRegistrationCredentials) {
247672634b8b0ed31891fb48e02dce75b6aead0be27Vitaly Buka  EXPECT_FALSE(HaveRegistrationCredentials());
248c11a17d59330e6356f9da62e5b4a7ecf6a726665Vitaly Buka  ReloadSettings();
24945109440ce6618aa8bb5084466ba2c4f1a8e2660Alex Vakulenko
2501a42e1466de3edd0c79215b739cd8e929ef8a7e8Vitaly Buka  EXPECT_CALL(
2511a42e1466de3edd0c79215b739cd8e929ef8a7e8Vitaly Buka      http_client_,
2521a42e1466de3edd0c79215b739cd8e929ef8a7e8Vitaly Buka      SendRequest(HttpClient::Method::kPost, dev_reg_->GetOAuthURL("token"),
253747634273144e0df7b37475375ad4790b6a7b0e8Vitaly Buka                  HttpClient::Headers{GetFormHeader()}, _, _))
25434668e731bb194b443bc0e6029d6d3583f08de28Vitaly Buka      .WillOnce(WithArgs<3, 4>(
25534668e731bb194b443bc0e6029d6d3583f08de28Vitaly Buka          Invoke([](const std::string& data,
25634668e731bb194b443bc0e6029d6d3583f08de28Vitaly Buka                    const HttpClient::SendRequestCallback& callback) {
25734668e731bb194b443bc0e6029d6d3583f08de28Vitaly Buka            EXPECT_EQ("refresh_token", GetFormField(data, "grant_type"));
25834668e731bb194b443bc0e6029d6d3583f08de28Vitaly Buka            EXPECT_EQ(test_data::kRefreshToken,
25934668e731bb194b443bc0e6029d6d3583f08de28Vitaly Buka                      GetFormField(data, "refresh_token"));
26034668e731bb194b443bc0e6029d6d3583f08de28Vitaly Buka            EXPECT_EQ(test_data::kClientId, GetFormField(data, "client_id"));
26134668e731bb194b443bc0e6029d6d3583f08de28Vitaly Buka            EXPECT_EQ(test_data::kClientSecret,
26234668e731bb194b443bc0e6029d6d3583f08de28Vitaly Buka                      GetFormField(data, "client_secret"));
2631020618923f7bf3066c8d36bbfe0a855eb58a974Vitaly Buka
26434668e731bb194b443bc0e6029d6d3583f08de28Vitaly Buka            base::DictionaryValue json;
26534668e731bb194b443bc0e6029d6d3583f08de28Vitaly Buka            json.SetString("access_token", test_data::kAccessToken);
26634668e731bb194b443bc0e6029d6d3583f08de28Vitaly Buka            json.SetInteger("expires_in", 3600);
2671020618923f7bf3066c8d36bbfe0a855eb58a974Vitaly Buka
26834668e731bb194b443bc0e6029d6d3583f08de28Vitaly Buka            callback.Run(ReplyWithJson(200, json), nullptr);
26934668e731bb194b443bc0e6029d6d3583f08de28Vitaly Buka          })));
2701020618923f7bf3066c8d36bbfe0a855eb58a974Vitaly Buka
27172d8d1611efb8c0dd87d466e971bea9468b7c3a1Vitaly Buka  EXPECT_CALL(
27272d8d1611efb8c0dd87d466e971bea9468b7c3a1Vitaly Buka      http_client_,
27372d8d1611efb8c0dd87d466e971bea9468b7c3a1Vitaly Buka      SendRequest(HttpClient::Method::kPost, HasSubstr("upsertLocalAuthInfo"),
27472d8d1611efb8c0dd87d466e971bea9468b7c3a1Vitaly Buka                  HttpClient::Headers{GetAuthHeader(), GetJsonHeader()}, _, _))
27572d8d1611efb8c0dd87d466e971bea9468b7c3a1Vitaly Buka      .WillOnce(WithArgs<3, 4>(
27672d8d1611efb8c0dd87d466e971bea9468b7c3a1Vitaly Buka          Invoke([](const std::string& data,
27772d8d1611efb8c0dd87d466e971bea9468b7c3a1Vitaly Buka                    const HttpClient::SendRequestCallback& callback) {
27829bc59330bec58e43df1050bee279819b54e7c6eVitaly Buka            auto dict = CreateDictionaryValue(data);
279f3fd9c30d383b8f0fc4d4d6cefd172a5fa1200c4Vitaly Buka            EXPECT_TRUE(dict->Remove("localAuthInfo.clientToken", nullptr));
28029bc59330bec58e43df1050bee279819b54e7c6eVitaly Buka            EXPECT_JSON_EQ(test_data::kAuthInfo, *dict);
28172d8d1611efb8c0dd87d466e971bea9468b7c3a1Vitaly Buka            base::DictionaryValue json;
28272d8d1611efb8c0dd87d466e971bea9468b7c3a1Vitaly Buka            callback.Run(ReplyWithJson(200, json), nullptr);
28372d8d1611efb8c0dd87d466e971bea9468b7c3a1Vitaly Buka          })));
28472d8d1611efb8c0dd87d466e971bea9468b7c3a1Vitaly Buka
285266b2b15731ff30ada2cb9cf040c465e774b6e09Alex Vakulenko  EXPECT_TRUE(RefreshAccessToken(nullptr));
286672634b8b0ed31891fb48e02dce75b6aead0be27Vitaly Buka  EXPECT_TRUE(HaveRegistrationCredentials());
2878e34d391dada2fc3255fecd724f6302e7952be51Alex Vakulenko}
2888e34d391dada2fc3255fecd724f6302e7952be51Alex Vakulenko
28924d189fbf5b5ee787831f9905a30bf7383453322Nathan BullockTEST_F(DeviceRegistrationInfoTest, CheckAuthenticationFailure) {
290c11a17d59330e6356f9da62e5b4a7ecf6a726665Vitaly Buka  ReloadSettings();
291c3c6dab99bb333417756817d154cd99ae71f4668Vitaly Buka  EXPECT_EQ(GcdState::kConnecting, GetGcdState());
29224d189fbf5b5ee787831f9905a30bf7383453322Nathan Bullock
2931a42e1466de3edd0c79215b739cd8e929ef8a7e8Vitaly Buka  EXPECT_CALL(
2941a42e1466de3edd0c79215b739cd8e929ef8a7e8Vitaly Buka      http_client_,
2951a42e1466de3edd0c79215b739cd8e929ef8a7e8Vitaly Buka      SendRequest(HttpClient::Method::kPost, dev_reg_->GetOAuthURL("token"),
296747634273144e0df7b37475375ad4790b6a7b0e8Vitaly Buka                  HttpClient::Headers{GetFormHeader()}, _, _))
29734668e731bb194b443bc0e6029d6d3583f08de28Vitaly Buka      .WillOnce(WithArgs<3, 4>(
29834668e731bb194b443bc0e6029d6d3583f08de28Vitaly Buka          Invoke([](const std::string& data,
29934668e731bb194b443bc0e6029d6d3583f08de28Vitaly Buka                    const HttpClient::SendRequestCallback& callback) {
30034668e731bb194b443bc0e6029d6d3583f08de28Vitaly Buka            EXPECT_EQ("refresh_token", GetFormField(data, "grant_type"));
30134668e731bb194b443bc0e6029d6d3583f08de28Vitaly Buka            EXPECT_EQ(test_data::kRefreshToken,
30234668e731bb194b443bc0e6029d6d3583f08de28Vitaly Buka                      GetFormField(data, "refresh_token"));
30334668e731bb194b443bc0e6029d6d3583f08de28Vitaly Buka            EXPECT_EQ(test_data::kClientId, GetFormField(data, "client_id"));
30434668e731bb194b443bc0e6029d6d3583f08de28Vitaly Buka            EXPECT_EQ(test_data::kClientSecret,
30534668e731bb194b443bc0e6029d6d3583f08de28Vitaly Buka                      GetFormField(data, "client_secret"));
3061020618923f7bf3066c8d36bbfe0a855eb58a974Vitaly Buka
30734668e731bb194b443bc0e6029d6d3583f08de28Vitaly Buka            base::DictionaryValue json;
30834668e731bb194b443bc0e6029d6d3583f08de28Vitaly Buka            json.SetString("error", "unable_to_authenticate");
30934668e731bb194b443bc0e6029d6d3583f08de28Vitaly Buka            callback.Run(ReplyWithJson(400, json), nullptr);
31034668e731bb194b443bc0e6029d6d3583f08de28Vitaly Buka          })));
3111020618923f7bf3066c8d36bbfe0a855eb58a974Vitaly Buka
3120801a1f20a0c8f34130d567cd3b7dcbd2be9cb3cVitaly Buka  ErrorPtr error;
313266b2b15731ff30ada2cb9cf040c465e774b6e09Alex Vakulenko  EXPECT_FALSE(RefreshAccessToken(&error));
31448a8669ddc2e8d785aad9ad18a5abbf8f1224fdeVitaly Buka  EXPECT_TRUE(error->HasError("unable_to_authenticate"));
315c3c6dab99bb333417756817d154cd99ae71f4668Vitaly Buka  EXPECT_EQ(GcdState::kConnecting, GetGcdState());
31624d189fbf5b5ee787831f9905a30bf7383453322Nathan Bullock}
31724d189fbf5b5ee787831f9905a30bf7383453322Nathan Bullock
31824d189fbf5b5ee787831f9905a30bf7383453322Nathan BullockTEST_F(DeviceRegistrationInfoTest, CheckDeregistration) {
319c11a17d59330e6356f9da62e5b4a7ecf6a726665Vitaly Buka  ReloadSettings();
320c3c6dab99bb333417756817d154cd99ae71f4668Vitaly Buka  EXPECT_EQ(GcdState::kConnecting, GetGcdState());
32124d189fbf5b5ee787831f9905a30bf7383453322Nathan Bullock
3221a42e1466de3edd0c79215b739cd8e929ef8a7e8Vitaly Buka  EXPECT_CALL(
3231a42e1466de3edd0c79215b739cd8e929ef8a7e8Vitaly Buka      http_client_,
3241a42e1466de3edd0c79215b739cd8e929ef8a7e8Vitaly Buka      SendRequest(HttpClient::Method::kPost, dev_reg_->GetOAuthURL("token"),
325747634273144e0df7b37475375ad4790b6a7b0e8Vitaly Buka                  HttpClient::Headers{GetFormHeader()}, _, _))
32634668e731bb194b443bc0e6029d6d3583f08de28Vitaly Buka      .WillOnce(WithArgs<3, 4>(
32734668e731bb194b443bc0e6029d6d3583f08de28Vitaly Buka          Invoke([](const std::string& data,
32834668e731bb194b443bc0e6029d6d3583f08de28Vitaly Buka                    const HttpClient::SendRequestCallback& callback) {
32934668e731bb194b443bc0e6029d6d3583f08de28Vitaly Buka            EXPECT_EQ("refresh_token", GetFormField(data, "grant_type"));
33034668e731bb194b443bc0e6029d6d3583f08de28Vitaly Buka            EXPECT_EQ(test_data::kRefreshToken,
33134668e731bb194b443bc0e6029d6d3583f08de28Vitaly Buka                      GetFormField(data, "refresh_token"));
33234668e731bb194b443bc0e6029d6d3583f08de28Vitaly Buka            EXPECT_EQ(test_data::kClientId, GetFormField(data, "client_id"));
33334668e731bb194b443bc0e6029d6d3583f08de28Vitaly Buka            EXPECT_EQ(test_data::kClientSecret,
33434668e731bb194b443bc0e6029d6d3583f08de28Vitaly Buka                      GetFormField(data, "client_secret"));
3351020618923f7bf3066c8d36bbfe0a855eb58a974Vitaly Buka
33634668e731bb194b443bc0e6029d6d3583f08de28Vitaly Buka            base::DictionaryValue json;
33734668e731bb194b443bc0e6029d6d3583f08de28Vitaly Buka            json.SetString("error", "invalid_grant");
33834668e731bb194b443bc0e6029d6d3583f08de28Vitaly Buka            callback.Run(ReplyWithJson(400, json), nullptr);
33934668e731bb194b443bc0e6029d6d3583f08de28Vitaly Buka          })));
3401020618923f7bf3066c8d36bbfe0a855eb58a974Vitaly Buka
3410801a1f20a0c8f34130d567cd3b7dcbd2be9cb3cVitaly Buka  ErrorPtr error;
342266b2b15731ff30ada2cb9cf040c465e774b6e09Alex Vakulenko  EXPECT_FALSE(RefreshAccessToken(&error));
34348a8669ddc2e8d785aad9ad18a5abbf8f1224fdeVitaly Buka  EXPECT_TRUE(error->HasError("invalid_grant"));
344c3c6dab99bb333417756817d154cd99ae71f4668Vitaly Buka  EXPECT_EQ(GcdState::kInvalidCredentials, GetGcdState());
3456a9d0e2cd473382d37a2cf11acdfa63c1038392eVitaly Buka  EXPECT_EQ(test_data::kCloudId, dev_reg_->GetSettings().cloud_id);
34624d189fbf5b5ee787831f9905a30bf7383453322Nathan Bullock}
34724d189fbf5b5ee787831f9905a30bf7383453322Nathan Bullock
3488e34d391dada2fc3255fecd724f6302e7952be51Alex VakulenkoTEST_F(DeviceRegistrationInfoTest, GetDeviceInfo) {
349c11a17d59330e6356f9da62e5b4a7ecf6a726665Vitaly Buka  ReloadSettings();
350266b2b15731ff30ada2cb9cf040c465e774b6e09Alex Vakulenko  SetAccessToken();
35145109440ce6618aa8bb5084466ba2c4f1a8e2660Alex Vakulenko
352747634273144e0df7b37475375ad4790b6a7b0e8Vitaly Buka  EXPECT_CALL(
353747634273144e0df7b37475375ad4790b6a7b0e8Vitaly Buka      http_client_,
354747634273144e0df7b37475375ad4790b6a7b0e8Vitaly Buka      SendRequest(HttpClient::Method::kGet, dev_reg_->GetDeviceURL(),
355747634273144e0df7b37475375ad4790b6a7b0e8Vitaly Buka                  HttpClient::Headers{GetAuthHeader(), GetJsonHeader()}, _, _))
35617280378dc037c09342604c2a75dddbc669706f2Vitaly Buka      .WillOnce(WithArgs<3, 4>(
35717280378dc037c09342604c2a75dddbc669706f2Vitaly Buka          Invoke([](const std::string& data,
358747634273144e0df7b37475375ad4790b6a7b0e8Vitaly Buka                    const HttpClient::SendRequestCallback& callback) {
35917280378dc037c09342604c2a75dddbc669706f2Vitaly Buka            base::DictionaryValue json;
36017280378dc037c09342604c2a75dddbc669706f2Vitaly Buka            json.SetString("channel.supportedType", "xmpp");
36117280378dc037c09342604c2a75dddbc669706f2Vitaly Buka            json.SetString("deviceKind", "vendor");
3626a9d0e2cd473382d37a2cf11acdfa63c1038392eVitaly Buka            json.SetString("id", test_data::kCloudId);
36388272d5b9e88dfd253c18aea4792fe57ee51696dVitaly Buka            json.SetString("kind", "weave#device");
364747634273144e0df7b37475375ad4790b6a7b0e8Vitaly Buka            callback.Run(ReplyWithJson(200, json), nullptr);
36517280378dc037c09342604c2a75dddbc669706f2Vitaly Buka          })));
3661020618923f7bf3066c8d36bbfe0a855eb58a974Vitaly Buka
367266b2b15731ff30ada2cb9cf040c465e774b6e09Alex Vakulenko  bool succeeded = false;
368747634273144e0df7b37475375ad4790b6a7b0e8Vitaly Buka  auto callback = [&succeeded, this](const base::DictionaryValue& info,
369747634273144e0df7b37475375ad4790b6a7b0e8Vitaly Buka                                     ErrorPtr error) {
370747634273144e0df7b37475375ad4790b6a7b0e8Vitaly Buka    EXPECT_FALSE(error);
371266b2b15731ff30ada2cb9cf040c465e774b6e09Alex Vakulenko    std::string id;
372266b2b15731ff30ada2cb9cf040c465e774b6e09Alex Vakulenko    EXPECT_TRUE(info.GetString("id", &id));
3736a9d0e2cd473382d37a2cf11acdfa63c1038392eVitaly Buka    EXPECT_EQ(test_data::kCloudId, id);
374266b2b15731ff30ada2cb9cf040c465e774b6e09Alex Vakulenko    succeeded = true;
375266b2b15731ff30ada2cb9cf040c465e774b6e09Alex Vakulenko  };
376747634273144e0df7b37475375ad4790b6a7b0e8Vitaly Buka  dev_reg_->GetDeviceInfo(base::Bind(callback));
377266b2b15731ff30ada2cb9cf040c465e774b6e09Alex Vakulenko  EXPECT_TRUE(succeeded);
3788e34d391dada2fc3255fecd724f6302e7952be51Alex Vakulenko}
3798e34d391dada2fc3255fecd724f6302e7952be51Alex Vakulenko
380beb1c5bef5530a76ad2ae421d8115e54386855d5Anton MuhinTEST_F(DeviceRegistrationInfoTest, RegisterDevice) {
3810a8ab9973e1fdf6b41d8f7b49529c9bd97a9071cVitaly Buka  ReloadSettings(false);
38272d8d1611efb8c0dd87d466e971bea9468b7c3a1Vitaly Buka
383d91d625f29b752be035c5fb49bb29d7ee85fcb90Alex Vakulenko  auto json_traits = CreateDictionaryValue(R"({
38445109440ce6618aa8bb5084466ba2c4f1a8e2660Alex Vakulenko    'base': {
385d91d625f29b752be035c5fb49bb29d7ee85fcb90Alex Vakulenko      'commands': {
386d91d625f29b752be035c5fb49bb29d7ee85fcb90Alex Vakulenko        'reboot': {
387d91d625f29b752be035c5fb49bb29d7ee85fcb90Alex Vakulenko          'parameters': {'delay': {'minimum': 10, 'type': 'integer'}},
388d91d625f29b752be035c5fb49bb29d7ee85fcb90Alex Vakulenko          'minimalRole': 'user'
389d91d625f29b752be035c5fb49bb29d7ee85fcb90Alex Vakulenko        }
390d91d625f29b752be035c5fb49bb29d7ee85fcb90Alex Vakulenko      },
391d91d625f29b752be035c5fb49bb29d7ee85fcb90Alex Vakulenko      'state': {
392d91d625f29b752be035c5fb49bb29d7ee85fcb90Alex Vakulenko        'firmwareVersion': {'type': 'string'}
39345109440ce6618aa8bb5084466ba2c4f1a8e2660Alex Vakulenko      }
39445109440ce6618aa8bb5084466ba2c4f1a8e2660Alex Vakulenko    },
39545109440ce6618aa8bb5084466ba2c4f1a8e2660Alex Vakulenko    'robot': {
396d91d625f29b752be035c5fb49bb29d7ee85fcb90Alex Vakulenko      'commands': {
397d91d625f29b752be035c5fb49bb29d7ee85fcb90Alex Vakulenko        '_jump': {
398d91d625f29b752be035c5fb49bb29d7ee85fcb90Alex Vakulenko          'parameters': {'_height': {'type': 'integer'}},
399d91d625f29b752be035c5fb49bb29d7ee85fcb90Alex Vakulenko          'minimalRole': 'user'
400d91d625f29b752be035c5fb49bb29d7ee85fcb90Alex Vakulenko        }
40145109440ce6618aa8bb5084466ba2c4f1a8e2660Alex Vakulenko      }
40245109440ce6618aa8bb5084466ba2c4f1a8e2660Alex Vakulenko    }
40345109440ce6618aa8bb5084466ba2c4f1a8e2660Alex Vakulenko  })");
404d91d625f29b752be035c5fb49bb29d7ee85fcb90Alex Vakulenko  EXPECT_TRUE(component_manager_.LoadTraits(*json_traits, nullptr));
40534668e731bb194b443bc0e6029d6d3583f08de28Vitaly Buka  EXPECT_TRUE(
40634668e731bb194b443bc0e6029d6d3583f08de28Vitaly Buka      component_manager_.AddComponent("", "comp", {"base", "robot"}, nullptr));
407d91d625f29b752be035c5fb49bb29d7ee85fcb90Alex Vakulenko  base::StringValue ver{"1.0"};
408d91d625f29b752be035c5fb49bb29d7ee85fcb90Alex Vakulenko  EXPECT_TRUE(component_manager_.SetStateProperty(
409d91d625f29b752be035c5fb49bb29d7ee85fcb90Alex Vakulenko      "comp", "base.firmwareVersion", ver, nullptr));
41045109440ce6618aa8bb5084466ba2c4f1a8e2660Alex Vakulenko
4111020618923f7bf3066c8d36bbfe0a855eb58a974Vitaly Buka  std::string ticket_url = dev_reg_->GetServiceURL("registrationTickets/") +
4121020618923f7bf3066c8d36bbfe0a855eb58a974Vitaly Buka                           test_data::kClaimTicketId;
4131a42e1466de3edd0c79215b739cd8e929ef8a7e8Vitaly Buka  EXPECT_CALL(http_client_,
4141a42e1466de3edd0c79215b739cd8e929ef8a7e8Vitaly Buka              SendRequest(HttpClient::Method::kPatch,
4151a42e1466de3edd0c79215b739cd8e929ef8a7e8Vitaly Buka                          ticket_url + "?key=" + test_data::kApiKey,
416747634273144e0df7b37475375ad4790b6a7b0e8Vitaly Buka                          HttpClient::Headers{GetJsonHeader()}, _, _))
41734668e731bb194b443bc0e6029d6d3583f08de28Vitaly Buka      .WillOnce(WithArgs<3, 4>(
41834668e731bb194b443bc0e6029d6d3583f08de28Vitaly Buka          Invoke([](const std::string& data,
41934668e731bb194b443bc0e6029d6d3583f08de28Vitaly Buka                    const HttpClient::SendRequestCallback& callback) {
42034668e731bb194b443bc0e6029d6d3583f08de28Vitaly Buka            auto json = test::CreateDictionaryValue(data);
42134668e731bb194b443bc0e6029d6d3583f08de28Vitaly Buka            EXPECT_NE(nullptr, json.get());
42234668e731bb194b443bc0e6029d6d3583f08de28Vitaly Buka            std::string value;
42334668e731bb194b443bc0e6029d6d3583f08de28Vitaly Buka            EXPECT_TRUE(json->GetString("id", &value));
42434668e731bb194b443bc0e6029d6d3583f08de28Vitaly Buka            EXPECT_EQ(test_data::kClaimTicketId, value);
42534668e731bb194b443bc0e6029d6d3583f08de28Vitaly Buka            EXPECT_TRUE(
42634668e731bb194b443bc0e6029d6d3583f08de28Vitaly Buka                json->GetString("deviceDraft.channel.supportedType", &value));
42734668e731bb194b443bc0e6029d6d3583f08de28Vitaly Buka            EXPECT_EQ("pull", value);
42834668e731bb194b443bc0e6029d6d3583f08de28Vitaly Buka            EXPECT_TRUE(json->GetString("oauthClientId", &value));
42934668e731bb194b443bc0e6029d6d3583f08de28Vitaly Buka            EXPECT_EQ(test_data::kClientId, value);
43034668e731bb194b443bc0e6029d6d3583f08de28Vitaly Buka            EXPECT_TRUE(json->GetString("deviceDraft.description", &value));
43134668e731bb194b443bc0e6029d6d3583f08de28Vitaly Buka            EXPECT_EQ("Easy to clean", value);
43234668e731bb194b443bc0e6029d6d3583f08de28Vitaly Buka            EXPECT_TRUE(json->GetString("deviceDraft.location", &value));
43334668e731bb194b443bc0e6029d6d3583f08de28Vitaly Buka            EXPECT_EQ("Kitchen", value);
43434668e731bb194b443bc0e6029d6d3583f08de28Vitaly Buka            EXPECT_TRUE(json->GetString("deviceDraft.modelManifestId", &value));
43534668e731bb194b443bc0e6029d6d3583f08de28Vitaly Buka            EXPECT_EQ("AAAAA", value);
43634668e731bb194b443bc0e6029d6d3583f08de28Vitaly Buka            EXPECT_TRUE(json->GetString("deviceDraft.name", &value));
43734668e731bb194b443bc0e6029d6d3583f08de28Vitaly Buka            EXPECT_EQ("Coffee Pot", value);
43834668e731bb194b443bc0e6029d6d3583f08de28Vitaly Buka            base::DictionaryValue* dict = nullptr;
4398d0cfefae24985025a934ea5461a51472c59cfc0Alex Vakulenko            EXPECT_FALSE(json->GetDictionary("deviceDraft.commandDefs", &dict));
4408d0cfefae24985025a934ea5461a51472c59cfc0Alex Vakulenko            EXPECT_FALSE(json->GetDictionary("deviceDraft.state", &dict));
44134668e731bb194b443bc0e6029d6d3583f08de28Vitaly Buka            EXPECT_TRUE(json->GetDictionary("deviceDraft.traits", &dict));
44234668e731bb194b443bc0e6029d6d3583f08de28Vitaly Buka            auto expectedTraits = R"({
4438d0cfefae24985025a934ea5461a51472c59cfc0Alex Vakulenko              'base': {
4448d0cfefae24985025a934ea5461a51472c59cfc0Alex Vakulenko                'commands': {
4458d0cfefae24985025a934ea5461a51472c59cfc0Alex Vakulenko                  'reboot': {
4468d0cfefae24985025a934ea5461a51472c59cfc0Alex Vakulenko                    'parameters': {'delay': {'minimum': 10, 'type': 'integer'}},
4478d0cfefae24985025a934ea5461a51472c59cfc0Alex Vakulenko                    'minimalRole': 'user'
4488d0cfefae24985025a934ea5461a51472c59cfc0Alex Vakulenko                  }
4498d0cfefae24985025a934ea5461a51472c59cfc0Alex Vakulenko                },
4508d0cfefae24985025a934ea5461a51472c59cfc0Alex Vakulenko                'state': {
4518d0cfefae24985025a934ea5461a51472c59cfc0Alex Vakulenko                  'firmwareVersion': {'type': 'string'}
452d91d625f29b752be035c5fb49bb29d7ee85fcb90Alex Vakulenko                }
453d91d625f29b752be035c5fb49bb29d7ee85fcb90Alex Vakulenko              },
4548d0cfefae24985025a934ea5461a51472c59cfc0Alex Vakulenko              'robot': {
4558d0cfefae24985025a934ea5461a51472c59cfc0Alex Vakulenko                'commands': {
4568d0cfefae24985025a934ea5461a51472c59cfc0Alex Vakulenko                  '_jump': {
4578d0cfefae24985025a934ea5461a51472c59cfc0Alex Vakulenko                    'parameters': {'_height': {'type': 'integer'}},
4588d0cfefae24985025a934ea5461a51472c59cfc0Alex Vakulenko                    'minimalRole': 'user'
4598d0cfefae24985025a934ea5461a51472c59cfc0Alex Vakulenko                  }
460d91d625f29b752be035c5fb49bb29d7ee85fcb90Alex Vakulenko                }
461d91d625f29b752be035c5fb49bb29d7ee85fcb90Alex Vakulenko              }
4628d0cfefae24985025a934ea5461a51472c59cfc0Alex Vakulenko            })";
46334668e731bb194b443bc0e6029d6d3583f08de28Vitaly Buka            EXPECT_JSON_EQ(expectedTraits, *dict);
464d91d625f29b752be035c5fb49bb29d7ee85fcb90Alex Vakulenko
46534668e731bb194b443bc0e6029d6d3583f08de28Vitaly Buka            EXPECT_TRUE(json->GetDictionary("deviceDraft.components", &dict));
46634668e731bb194b443bc0e6029d6d3583f08de28Vitaly Buka            auto expectedComponents = R"({
4678d0cfefae24985025a934ea5461a51472c59cfc0Alex Vakulenko              'comp': {
4688d0cfefae24985025a934ea5461a51472c59cfc0Alex Vakulenko                'traits': ['base', 'robot'],
4698d0cfefae24985025a934ea5461a51472c59cfc0Alex Vakulenko                'state': {
4708d0cfefae24985025a934ea5461a51472c59cfc0Alex Vakulenko                  'base': { 'firmwareVersion': '1.0' }
4718d0cfefae24985025a934ea5461a51472c59cfc0Alex Vakulenko                }
472d91d625f29b752be035c5fb49bb29d7ee85fcb90Alex Vakulenko              }
4738d0cfefae24985025a934ea5461a51472c59cfc0Alex Vakulenko            })";
47434668e731bb194b443bc0e6029d6d3583f08de28Vitaly Buka            EXPECT_JSON_EQ(expectedComponents, *dict);
47534668e731bb194b443bc0e6029d6d3583f08de28Vitaly Buka
47634668e731bb194b443bc0e6029d6d3583f08de28Vitaly Buka            base::DictionaryValue json_resp;
47734668e731bb194b443bc0e6029d6d3583f08de28Vitaly Buka            json_resp.SetString("id", test_data::kClaimTicketId);
47834668e731bb194b443bc0e6029d6d3583f08de28Vitaly Buka            json_resp.SetString("kind", "weave#registrationTicket");
47934668e731bb194b443bc0e6029d6d3583f08de28Vitaly Buka            json_resp.SetString("oauthClientId", test_data::kClientId);
48034668e731bb194b443bc0e6029d6d3583f08de28Vitaly Buka            base::DictionaryValue* device_draft = nullptr;
48134668e731bb194b443bc0e6029d6d3583f08de28Vitaly Buka            EXPECT_TRUE(json->GetDictionary("deviceDraft", &device_draft));
48234668e731bb194b443bc0e6029d6d3583f08de28Vitaly Buka            device_draft = device_draft->DeepCopy();
48334668e731bb194b443bc0e6029d6d3583f08de28Vitaly Buka            device_draft->SetString("id", test_data::kCloudId);
48434668e731bb194b443bc0e6029d6d3583f08de28Vitaly Buka            device_draft->SetString("kind", "weave#device");
48534668e731bb194b443bc0e6029d6d3583f08de28Vitaly Buka            json_resp.Set("deviceDraft", device_draft);
48634668e731bb194b443bc0e6029d6d3583f08de28Vitaly Buka
48734668e731bb194b443bc0e6029d6d3583f08de28Vitaly Buka            callback.Run(ReplyWithJson(200, json_resp), nullptr);
48834668e731bb194b443bc0e6029d6d3583f08de28Vitaly Buka          })));
4891020618923f7bf3066c8d36bbfe0a855eb58a974Vitaly Buka
4901020618923f7bf3066c8d36bbfe0a855eb58a974Vitaly Buka  EXPECT_CALL(http_client_,
4911a42e1466de3edd0c79215b739cd8e929ef8a7e8Vitaly Buka              SendRequest(HttpClient::Method::kPost,
49217280378dc037c09342604c2a75dddbc669706f2Vitaly Buka                          ticket_url + "/finalize?key=" + test_data::kApiKey,
493747634273144e0df7b37475375ad4790b6a7b0e8Vitaly Buka                          HttpClient::Headers{}, _, _))
494747634273144e0df7b37475375ad4790b6a7b0e8Vitaly Buka      .WillOnce(WithArgs<4>(
495747634273144e0df7b37475375ad4790b6a7b0e8Vitaly Buka          Invoke([](const HttpClient::SendRequestCallback& callback) {
49617280378dc037c09342604c2a75dddbc669706f2Vitaly Buka            base::DictionaryValue json;
49717280378dc037c09342604c2a75dddbc669706f2Vitaly Buka            json.SetString("id", test_data::kClaimTicketId);
49888272d5b9e88dfd253c18aea4792fe57ee51696dVitaly Buka            json.SetString("kind", "weave#registrationTicket");
49917280378dc037c09342604c2a75dddbc669706f2Vitaly Buka            json.SetString("oauthClientId", test_data::kClientId);
50017280378dc037c09342604c2a75dddbc669706f2Vitaly Buka            json.SetString("userEmail", "user@email.com");
5016a9d0e2cd473382d37a2cf11acdfa63c1038392eVitaly Buka            json.SetString("deviceDraft.id", test_data::kCloudId);
50288272d5b9e88dfd253c18aea4792fe57ee51696dVitaly Buka            json.SetString("deviceDraft.kind", "weave#device");
50317280378dc037c09342604c2a75dddbc669706f2Vitaly Buka            json.SetString("deviceDraft.channel.supportedType", "xmpp");
50417280378dc037c09342604c2a75dddbc669706f2Vitaly Buka            json.SetString("robotAccountEmail", test_data::kRobotAccountEmail);
50517280378dc037c09342604c2a75dddbc669706f2Vitaly Buka            json.SetString("robotAccountAuthorizationCode",
50617280378dc037c09342604c2a75dddbc669706f2Vitaly Buka                           test_data::kRobotAccountAuthCode);
507747634273144e0df7b37475375ad4790b6a7b0e8Vitaly Buka            callback.Run(ReplyWithJson(200, json), nullptr);
50817280378dc037c09342604c2a75dddbc669706f2Vitaly Buka          })));
5091020618923f7bf3066c8d36bbfe0a855eb58a974Vitaly Buka
5101a42e1466de3edd0c79215b739cd8e929ef8a7e8Vitaly Buka  EXPECT_CALL(
5111a42e1466de3edd0c79215b739cd8e929ef8a7e8Vitaly Buka      http_client_,
5121a42e1466de3edd0c79215b739cd8e929ef8a7e8Vitaly Buka      SendRequest(HttpClient::Method::kPost, dev_reg_->GetOAuthURL("token"),
513747634273144e0df7b37475375ad4790b6a7b0e8Vitaly Buka                  HttpClient::Headers{GetFormHeader()}, _, _))
51417280378dc037c09342604c2a75dddbc669706f2Vitaly Buka      .WillOnce(WithArgs<3, 4>(Invoke([](
51517280378dc037c09342604c2a75dddbc669706f2Vitaly Buka          const std::string& data,
516747634273144e0df7b37475375ad4790b6a7b0e8Vitaly Buka          const HttpClient::SendRequestCallback& callback) {
5171020618923f7bf3066c8d36bbfe0a855eb58a974Vitaly Buka        EXPECT_EQ("authorization_code", GetFormField(data, "grant_type"));
5181020618923f7bf3066c8d36bbfe0a855eb58a974Vitaly Buka        EXPECT_EQ(test_data::kRobotAccountAuthCode, GetFormField(data, "code"));
5191020618923f7bf3066c8d36bbfe0a855eb58a974Vitaly Buka        EXPECT_EQ(test_data::kClientId, GetFormField(data, "client_id"));
5201020618923f7bf3066c8d36bbfe0a855eb58a974Vitaly Buka        EXPECT_EQ(test_data::kClientSecret,
5211020618923f7bf3066c8d36bbfe0a855eb58a974Vitaly Buka                  GetFormField(data, "client_secret"));
5221020618923f7bf3066c8d36bbfe0a855eb58a974Vitaly Buka        EXPECT_EQ("oob", GetFormField(data, "redirect_uri"));
5231020618923f7bf3066c8d36bbfe0a855eb58a974Vitaly Buka
5241020618923f7bf3066c8d36bbfe0a855eb58a974Vitaly Buka        base::DictionaryValue json;
5251020618923f7bf3066c8d36bbfe0a855eb58a974Vitaly Buka        json.SetString("access_token", test_data::kAccessToken);
5261020618923f7bf3066c8d36bbfe0a855eb58a974Vitaly Buka        json.SetString("token_type", "Bearer");
5271020618923f7bf3066c8d36bbfe0a855eb58a974Vitaly Buka        json.SetString("refresh_token", test_data::kRefreshToken);
5281020618923f7bf3066c8d36bbfe0a855eb58a974Vitaly Buka        json.SetInteger("expires_in", 3600);
5291020618923f7bf3066c8d36bbfe0a855eb58a974Vitaly Buka
530747634273144e0df7b37475375ad4790b6a7b0e8Vitaly Buka        callback.Run(ReplyWithJson(200, json), nullptr);
5311020618923f7bf3066c8d36bbfe0a855eb58a974Vitaly Buka      })));
5321020618923f7bf3066c8d36bbfe0a855eb58a974Vitaly Buka
53372d8d1611efb8c0dd87d466e971bea9468b7c3a1Vitaly Buka  EXPECT_CALL(
53472d8d1611efb8c0dd87d466e971bea9468b7c3a1Vitaly Buka      http_client_,
53572d8d1611efb8c0dd87d466e971bea9468b7c3a1Vitaly Buka      SendRequest(HttpClient::Method::kPost, HasSubstr("upsertLocalAuthInfo"),
53672d8d1611efb8c0dd87d466e971bea9468b7c3a1Vitaly Buka                  HttpClient::Headers{GetAuthHeader(), GetJsonHeader()}, _, _))
53772d8d1611efb8c0dd87d466e971bea9468b7c3a1Vitaly Buka      .WillOnce(WithArgs<3, 4>(
53872d8d1611efb8c0dd87d466e971bea9468b7c3a1Vitaly Buka          Invoke([](const std::string& data,
53972d8d1611efb8c0dd87d466e971bea9468b7c3a1Vitaly Buka                    const HttpClient::SendRequestCallback& callback) {
54029bc59330bec58e43df1050bee279819b54e7c6eVitaly Buka            auto dict = CreateDictionaryValue(data);
541f3fd9c30d383b8f0fc4d4d6cefd172a5fa1200c4Vitaly Buka            EXPECT_TRUE(dict->Remove("localAuthInfo.clientToken", nullptr));
54229bc59330bec58e43df1050bee279819b54e7c6eVitaly Buka            EXPECT_JSON_EQ(test_data::kAuthInfo, *dict);
54372d8d1611efb8c0dd87d466e971bea9468b7c3a1Vitaly Buka            base::DictionaryValue json;
54472d8d1611efb8c0dd87d466e971bea9468b7c3a1Vitaly Buka            callback.Run(ReplyWithJson(200, json), nullptr);
54572d8d1611efb8c0dd87d466e971bea9468b7c3a1Vitaly Buka          })));
54672d8d1611efb8c0dd87d466e971bea9468b7c3a1Vitaly Buka
54712870bd07dd3c8f44528638a9c290b72e22d32d2Vitaly Buka  bool done = false;
54812870bd07dd3c8f44528638a9c290b72e22d32d2Vitaly Buka  dev_reg_->RegisterDevice(
549747634273144e0df7b37475375ad4790b6a7b0e8Vitaly Buka      test_data::kClaimTicketId, base::Bind([this, &done](ErrorPtr error) {
550747634273144e0df7b37475375ad4790b6a7b0e8Vitaly Buka        EXPECT_FALSE(error);
55112870bd07dd3c8f44528638a9c290b72e22d32d2Vitaly Buka        done = true;
55212870bd07dd3c8f44528638a9c290b72e22d32d2Vitaly Buka        task_runner_.Break();
55312870bd07dd3c8f44528638a9c290b72e22d32d2Vitaly Buka        EXPECT_EQ(GcdState::kConnecting, GetGcdState());
55412870bd07dd3c8f44528638a9c290b72e22d32d2Vitaly Buka
55512870bd07dd3c8f44528638a9c290b72e22d32d2Vitaly Buka        // Validate the device info saved to storage...
5566a9d0e2cd473382d37a2cf11acdfa63c1038392eVitaly Buka        EXPECT_EQ(test_data::kCloudId, dev_reg_->GetSettings().cloud_id);
55712870bd07dd3c8f44528638a9c290b72e22d32d2Vitaly Buka        EXPECT_EQ(test_data::kRefreshToken,
55812870bd07dd3c8f44528638a9c290b72e22d32d2Vitaly Buka                  dev_reg_->GetSettings().refresh_token);
55912870bd07dd3c8f44528638a9c290b72e22d32d2Vitaly Buka        EXPECT_EQ(test_data::kRobotAccountEmail,
5600a8ab9973e1fdf6b41d8f7b49529c9bd97a9071cVitaly Buka                  dev_reg_->GetSettings().robot_account);
5610a8ab9973e1fdf6b41d8f7b49529c9bd97a9071cVitaly Buka      }));
5620a8ab9973e1fdf6b41d8f7b49529c9bd97a9071cVitaly Buka  task_runner_.Run();
5630a8ab9973e1fdf6b41d8f7b49529c9bd97a9071cVitaly Buka  EXPECT_TRUE(done);
5640a8ab9973e1fdf6b41d8f7b49529c9bd97a9071cVitaly Buka}
5650a8ab9973e1fdf6b41d8f7b49529c9bd97a9071cVitaly Buka
5660a8ab9973e1fdf6b41d8f7b49529c9bd97a9071cVitaly BukaTEST_F(DeviceRegistrationInfoTest, ReRegisterDevice) {
5670a8ab9973e1fdf6b41d8f7b49529c9bd97a9071cVitaly Buka  ReloadSettings();
5680a8ab9973e1fdf6b41d8f7b49529c9bd97a9071cVitaly Buka
5690a8ab9973e1fdf6b41d8f7b49529c9bd97a9071cVitaly Buka  bool done = false;
5700a8ab9973e1fdf6b41d8f7b49529c9bd97a9071cVitaly Buka  dev_reg_->RegisterDevice(
5710a8ab9973e1fdf6b41d8f7b49529c9bd97a9071cVitaly Buka      test_data::kClaimTicketId, base::Bind([this, &done](ErrorPtr error) {
57248a8669ddc2e8d785aad9ad18a5abbf8f1224fdeVitaly Buka        EXPECT_TRUE(error->HasError("already_registered"));
5730a8ab9973e1fdf6b41d8f7b49529c9bd97a9071cVitaly Buka        done = true;
5740a8ab9973e1fdf6b41d8f7b49529c9bd97a9071cVitaly Buka        task_runner_.Break();
5750a8ab9973e1fdf6b41d8f7b49529c9bd97a9071cVitaly Buka        EXPECT_EQ(GcdState::kConnecting, GetGcdState());
5760a8ab9973e1fdf6b41d8f7b49529c9bd97a9071cVitaly Buka
5770a8ab9973e1fdf6b41d8f7b49529c9bd97a9071cVitaly Buka        // Validate the device info saved to storage...
5780a8ab9973e1fdf6b41d8f7b49529c9bd97a9071cVitaly Buka        EXPECT_EQ(test_data::kCloudId, dev_reg_->GetSettings().cloud_id);
5790a8ab9973e1fdf6b41d8f7b49529c9bd97a9071cVitaly Buka        EXPECT_EQ(test_data::kRefreshToken,
5800a8ab9973e1fdf6b41d8f7b49529c9bd97a9071cVitaly Buka                  dev_reg_->GetSettings().refresh_token);
5810a8ab9973e1fdf6b41d8f7b49529c9bd97a9071cVitaly Buka        EXPECT_EQ(test_data::kRobotAccountEmail,
58212870bd07dd3c8f44528638a9c290b72e22d32d2Vitaly Buka                  dev_reg_->GetSettings().robot_account);
583747634273144e0df7b37475375ad4790b6a7b0e8Vitaly Buka      }));
58412870bd07dd3c8f44528638a9c290b72e22d32d2Vitaly Buka  task_runner_.Run();
58512870bd07dd3c8f44528638a9c290b72e22d32d2Vitaly Buka  EXPECT_TRUE(done);
5868e34d391dada2fc3255fecd724f6302e7952be51Alex Vakulenko}
5878e34d391dada2fc3255fecd724f6302e7952be51Alex Vakulenko
588c900e48b8d482b1462a4d262856e344d22bcc6a5Christopher WileyTEST_F(DeviceRegistrationInfoTest, OOBRegistrationStatus) {
5891020618923f7bf3066c8d36bbfe0a855eb58a974Vitaly Buka  // After we've been initialized, we should be either offline or
5901020618923f7bf3066c8d36bbfe0a855eb58a974Vitaly Buka  // unregistered, depending on whether or not we've found credentials.
591c3c6dab99bb333417756817d154cd99ae71f4668Vitaly Buka  EXPECT_EQ(GcdState::kUnconfigured, GetGcdState());
592c900e48b8d482b1462a4d262856e344d22bcc6a5Christopher Wiley  // Put some credentials into our state, make sure we call that offline.
593c11a17d59330e6356f9da62e5b4a7ecf6a726665Vitaly Buka  ReloadSettings();
594c3c6dab99bb333417756817d154cd99ae71f4668Vitaly Buka  EXPECT_EQ(GcdState::kConnecting, GetGcdState());
595c900e48b8d482b1462a4d262856e344d22bcc6a5Christopher Wiley}
596c900e48b8d482b1462a4d262856e344d22bcc6a5Christopher Wiley
59747a1f6f5afe3df14fb7db35d4be56c93ff742c22Vitaly Bukaclass DeviceRegistrationInfoUpdateCommandTest
59847a1f6f5afe3df14fb7db35d4be56c93ff742c22Vitaly Buka    : public DeviceRegistrationInfoTest {
59947a1f6f5afe3df14fb7db35d4be56c93ff742c22Vitaly Buka protected:
60047a1f6f5afe3df14fb7db35d4be56c93ff742c22Vitaly Buka  void SetUp() override {
60147a1f6f5afe3df14fb7db35d4be56c93ff742c22Vitaly Buka    DeviceRegistrationInfoTest::SetUp();
60247a1f6f5afe3df14fb7db35d4be56c93ff742c22Vitaly Buka
60347a1f6f5afe3df14fb7db35d4be56c93ff742c22Vitaly Buka    ReloadSettings();
60447a1f6f5afe3df14fb7db35d4be56c93ff742c22Vitaly Buka    SetAccessToken();
60547a1f6f5afe3df14fb7db35d4be56c93ff742c22Vitaly Buka
606d91d625f29b752be035c5fb49bb29d7ee85fcb90Alex Vakulenko    auto json_traits = CreateDictionaryValue(R"({
60747a1f6f5afe3df14fb7db35d4be56c93ff742c22Vitaly Buka      'robot': {
608d91d625f29b752be035c5fb49bb29d7ee85fcb90Alex Vakulenko        'commands': {
609d91d625f29b752be035c5fb49bb29d7ee85fcb90Alex Vakulenko          '_jump': {
610d91d625f29b752be035c5fb49bb29d7ee85fcb90Alex Vakulenko            'parameters': {'_height': 'integer'},
611d91d625f29b752be035c5fb49bb29d7ee85fcb90Alex Vakulenko            'progress': {'progress': 'integer'},
612d91d625f29b752be035c5fb49bb29d7ee85fcb90Alex Vakulenko            'results': {'status': 'string'},
613d91d625f29b752be035c5fb49bb29d7ee85fcb90Alex Vakulenko            'minimalRole': 'user'
614d91d625f29b752be035c5fb49bb29d7ee85fcb90Alex Vakulenko          }
61547a1f6f5afe3df14fb7db35d4be56c93ff742c22Vitaly Buka        }
6169e2f8cda5fb177d7dc8d43011eea3829427e34cdAlex Vakulenko      }
61747a1f6f5afe3df14fb7db35d4be56c93ff742c22Vitaly Buka    })");
618d91d625f29b752be035c5fb49bb29d7ee85fcb90Alex Vakulenko    EXPECT_TRUE(component_manager_.LoadTraits(*json_traits, nullptr));
61934668e731bb194b443bc0e6029d6d3583f08de28Vitaly Buka    EXPECT_TRUE(
62034668e731bb194b443bc0e6029d6d3583f08de28Vitaly Buka        component_manager_.AddComponent("", "comp", {"robot"}, nullptr));
62147a1f6f5afe3df14fb7db35d4be56c93ff742c22Vitaly Buka
62247a1f6f5afe3df14fb7db35d4be56c93ff742c22Vitaly Buka    command_url_ = dev_reg_->GetServiceURL("commands/1234");
62347a1f6f5afe3df14fb7db35d4be56c93ff742c22Vitaly Buka
62447a1f6f5afe3df14fb7db35d4be56c93ff742c22Vitaly Buka    auto commands_json = CreateValue(R"([{
62547a1f6f5afe3df14fb7db35d4be56c93ff742c22Vitaly Buka      'name':'robot._jump',
626d91d625f29b752be035c5fb49bb29d7ee85fcb90Alex Vakulenko      'component': 'comp',
62747a1f6f5afe3df14fb7db35d4be56c93ff742c22Vitaly Buka      'id':'1234',
62847a1f6f5afe3df14fb7db35d4be56c93ff742c22Vitaly Buka      'parameters': {'_height': 100},
62947a1f6f5afe3df14fb7db35d4be56c93ff742c22Vitaly Buka      'minimalRole': 'user'
63047a1f6f5afe3df14fb7db35d4be56c93ff742c22Vitaly Buka    }])");
63147a1f6f5afe3df14fb7db35d4be56c93ff742c22Vitaly Buka    ASSERT_NE(nullptr, commands_json.get());
63247a1f6f5afe3df14fb7db35d4be56c93ff742c22Vitaly Buka    const base::ListValue* command_list = nullptr;
63347a1f6f5afe3df14fb7db35d4be56c93ff742c22Vitaly Buka    ASSERT_TRUE(commands_json->GetAsList(&command_list));
63447a1f6f5afe3df14fb7db35d4be56c93ff742c22Vitaly Buka    PublishCommands(*command_list);
635d91d625f29b752be035c5fb49bb29d7ee85fcb90Alex Vakulenko    command_ = component_manager_.FindCommand("1234");
63647a1f6f5afe3df14fb7db35d4be56c93ff742c22Vitaly Buka    ASSERT_NE(nullptr, command_);
63747a1f6f5afe3df14fb7db35d4be56c93ff742c22Vitaly Buka  }
6389e2f8cda5fb177d7dc8d43011eea3829427e34cdAlex Vakulenko
639ff1d1862455e0e1aea2dffedf505eea5fdce2c6cVitaly Buka  void TearDown() override {
640ff1d1862455e0e1aea2dffedf505eea5fdce2c6cVitaly Buka    task_runner_.RunOnce();
641ff1d1862455e0e1aea2dffedf505eea5fdce2c6cVitaly Buka    DeviceRegistrationInfoTest::TearDown();
642ff1d1862455e0e1aea2dffedf505eea5fdce2c6cVitaly Buka  }
643ff1d1862455e0e1aea2dffedf505eea5fdce2c6cVitaly Buka
64447a1f6f5afe3df14fb7db35d4be56c93ff742c22Vitaly Buka  Command* command_{nullptr};
64547a1f6f5afe3df14fb7db35d4be56c93ff742c22Vitaly Buka  std::string command_url_;
64647a1f6f5afe3df14fb7db35d4be56c93ff742c22Vitaly Buka};
6479e2f8cda5fb177d7dc8d43011eea3829427e34cdAlex Vakulenko
64847a1f6f5afe3df14fb7db35d4be56c93ff742c22Vitaly BukaTEST_F(DeviceRegistrationInfoUpdateCommandTest, SetProgress) {
649747634273144e0df7b37475375ad4790b6a7b0e8Vitaly Buka  EXPECT_CALL(
650747634273144e0df7b37475375ad4790b6a7b0e8Vitaly Buka      http_client_,
651747634273144e0df7b37475375ad4790b6a7b0e8Vitaly Buka      SendRequest(HttpClient::Method::kPatch, command_url_,
652747634273144e0df7b37475375ad4790b6a7b0e8Vitaly Buka                  HttpClient::Headers{GetAuthHeader(), GetJsonHeader()}, _, _))
65317280378dc037c09342604c2a75dddbc669706f2Vitaly Buka      .WillOnce(WithArgs<3, 4>(Invoke([](
65417280378dc037c09342604c2a75dddbc669706f2Vitaly Buka          const std::string& data,
655747634273144e0df7b37475375ad4790b6a7b0e8Vitaly Buka          const HttpClient::SendRequestCallback& callback) {
65617280378dc037c09342604c2a75dddbc669706f2Vitaly Buka        EXPECT_JSON_EQ((R"({"state":"inProgress","progress":{"progress":18}})"),
6571020618923f7bf3066c8d36bbfe0a855eb58a974Vitaly Buka                       *CreateDictionaryValue(data));
6581020618923f7bf3066c8d36bbfe0a855eb58a974Vitaly Buka        base::DictionaryValue json;
659747634273144e0df7b37475375ad4790b6a7b0e8Vitaly Buka        callback.Run(ReplyWithJson(200, json), nullptr);
6601020618923f7bf3066c8d36bbfe0a855eb58a974Vitaly Buka      })));
66147a1f6f5afe3df14fb7db35d4be56c93ff742c22Vitaly Buka  EXPECT_TRUE(command_->SetProgress(*CreateDictionaryValue("{'progress':18}"),
66247a1f6f5afe3df14fb7db35d4be56c93ff742c22Vitaly Buka                                    nullptr));
66347a1f6f5afe3df14fb7db35d4be56c93ff742c22Vitaly Buka}
6641020618923f7bf3066c8d36bbfe0a855eb58a974Vitaly Buka
6652f54897f368f71486753f7fef7172a89477fc272Vitaly BukaTEST_F(DeviceRegistrationInfoUpdateCommandTest, Complete) {
666747634273144e0df7b37475375ad4790b6a7b0e8Vitaly Buka  EXPECT_CALL(
667747634273144e0df7b37475375ad4790b6a7b0e8Vitaly Buka      http_client_,
668747634273144e0df7b37475375ad4790b6a7b0e8Vitaly Buka      SendRequest(HttpClient::Method::kPatch, command_url_,
669747634273144e0df7b37475375ad4790b6a7b0e8Vitaly Buka                  HttpClient::Headers{GetAuthHeader(), GetJsonHeader()}, _, _))
670f0a3b2243db08f65f155a3d8e81a6a544fa54f1dVitaly Buka      .WillOnce(WithArgs<3, 4>(
671f0a3b2243db08f65f155a3d8e81a6a544fa54f1dVitaly Buka          Invoke([](const std::string& data,
672f0a3b2243db08f65f155a3d8e81a6a544fa54f1dVitaly Buka                    const HttpClient::SendRequestCallback& callback) {
673f0a3b2243db08f65f155a3d8e81a6a544fa54f1dVitaly Buka            EXPECT_JSON_EQ(R"({"state":"done", "results":{"status":"Ok"}})",
674f0a3b2243db08f65f155a3d8e81a6a544fa54f1dVitaly Buka                           *CreateDictionaryValue(data));
675f0a3b2243db08f65f155a3d8e81a6a544fa54f1dVitaly Buka            base::DictionaryValue json;
676f0a3b2243db08f65f155a3d8e81a6a544fa54f1dVitaly Buka            callback.Run(ReplyWithJson(200, json), nullptr);
677f0a3b2243db08f65f155a3d8e81a6a544fa54f1dVitaly Buka          })));
6782f54897f368f71486753f7fef7172a89477fc272Vitaly Buka  EXPECT_TRUE(
6792f54897f368f71486753f7fef7172a89477fc272Vitaly Buka      command_->Complete(*CreateDictionaryValue("{'status': 'Ok'}"), nullptr));
68047a1f6f5afe3df14fb7db35d4be56c93ff742c22Vitaly Buka}
6811020618923f7bf3066c8d36bbfe0a855eb58a974Vitaly Buka
68247a1f6f5afe3df14fb7db35d4be56c93ff742c22Vitaly BukaTEST_F(DeviceRegistrationInfoUpdateCommandTest, Cancel) {
683747634273144e0df7b37475375ad4790b6a7b0e8Vitaly Buka  EXPECT_CALL(
684747634273144e0df7b37475375ad4790b6a7b0e8Vitaly Buka      http_client_,
685747634273144e0df7b37475375ad4790b6a7b0e8Vitaly Buka      SendRequest(HttpClient::Method::kPatch, command_url_,
686747634273144e0df7b37475375ad4790b6a7b0e8Vitaly Buka                  HttpClient::Headers{GetAuthHeader(), GetJsonHeader()}, _, _))
68734668e731bb194b443bc0e6029d6d3583f08de28Vitaly Buka      .WillOnce(WithArgs<3, 4>(
68834668e731bb194b443bc0e6029d6d3583f08de28Vitaly Buka          Invoke([](const std::string& data,
68934668e731bb194b443bc0e6029d6d3583f08de28Vitaly Buka                    const HttpClient::SendRequestCallback& callback) {
69034668e731bb194b443bc0e6029d6d3583f08de28Vitaly Buka            EXPECT_JSON_EQ(R"({"state":"cancelled"})",
69134668e731bb194b443bc0e6029d6d3583f08de28Vitaly Buka                           *CreateDictionaryValue(data));
69234668e731bb194b443bc0e6029d6d3583f08de28Vitaly Buka            base::DictionaryValue json;
69334668e731bb194b443bc0e6029d6d3583f08de28Vitaly Buka            callback.Run(ReplyWithJson(200, json), nullptr);
69434668e731bb194b443bc0e6029d6d3583f08de28Vitaly Buka          })));
69547a1f6f5afe3df14fb7db35d4be56c93ff742c22Vitaly Buka  EXPECT_TRUE(command_->Cancel(nullptr));
6969e2f8cda5fb177d7dc8d43011eea3829427e34cdAlex Vakulenko}
6979e2f8cda5fb177d7dc8d43011eea3829427e34cdAlex Vakulenko
698b6f015a1ef3caffbc2af53184c0ec5342e42e048Vitaly Buka}  // namespace weave
699