| // Copyright 2016 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "chromeos/ash/components/tether/keep_alive_operation.h" |
| |
| #include <memory> |
| #include <optional> |
| #include <vector> |
| |
| #include "base/memory/ptr_util.h" |
| #include "base/memory/raw_ptr.h" |
| #include "base/test/metrics/histogram_tester.h" |
| #include "base/test/simple_test_clock.h" |
| #include "chromeos/ash/components/multidevice/remote_device_test_util.h" |
| #include "chromeos/ash/components/tether/fake_host_connection.h" |
| #include "chromeos/ash/components/tether/message_wrapper.h" |
| #include "chromeos/ash/components/tether/proto_test_util.h" |
| #include "chromeos/ash/components/timer_factory/fake_timer_factory.h" |
| #include "testing/gmock/include/gmock/gmock.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| |
| using testing::_; |
| using testing::Invoke; |
| using testing::NotNull; |
| |
| namespace ash::tether { |
| |
| namespace { |
| |
| // Used to verify the KeepAliveOperation notifies the observer when appropriate. |
| class MockOperationObserver : public KeepAliveOperation::Observer { |
| public: |
| MockOperationObserver() = default; |
| |
| MockOperationObserver(const MockOperationObserver&) = delete; |
| MockOperationObserver& operator=(const MockOperationObserver&) = delete; |
| |
| ~MockOperationObserver() = default; |
| |
| MOCK_METHOD1(OnOperationFinishedRaw, void(DeviceStatus*)); |
| |
| void OnOperationFinished( |
| std::unique_ptr<DeviceStatus> device_status) override { |
| OnOperationFinishedRaw(device_status.get()); |
| } |
| }; |
| |
| } // namespace |
| |
| class KeepAliveOperationTest : public testing::Test { |
| public: |
| KeepAliveOperationTest(const KeepAliveOperationTest&) = delete; |
| KeepAliveOperationTest& operator=(const KeepAliveOperationTest&) = delete; |
| |
| protected: |
| KeepAliveOperationTest() |
| : tether_host_(TetherHost(multidevice::CreateRemoteDeviceRefForTest())) {} |
| |
| void SetUp() override { |
| fake_host_connection_factory_ = |
| std::make_unique<FakeHostConnection::Factory>(); |
| operation_ = base::WrapUnique(new KeepAliveOperation( |
| tether_host_, fake_host_connection_factory_.get())); |
| operation_->AddObserver(&mock_observer_); |
| |
| operation_->SetTimerFactoryForTest( |
| std::make_unique<ash::timer_factory::FakeTimerFactory>()); |
| |
| test_clock_.SetNow(base::Time::UnixEpoch()); |
| operation_->SetClockForTest(&test_clock_); |
| } |
| |
| const TetherHost tether_host_; |
| |
| std::unique_ptr<FakeHostConnection::Factory> fake_host_connection_factory_; |
| std::unique_ptr<KeepAliveOperation> operation_; |
| |
| base::SimpleTestClock test_clock_; |
| MockOperationObserver mock_observer_; |
| base::HistogramTester histogram_tester_; |
| }; |
| |
| // Tests that the KeepAliveTickle message is sent to the remote device once the |
| // communication channel is connected and authenticated. |
| TEST_F(KeepAliveOperationTest, KeepAliveTickleSentOnceAuthenticated) { |
| // Setup the connection. |
| fake_host_connection_factory_->SetupConnectionAttempt(tether_host_); |
| |
| // Start the operation. |
| operation_->Initialize(); |
| |
| // Verify the KeepAliveTickle message is sent. |
| auto message_wrapper = std::make_unique<MessageWrapper>(KeepAliveTickle()); |
| std::string expected_payload = message_wrapper->ToRawMessage(); |
| EXPECT_EQ(1u, fake_host_connection_factory_ |
| ->GetActiveConnection(tether_host_.GetDeviceId()) |
| ->sent_messages() |
| .size()); |
| EXPECT_EQ(expected_payload, |
| fake_host_connection_factory_ |
| ->GetActiveConnection(tether_host_.GetDeviceId()) |
| ->sent_messages()[0] |
| .first->ToRawMessage()); |
| } |
| |
| // Tests that observers are notified when the operation has completed, signified |
| // by the OnMessageReceived handler being called. |
| TEST_F(KeepAliveOperationTest, NotifiesObserversOnResponse) { |
| DeviceStatus test_status = CreateDeviceStatusWithFakeFields(); |
| |
| // Setup the connection. |
| fake_host_connection_factory_->SetupConnectionAttempt(tether_host_); |
| |
| // Verify that the observer is called with the correct parameters. |
| EXPECT_CALL(mock_observer_, OnOperationFinishedRaw(NotNull())) |
| .WillOnce(Invoke([&test_status](DeviceStatus* status) { |
| EXPECT_EQ(test_status.SerializeAsString(), status->SerializeAsString()); |
| })); |
| |
| // Start the operation. |
| operation_->Initialize(); |
| |
| KeepAliveTickleResponse response; |
| response.mutable_device_status()->CopyFrom(test_status); |
| std::unique_ptr<MessageWrapper> message(new MessageWrapper(response)); |
| operation_->OnMessageReceived(std::move(message)); |
| } |
| |
| TEST_F(KeepAliveOperationTest, RecordsResponseDuration) { |
| static constexpr base::TimeDelta kKeepAliveTickleResponseTime = |
| base::Seconds(3); |
| |
| EXPECT_CALL(mock_observer_, OnOperationFinishedRaw(_)); |
| |
| // Setup the connection. |
| fake_host_connection_factory_->SetupConnectionAttempt(tether_host_); |
| |
| // Initialize the operation. |
| operation_->Initialize(); |
| |
| // Advance the clock in order to verify a non-zero response duration is |
| // recorded and verified (below). |
| test_clock_.Advance(kKeepAliveTickleResponseTime); |
| |
| std::unique_ptr<MessageWrapper> message( |
| new MessageWrapper(KeepAliveTickleResponse())); |
| operation_->OnMessageReceived(std::move(message)); |
| |
| histogram_tester_.ExpectTimeBucketCount( |
| "InstantTethering.Performance.KeepAliveTickleResponseDuration", |
| kKeepAliveTickleResponseTime, 1); |
| } |
| |
| } // namespace ash::tether |