// Copyright 2014 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 "buffet/device_registration_info.h"

#include <base/json/json_reader.h>
#include <base/json/json_writer.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 "buffet/commands/command_manager.h"
#include "buffet/commands/unittest_utils.h"
#include "buffet/device_registration_storage_keys.h"
#include "buffet/states/mock_state_change_queue_interface.h"
#include "buffet/states/state_manager.h"
#include "buffet/storage_impls.h"

namespace buffet {

using chromeos::http::request_header::kAuthorization;
using chromeos::http::fake::ServerRequest;
using chromeos::http::fake::ServerResponse;

namespace {

namespace test_data {

const char kServiceURL[]           = "http://gcd.server.com/";
const char kOAuthURL[]             = "http://oauth.server.com/";
const char kApiKey[]               = "GOadRdTf9FERf0k4w6EFOof56fUJ3kFDdFL3d7f";
const char kClientId[]             = "123543821385-sfjkjshdkjhfk234sdfsdfkskd"
                                     "fkjh7f.apps.googleusercontent.com";
const char kClientSecret[]         = "5sdGdGlfolGlrFKfdFlgP6FG";
const char kDeviceId[]             = "4a7ea2d1-b331-1e1f-b206-e863c7635196";
const char kClaimTicketId[]        = "RTcUE";
const char kAccessToken[]          = "ya29.1.AADtN_V-dLUM-sVZ0qVjG9Dxm5NgdS9J"
                                     "Mx_JLUqhC9bED_YFjzHZtYt65ZzXCS35NMAeaVZ"
                                     "Dei530-w0yE2urpQ";
const char kRefreshToken[]         = "1/zQmxR6PKNvhcxf9SjXUrCjcmCrcqRKXctc6cp"
                                     "1nI-GQ";
const char kRobotAccountAuthCode[] = "4/Mf_ujEhPejVhOq-OxW9F5cSOnWzx."
                                     "YgciVjTYGscRshQV0ieZDAqiTIjMigI";
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.
void SetDefaultDeviceRegistration(base::DictionaryValue* data) {
  data->SetString(storage_keys::kRefreshToken, test_data::kRefreshToken);
  data->SetString(storage_keys::kDeviceId, test_data::kDeviceId);
  data->SetString(storage_keys::kRobotAccount, 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";
  }
  json.SetInteger("expires_in", 3600);
  response->ReplyJson(chromeos::http::status_code::Ok, &json);
}

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);
}

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},
  });
}

}  // anonymous namespace

// This is a helper class that allows the unit tests to access private
// methods and data since TestHelper is declared as a friend to
// DeviceRegistrationInfo.
class DeviceRegistrationInfo::TestHelper {
 public:
  static bool Save(DeviceRegistrationInfo* info) {
    return info->Save();
  }

  static void PublishCommands(DeviceRegistrationInfo* info,
                              const base::ListValue& commands) {
    return info->PublishCommands(commands);
  }

  static bool CheckRegistration(DeviceRegistrationInfo* info,
                                chromeos::ErrorPtr* error) {
    return info->CheckRegistration(error);
  }
};

class DeviceRegistrationInfoTest : public ::testing::Test {
 protected:
  void SetUp() override {
    storage_ = std::make_shared<MemStorage>();
    storage_->Save(&data_);
    transport_ = std::make_shared<chromeos::http::fake::Transport>();
    command_manager_ = std::make_shared<CommandManager>(nullptr);
    state_manager_ = std::make_shared<StateManager>(&mock_state_change_queue_);
    chromeos::KeyValueStore config_store;
    config_store.SetString("client_id", test_data::kClientId);
    config_store.SetString("client_secret", test_data::kClientSecret);
    config_store.SetString("api_key", test_data::kApiKey);
    config_store.SetString("device_kind",  "vendor");
    config_store.SetString("name",  "Coffee Pot");
    config_store.SetString("description", "Easy to clean");
    config_store.SetString("location", "Kitchen");
    config_store.SetString("anonymous_access_role", "viewer");
    config_store.SetString("model_id", "AAAAA");
    config_store.SetString("oauth_url", test_data::kOAuthURL);
    config_store.SetString("service_url", test_data::kServiceURL);
    std::unique_ptr<BuffetConfig> config{new BuffetConfig};
    config->Load(config_store);
    dev_reg_ = std::unique_ptr<DeviceRegistrationInfo>(
        new DeviceRegistrationInfo(command_manager_, state_manager_,
                                   std::move(config),
                                   transport_, storage_,
                                   true,
                                   nullptr));
  }

  base::DictionaryValue data_;
  std::shared_ptr<MemStorage> storage_;
  std::shared_ptr<chromeos::http::fake::Transport> transport_;
  std::unique_ptr<DeviceRegistrationInfo> dev_reg_;
  std::shared_ptr<CommandManager> command_manager_;
  testing::NiceMock<MockStateChangeQueueInterface> mock_state_change_queue_;
  std::shared_ptr<StateManager> state_manager_;
};

////////////////////////////////////////////////////////////////////////////////
TEST_F(DeviceRegistrationInfoTest, GetServiceURL) {
  EXPECT_TRUE(dev_reg_->Load());
  EXPECT_EQ(test_data::kServiceURL, dev_reg_->GetServiceURL());
  std::string url = test_data::kServiceURL;
  url += "registrationTickets";
  EXPECT_EQ(url, dev_reg_->GetServiceURL("registrationTickets"));
  url += "?key=";
  url += test_data::kApiKey;
  EXPECT_EQ(url, dev_reg_->GetServiceURL("registrationTickets", {
    {"key", test_data::kApiKey}
  }));
  url += "&restart=true";
  EXPECT_EQ(url, dev_reg_->GetServiceURL("registrationTickets", {
    {"key", test_data::kApiKey},
    {"restart", "true"},
  }));
}

TEST_F(DeviceRegistrationInfoTest, VerifySave) {
  base::DictionaryValue data;
  data.SetString(storage_keys::kRefreshToken, "d");
  data.SetString(storage_keys::kDeviceId, "e");
  data.SetString(storage_keys::kRobotAccount, "h");
  data.SetString(storage_keys::kName, "k");
  data.SetString(storage_keys::kDescription, "l");
  data.SetString(storage_keys::kLocation, "m");
  data.SetString(storage_keys::kAnonymousAccessRole, "user");

  storage_->Save(&data);

  // This test isn't really trying to test Load, it is just the easiest
  // way to initialize the properties in dev_reg_.
  EXPECT_TRUE(dev_reg_->Load());

  // Clear the storage to get a clean test.
  base::DictionaryValue empty;
  storage_->Save(&empty);
  EXPECT_TRUE(DeviceRegistrationInfo::TestHelper::Save(dev_reg_.get()));
  EXPECT_TRUE(storage_->Load()->Equals(&data));
}

TEST_F(DeviceRegistrationInfoTest, GetOAuthURL) {
  EXPECT_TRUE(dev_reg_->Load());
  EXPECT_EQ(test_data::kOAuthURL, dev_reg_->GetOAuthURL());
  std::string url = test_data::kOAuthURL;
  url += "auth?scope=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fclouddevices&";
  url += "redirect_uri=urn%3Aietf%3Awg%3Aoauth%3A2.0%3Aoob&";
  url += "response_type=code&";
  url += "client_id=";
  url += test_data::kClientId;
  EXPECT_EQ(url, dev_reg_->GetOAuthURL("auth", {
    {"scope", "https://www.googleapis.com/auth/clouddevices"},
    {"redirect_uri", "urn:ietf:wg:oauth:2.0:oob"},
    {"response_type", "code"},
    {"client_id", test_data::kClientId}
  }));
}

TEST_F(DeviceRegistrationInfoTest, CheckRegistration) {
  EXPECT_TRUE(dev_reg_->Load());
  EXPECT_FALSE(DeviceRegistrationInfo::TestHelper::CheckRegistration(
      dev_reg_.get(), nullptr));
  EXPECT_EQ(0, transport_->GetRequestCount());

  SetDefaultDeviceRegistration(&data_);
  storage_->Save(&data_);
  EXPECT_TRUE(dev_reg_->Load());

  transport_->AddHandler(dev_reg_->GetOAuthURL("token"),
                         chromeos::http::request_type::kPost,
                         base::Bind(OAuth2Handler));
  transport_->ResetRequestCount();
  EXPECT_TRUE(DeviceRegistrationInfo::TestHelper::CheckRegistration(
      dev_reg_.get(), nullptr));
  EXPECT_EQ(1, transport_->GetRequestCount());
}

TEST_F(DeviceRegistrationInfoTest, CheckAuthenticationFailure) {
  SetDefaultDeviceRegistration(&data_);
  storage_->Save(&data_);
  EXPECT_TRUE(dev_reg_->Load());
  EXPECT_EQ(RegistrationStatus::kConnecting, dev_reg_->GetRegistrationStatus());

  transport_->AddHandler(dev_reg_->GetOAuthURL("token"),
                         chromeos::http::request_type::kPost,
                         base::Bind(OAuth2HandlerFail));
  transport_->ResetRequestCount();
  chromeos::ErrorPtr error;
  EXPECT_FALSE(DeviceRegistrationInfo::TestHelper::CheckRegistration(
      dev_reg_.get(), &error));
  EXPECT_EQ(1, transport_->GetRequestCount());
  EXPECT_TRUE(error->HasError(kErrorDomainOAuth2, "unable_to_authenticate"));
  EXPECT_EQ(RegistrationStatus::kConnecting, dev_reg_->GetRegistrationStatus());
}

TEST_F(DeviceRegistrationInfoTest, CheckDeregistration) {
  SetDefaultDeviceRegistration(&data_);
  storage_->Save(&data_);
  EXPECT_TRUE(dev_reg_->Load());
  EXPECT_EQ(RegistrationStatus::kConnecting, dev_reg_->GetRegistrationStatus());

  transport_->AddHandler(dev_reg_->GetOAuthURL("token"),
                         chromeos::http::request_type::kPost,
                         base::Bind(OAuth2HandlerDeregister));
  transport_->ResetRequestCount();
  chromeos::ErrorPtr error;
  EXPECT_FALSE(DeviceRegistrationInfo::TestHelper::CheckRegistration(
      dev_reg_.get(), &error));
  EXPECT_EQ(1, transport_->GetRequestCount());
  EXPECT_TRUE(error->HasError(kErrorDomainOAuth2, "invalid_grant"));
  EXPECT_EQ(RegistrationStatus::kInvalidCredentials,
            dev_reg_->GetRegistrationStatus());
}

TEST_F(DeviceRegistrationInfoTest, GetDeviceInfo) {
  SetDefaultDeviceRegistration(&data_);
  storage_->Save(&data_);
  EXPECT_TRUE(dev_reg_->Load());

  transport_->AddHandler(dev_reg_->GetOAuthURL("token"),
                         chromeos::http::request_type::kPost,
                         base::Bind(OAuth2Handler));
  transport_->AddHandler(dev_reg_->GetDeviceURL(),
                         chromeos::http::request_type::kGet,
                         base::Bind(DeviceInfoHandler));
  transport_->ResetRequestCount();
  auto device_info = dev_reg_->GetDeviceInfo(nullptr);
  EXPECT_EQ(2, transport_->GetRequestCount());
  EXPECT_NE(nullptr, device_info.get());
  base::DictionaryValue* dict = nullptr;
  EXPECT_TRUE(device_info->GetAsDictionary(&dict));
  std::string id;
  EXPECT_TRUE(dict->GetString("id", &id));
  EXPECT_EQ(test_data::kDeviceId, id);
}

TEST_F(DeviceRegistrationInfoTest, GetDeviceId) {
  SetDefaultDeviceRegistration(&data_);
  storage_->Save(&data_);
  EXPECT_TRUE(dev_reg_->Load());

  transport_->AddHandler(dev_reg_->GetOAuthURL("token"),
                         chromeos::http::request_type::kPost,
                         base::Bind(OAuth2Handler));
  transport_->AddHandler(dev_reg_->GetDeviceURL(),
                         chromeos::http::request_type::kGet,
                         base::Bind(DeviceInfoHandler));
  EXPECT_EQ(test_data::kDeviceId, dev_reg_->GetDeviceId());
}

TEST_F(DeviceRegistrationInfoTest, RegisterDevice) {
  EXPECT_TRUE(dev_reg_->Load());

  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("xmpp", 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'
            }
          }
        }
      },
      'robot': {
        '_jump': {
          'parameters': {
            '_height': {
              'type': 'integer'
            }
          }
        }
      }
    })";
    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"({
    'base': {
      'reboot': {
        'parameters': {'delay': 'integer'},
        'results': {}
      },
      'shutdown': {
        'parameters': {},
        'results': {}
      }
    }
  })");
  EXPECT_TRUE(command_manager_->LoadBaseCommands(*json_base, nullptr));
  auto json_cmds = unittests::CreateDictionaryValue(R"({
    'base': {
      'reboot': {
        'parameters': {'delay': {'minimum': 10}},
        'results': {}
      }
    },
    'robot': {
      '_jump': {
        'parameters': {'_height': 'integer'},
        'results': {}
      }
    }
  })");
  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));

  transport_->AddHandler(dev_reg_->GetOAuthURL("token"),
                         chromeos::http::request_type::kPost,
                         base::Bind(OAuth2Handler));
  storage_->reset_save_count();

  std::map<std::string, std::string> params;
  params["ticket_id"] = test_data::kClaimTicketId;
  std::string device_id = dev_reg_->RegisterDevice(params, nullptr);

  EXPECT_EQ(test_data::kDeviceId, device_id);
  EXPECT_GT(storage_->save_count(), 1);  // The state must have been saved.
  EXPECT_EQ(3, transport_->GetRequestCount());
  EXPECT_EQ(RegistrationStatus::kConnecting, dev_reg_->GetRegistrationStatus());

  // Validate the device info saved to storage...
  auto storage_data = storage_->Load();
  base::DictionaryValue* dict = nullptr;
  EXPECT_TRUE(storage_data->GetAsDictionary(&dict));
  std::string value;
  EXPECT_TRUE(dict->GetString(storage_keys::kDeviceId, &value));
  EXPECT_EQ(test_data::kDeviceId, value);
  EXPECT_TRUE(dict->GetString(storage_keys::kRefreshToken, &value));
  EXPECT_EQ(test_data::kRefreshToken, value);
  EXPECT_TRUE(dict->GetString(storage_keys::kRobotAccount, &value));
  EXPECT_EQ(test_data::kRobotAccountEmail, value);
}

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.
  EXPECT_TRUE(dev_reg_->Load());
  EXPECT_EQ(RegistrationStatus::kUnconfigured,
            dev_reg_->GetRegistrationStatus());
  // Put some credentials into our state, make sure we call that offline.
  SetDefaultDeviceRegistration(&data_);
  storage_->Save(&data_);
  EXPECT_TRUE(dev_reg_->Load());
  EXPECT_EQ(RegistrationStatus::kConnecting, dev_reg_->GetRegistrationStatus());
}

TEST_F(DeviceRegistrationInfoTest, UpdateCommand) {
  EXPECT_TRUE(dev_reg_->Load());
  auto json_cmds = unittests::CreateDictionaryValue(R"({
    'robot': {
      '_jump': {
        'parameters': {'_height': 'integer'},
        'results': {'status': 'string'}
      }
    }
  })");
  EXPECT_TRUE(command_manager_->LoadCommands(*json_cmds, "", nullptr));

  const std::string command_url = dev_reg_->GetServiceURL("commands/1234");

  auto commands_json = unittests::CreateValue(R"([{
    'name':'robot._jump',
    'id':'1234',
    'parameters': {'_height': 100}
  }])");
  ASSERT_NE(nullptr, commands_json.get());
  const base::ListValue* command_list = nullptr;
  ASSERT_TRUE(commands_json->GetAsList(&command_list));
  DeviceRegistrationInfo::TestHelper::PublishCommands(dev_reg_.get(),
                                                      *command_list);
  auto command = command_manager_->FindCommand("1234");
  ASSERT_NE(nullptr, command);
  StringPropType string_type;
  native_types::Object results{
    {"status", string_type.CreateValue(std::string{"Ok"}, nullptr)}
  };

  // 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));

  command->SetResults(results);

  // 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{});
  };

  transport_->AddHandler(command_url,
                         chromeos::http::request_type::kPatch,
                         base::Bind(update_command_progress));

  native_types::Object progress{
      {"progress", unittests::make_int_prop_value(18)}};
  command->SetProgress(progress);

  // 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));

  command->Cancel();
}


}  // namespace buffet
