blob: 2db4aadba6ef5f41bbc41487164b2ccd3990be98 [file] [log] [blame]
// Copyright 2016 The Chromium 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 "chromeos/components/tether/keep_alive_operation.h"
#include <memory>
#include <vector>
#include "base/memory/ptr_util.h"
#include "base/optional.h"
#include "base/test/metrics/histogram_tester.h"
#include "base/test/scoped_feature_list.h"
#include "base/test/scoped_task_environment.h"
#include "base/test/simple_test_clock.h"
#include "chromeos/chromeos_features.h"
#include "chromeos/components/tether/fake_ble_connection_manager.h"
#include "chromeos/components/tether/message_wrapper.h"
#include "chromeos/components/tether/proto/tether.pb.h"
#include "chromeos/components/tether/proto_test_util.h"
#include "chromeos/services/device_sync/public/cpp/fake_device_sync_client.h"
#include "chromeos/services/secure_channel/public/cpp/client/fake_secure_channel_client.h"
#include "components/cryptauth/remote_device_test_util.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace chromeos {
namespace tether {
namespace {
constexpr base::TimeDelta kKeepAliveTickleResponseTime =
base::TimeDelta::FromSeconds(3);
class TestObserver final : public KeepAliveOperation::Observer {
public:
TestObserver() : has_run_callback_(false) {}
virtual ~TestObserver() = default;
bool has_run_callback() { return has_run_callback_; }
base::Optional<cryptauth::RemoteDeviceRef> last_remote_device_received() {
return last_remote_device_received_;
}
DeviceStatus* last_device_status_received() {
return last_device_status_received_.get();
}
void OnOperationFinished(
cryptauth::RemoteDeviceRef remote_device,
std::unique_ptr<DeviceStatus> device_status) override {
has_run_callback_ = true;
last_remote_device_received_ = remote_device;
last_device_status_received_ = std::move(device_status);
}
private:
bool has_run_callback_;
base::Optional<cryptauth::RemoteDeviceRef> last_remote_device_received_;
std::unique_ptr<DeviceStatus> last_device_status_received_;
};
std::string CreateKeepAliveTickleString() {
KeepAliveTickle tickle;
return MessageWrapper(tickle).ToRawMessage();
}
std::string CreateKeepAliveTickleResponseString() {
KeepAliveTickleResponse response;
response.mutable_device_status()->CopyFrom(
CreateDeviceStatusWithFakeFields());
return MessageWrapper(response).ToRawMessage();
}
} // namespace
class KeepAliveOperationTest : public testing::Test {
protected:
KeepAliveOperationTest()
: keep_alive_tickle_string_(CreateKeepAliveTickleString()),
test_device_(cryptauth::CreateRemoteDeviceRefListForTest(1)[0]) {}
void SetUp() override {
scoped_feature_list_.InitAndDisableFeature(features::kMultiDeviceApi);
fake_device_sync_client_ =
std::make_unique<device_sync::FakeDeviceSyncClient>();
fake_secure_channel_client_ =
std::make_unique<secure_channel::FakeSecureChannelClient>();
fake_ble_connection_manager_ = std::make_unique<FakeBleConnectionManager>();
operation_ = base::WrapUnique(new KeepAliveOperation(
test_device_, fake_device_sync_client_.get(),
fake_secure_channel_client_.get(), fake_ble_connection_manager_.get()));
test_observer_ = base::WrapUnique(new TestObserver());
operation_->AddObserver(test_observer_.get());
test_clock_.SetNow(base::Time::UnixEpoch());
operation_->SetClockForTest(&test_clock_);
operation_->Initialize();
}
void SimulateDeviceAuthenticationAndVerifyMessageSent() {
operation_->OnDeviceAuthenticated(test_device_);
// Verify that the message was sent successfully.
std::vector<FakeBleConnectionManager::SentMessage>& sent_messages =
fake_ble_connection_manager_->sent_messages();
ASSERT_EQ(1u, sent_messages.size());
EXPECT_EQ(test_device_.GetDeviceId(), sent_messages[0].device_id);
EXPECT_EQ(keep_alive_tickle_string_, sent_messages[0].message);
}
const base::test::ScopedTaskEnvironment scoped_task_environment_;
const std::string keep_alive_tickle_string_;
const cryptauth::RemoteDeviceRef test_device_;
base::test::ScopedFeatureList scoped_feature_list_;
std::unique_ptr<device_sync::FakeDeviceSyncClient> fake_device_sync_client_;
std::unique_ptr<secure_channel::SecureChannelClient>
fake_secure_channel_client_;
std::unique_ptr<FakeBleConnectionManager> fake_ble_connection_manager_;
base::SimpleTestClock test_clock_;
std::unique_ptr<TestObserver> test_observer_;
std::unique_ptr<KeepAliveOperation> operation_;
base::HistogramTester histogram_tester_;
private:
DISALLOW_COPY_AND_ASSIGN(KeepAliveOperationTest);
};
TEST_F(KeepAliveOperationTest, TestSendsKeepAliveTickleAndReceivesResponse) {
EXPECT_FALSE(test_observer_->has_run_callback());
SimulateDeviceAuthenticationAndVerifyMessageSent();
EXPECT_FALSE(test_observer_->has_run_callback());
test_clock_.Advance(kKeepAliveTickleResponseTime);
fake_ble_connection_manager_->ReceiveMessage(
test_device_.GetDeviceId(), CreateKeepAliveTickleResponseString());
EXPECT_TRUE(test_observer_->has_run_callback());
EXPECT_EQ(test_device_, test_observer_->last_remote_device_received());
ASSERT_TRUE(test_observer_->last_device_status_received());
EXPECT_EQ(CreateDeviceStatusWithFakeFields().SerializeAsString(),
test_observer_->last_device_status_received()->SerializeAsString());
histogram_tester_.ExpectTimeBucketCount(
"InstantTethering.Performance.KeepAliveTickleResponseDuration",
kKeepAliveTickleResponseTime, 1);
}
TEST_F(KeepAliveOperationTest, TestCannotConnect) {
// Simulate the device failing to connect.
fake_ble_connection_manager_->SimulateUnansweredConnectionAttempts(
test_device_.GetDeviceId(),
MessageTransferOperation::kMaxEmptyScansPerDevice);
// The maximum number of connection failures has occurred.
EXPECT_TRUE(test_observer_->has_run_callback());
ASSERT_TRUE(test_observer_->last_remote_device_received());
EXPECT_EQ(test_device_, test_observer_->last_remote_device_received());
EXPECT_FALSE(test_observer_->last_device_status_received());
histogram_tester_.ExpectTotalCount(
"InstantTethering.Performance.KeepAliveTickleResponseDuration", 0);
}
} // namespace tether
} // namespace chromeos