| // 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/ble_synchronizer.h" |
| |
| #include <memory> |
| |
| #include "base/bind.h" |
| #include "base/callback_forward.h" |
| #include "base/memory/ptr_util.h" |
| #include "base/memory/ref_counted.h" |
| #include "base/memory/weak_ptr.h" |
| #include "base/test/histogram_tester.h" |
| #include "base/test/scoped_task_environment.h" |
| #include "base/test/simple_test_clock.h" |
| #include "base/test/test_simple_task_runner.h" |
| #include "base/timer/mock_timer.h" |
| #include "chromeos/components/tether/ble_constants.h" |
| #include "components/cryptauth/data_with_timestamp.h" |
| #include "device/bluetooth/bluetooth_advertisement.h" |
| #include "device/bluetooth/test/mock_bluetooth_adapter.h" |
| #include "device/bluetooth/test/mock_bluetooth_advertisement.h" |
| #include "device/bluetooth/test/mock_bluetooth_discovery_session.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| |
| using testing::Invoke; |
| using testing::NiceMock; |
| using testing::_; |
| |
| namespace chromeos { |
| |
| namespace tether { |
| |
| namespace { |
| |
| const char kId1[] = "id1"; |
| const char kId2[] = "id2"; |
| const char kId3[] = "id3"; |
| |
| int64_t kTimeBetweenEachCommandMs = 200; |
| |
| struct RegisterAdvertisementArgs { |
| RegisterAdvertisementArgs( |
| const device::BluetoothAdvertisement::UUIDList& service_uuids, |
| const device::BluetoothAdapter::CreateAdvertisementCallback& callback, |
| const device::BluetoothAdapter::AdvertisementErrorCallback& |
| error_callback) |
| : service_uuids(service_uuids), |
| callback(callback), |
| error_callback(error_callback) {} |
| |
| device::BluetoothAdvertisement::UUIDList service_uuids; |
| const device::BluetoothAdapter::CreateAdvertisementCallback callback; |
| const device::BluetoothAdapter::AdvertisementErrorCallback error_callback; |
| }; |
| |
| struct UnregisterAdvertisementArgs { |
| UnregisterAdvertisementArgs( |
| const device::BluetoothAdvertisement::SuccessCallback& callback, |
| const device::BluetoothAdvertisement::ErrorCallback& error_callback) |
| : callback(callback), error_callback(error_callback) {} |
| |
| const device::BluetoothAdvertisement::SuccessCallback callback; |
| const device::BluetoothAdvertisement::ErrorCallback error_callback; |
| }; |
| |
| struct StartDiscoverySessionArgs { |
| StartDiscoverySessionArgs( |
| const device::BluetoothAdapter::DiscoverySessionCallback& callback, |
| const device::BluetoothAdapter::ErrorCallback& error_callback) |
| : callback(callback), error_callback(error_callback) {} |
| |
| const device::BluetoothAdapter::DiscoverySessionCallback callback; |
| const device::BluetoothAdapter::ErrorCallback error_callback; |
| }; |
| |
| struct StopDiscoverySessionArgs { |
| StopDiscoverySessionArgs( |
| const base::Closure& callback, |
| const device::BluetoothDiscoverySession::ErrorCallback& error_callback) |
| : callback(callback), error_callback(error_callback) {} |
| |
| const base::Closure callback; |
| const device::BluetoothDiscoverySession::ErrorCallback error_callback; |
| }; |
| |
| class MockBluetoothAdapterWithAdvertisements |
| : public device::MockBluetoothAdapter { |
| public: |
| MockBluetoothAdapterWithAdvertisements() : MockBluetoothAdapter() {} |
| |
| MOCK_METHOD1(RegisterAdvertisementWithArgsStruct, |
| void(RegisterAdvertisementArgs*)); |
| MOCK_METHOD3(StartDiscoverySessionWithFilterRaw, |
| void(device::BluetoothDiscoveryFilter*, |
| const device::BluetoothAdapter::DiscoverySessionCallback&, |
| const device::BluetoothAdapter::ErrorCallback&)); |
| |
| void RegisterAdvertisement( |
| std::unique_ptr<device::BluetoothAdvertisement::Data> advertisement_data, |
| const device::BluetoothAdapter::CreateAdvertisementCallback& callback, |
| const device::BluetoothAdapter::AdvertisementErrorCallback& |
| error_callback) override { |
| RegisterAdvertisementWithArgsStruct(new RegisterAdvertisementArgs( |
| *advertisement_data->service_uuids(), callback, error_callback)); |
| } |
| |
| void StartDiscoverySessionWithFilter( |
| std::unique_ptr<device::BluetoothDiscoveryFilter> discovery_filter, |
| const device::BluetoothAdapter::DiscoverySessionCallback& callback, |
| const device::BluetoothAdapter::ErrorCallback& error_callback) override { |
| StartDiscoverySessionWithFilterRaw(discovery_filter.get(), callback, |
| error_callback); |
| } |
| |
| protected: |
| ~MockBluetoothAdapterWithAdvertisements() override = default; |
| }; |
| |
| class FakeBluetoothAdvertisement : public device::BluetoothAdvertisement { |
| public: |
| // |unregister_callback| should be called with the callbacks passed to |
| // Unregister() whenever an Unregister() call occurs. |
| FakeBluetoothAdvertisement( |
| const base::Callback< |
| void(const device::BluetoothAdvertisement::SuccessCallback&, |
| const device::BluetoothAdvertisement::ErrorCallback&)>& |
| unregister_callback) |
| : unregister_callback_(unregister_callback) {} |
| |
| // BluetoothAdvertisement: |
| void Unregister( |
| const device::BluetoothAdvertisement::SuccessCallback& success_callback, |
| const device::BluetoothAdvertisement::ErrorCallback& error_callback) |
| override { |
| unregister_callback_.Run(success_callback, error_callback); |
| } |
| |
| private: |
| ~FakeBluetoothAdvertisement() override = default; |
| |
| base::Callback<void(const device::BluetoothAdvertisement::SuccessCallback&, |
| const device::BluetoothAdvertisement::ErrorCallback&)> |
| unregister_callback_; |
| |
| DISALLOW_COPY_AND_ASSIGN(FakeBluetoothAdvertisement); |
| }; |
| |
| class FakeDiscoverySession : public device::MockBluetoothDiscoverySession { |
| public: |
| // |stop_callback| should be called with the callbacks passed to |
| // Stop() whenever a Stop() call occurs. |
| FakeDiscoverySession( |
| const base::Callback< |
| void(const base::Closure&, |
| const device::BluetoothDiscoverySession::ErrorCallback&)>& |
| stop_callback) |
| : stop_callback_(stop_callback) {} |
| ~FakeDiscoverySession() override = default; |
| |
| // BluetoothDiscoverySession: |
| void Stop(const base::Closure& callback, |
| const device::BluetoothDiscoverySession::ErrorCallback& |
| error_callback) override { |
| stop_callback_.Run(callback, error_callback); |
| } |
| |
| private: |
| base::Callback<void(const base::Closure&, |
| const device::BluetoothDiscoverySession::ErrorCallback&)> |
| stop_callback_; |
| |
| DISALLOW_COPY_AND_ASSIGN(FakeDiscoverySession); |
| }; |
| |
| // Creates a UUIDList with one element of value |id|. |
| std::unique_ptr<device::BluetoothAdvertisement::UUIDList> CreateUUIDList( |
| const std::string& id) { |
| return std::make_unique<device::BluetoothAdvertisement::UUIDList>(1u, id); |
| } |
| |
| // Creates advertisement data with a UUID list with one element of value |id|. |
| std::unique_ptr<device::BluetoothAdvertisement::Data> GenerateAdvertisementData( |
| const std::string& id) { |
| auto data = std::make_unique<device::BluetoothAdvertisement::Data>( |
| device::BluetoothAdvertisement::AdvertisementType:: |
| ADVERTISEMENT_TYPE_PERIPHERAL); |
| data->set_service_uuids(CreateUUIDList(id)); |
| return data; |
| } |
| |
| } // namespace |
| |
| class BleSynchronizerTest : public testing::Test { |
| protected: |
| BleSynchronizerTest() |
| : fake_advertisement_(base::MakeRefCounted<FakeBluetoothAdvertisement>( |
| base::Bind(&BleSynchronizerTest::OnUnregisterCalled, |
| base::Unretained(this)))), |
| fake_discovery_session_(base::WrapUnique(new FakeDiscoverySession( |
| base::Bind(&BleSynchronizerTest::OnStopCalled, |
| base::Unretained(this))))), |
| fake_discovery_session_weak_ptr_factory_( |
| fake_discovery_session_.get()) {} |
| |
| void SetUp() override { |
| num_register_success_ = 0; |
| num_register_error_ = 0; |
| num_unregister_success_ = 0; |
| num_unregister_error_ = 0; |
| num_start_success_ = 0; |
| num_start_error_ = 0; |
| num_stop_success_ = 0; |
| num_stop_error_ = 0; |
| register_args_list_.clear(); |
| |
| mock_adapter_ = base::MakeRefCounted< |
| NiceMock<MockBluetoothAdapterWithAdvertisements>>(); |
| ON_CALL(*mock_adapter_, RegisterAdvertisementWithArgsStruct(_)) |
| .WillByDefault( |
| Invoke(this, &BleSynchronizerTest::OnAdapterRegisterAdvertisement)); |
| ON_CALL(*mock_adapter_, StartDiscoverySessionWithFilterRaw(_, _, _)) |
| .WillByDefault( |
| Invoke(this, &BleSynchronizerTest::OnAdapterStartDiscoverySession)); |
| |
| mock_timer_ = new base::MockTimer(true /* retain_user_task */, |
| false /* is_repeating */); |
| |
| test_clock_ = new base::SimpleTestClock(); |
| test_clock_->Advance(TimeDeltaMillis(kTimeBetweenEachCommandMs)); |
| test_task_runner_ = base::MakeRefCounted<base::TestSimpleTaskRunner>(); |
| |
| synchronizer_ = std::make_unique<BleSynchronizer>(mock_adapter_); |
| synchronizer_->SetTestDoubles(base::WrapUnique(mock_timer_), |
| base::WrapUnique(test_clock_), |
| test_task_runner_); |
| } |
| |
| base::TimeDelta TimeDeltaMillis(int64_t num_millis) { |
| return base::TimeDelta::FromMilliseconds(num_millis); |
| } |
| |
| void OnAdapterRegisterAdvertisement(RegisterAdvertisementArgs* args) { |
| register_args_list_.emplace_back(base::WrapUnique(args)); |
| } |
| |
| void OnAdapterStartDiscoverySession( |
| device::BluetoothDiscoveryFilter* discovery_filter, |
| const device::BluetoothAdapter::DiscoverySessionCallback& callback, |
| const device::BluetoothAdapter::ErrorCallback& error_callback) { |
| EXPECT_EQ(device::BluetoothTransport::BLUETOOTH_TRANSPORT_LE, |
| discovery_filter->GetTransport()); |
| start_discovery_args_list_.emplace_back(base::WrapUnique( |
| new StartDiscoverySessionArgs(callback, error_callback))); |
| } |
| |
| void RegisterAdvertisement(const std::string& id) { |
| synchronizer_->RegisterAdvertisement( |
| GenerateAdvertisementData(id), |
| base::Bind(&BleSynchronizerTest::OnAdvertisementRegistered, |
| base::Unretained(this)), |
| base::Bind(&BleSynchronizerTest::OnErrorRegisteringAdvertisement, |
| base::Unretained(this))); |
| } |
| |
| void InvokeRegisterCallback(bool success, |
| const std::string& expected_id, |
| size_t reg_arg_index, |
| size_t expected_registration_result_count) { |
| EXPECT_TRUE(register_args_list_.size() >= reg_arg_index); |
| EXPECT_EQ(*CreateUUIDList(expected_id), |
| register_args_list_[reg_arg_index]->service_uuids); |
| |
| BleSynchronizer::BluetoothAdvertisementResult expected_result; |
| if (success) { |
| register_args_list_[reg_arg_index]->callback.Run( |
| base::MakeRefCounted<device::MockBluetoothAdvertisement>()); |
| expected_result = BleSynchronizer::BluetoothAdvertisementResult::SUCCESS; |
| } else { |
| register_args_list_[reg_arg_index]->error_callback.Run( |
| device::BluetoothAdvertisement::ErrorCode:: |
| INVALID_ADVERTISEMENT_ERROR_CODE); |
| expected_result = BleSynchronizer::BluetoothAdvertisementResult:: |
| INVALID_ADVERTISEMENT_ERROR_CODE; |
| } |
| |
| histogram_tester_.ExpectBucketCount( |
| "InstantTethering.BluetoothAdvertisementRegistrationResult", |
| expected_result, expected_registration_result_count); |
| |
| // Reset to make sure that this callback is never double-invoked. |
| register_args_list_[reg_arg_index].reset(); |
| test_task_runner_->RunUntilIdle(); |
| } |
| |
| void OnAdvertisementRegistered( |
| scoped_refptr<device::BluetoothAdvertisement> advertisement) { |
| ++num_register_success_; |
| } |
| |
| void OnErrorRegisteringAdvertisement( |
| device::BluetoothAdvertisement::ErrorCode error_code) { |
| ++num_register_error_; |
| } |
| |
| void UnregisterAdvertisement() { |
| synchronizer_->UnregisterAdvertisement( |
| fake_advertisement_, |
| base::Bind(&BleSynchronizerTest::OnAdvertisementUnregistered, |
| base::Unretained(this)), |
| base::Bind(&BleSynchronizerTest::OnErrorUnregisteringAdvertisement, |
| base::Unretained(this))); |
| } |
| |
| void InvokeUnregisterCallback(bool success, |
| size_t unreg_arg_index, |
| size_t expected_unregistration_result_count) { |
| EXPECT_TRUE(unregister_args_list_.size() >= unreg_arg_index); |
| |
| BleSynchronizer::BluetoothAdvertisementResult expected_result; |
| if (success) { |
| unregister_args_list_[unreg_arg_index]->callback.Run(); |
| expected_result = BleSynchronizer::BluetoothAdvertisementResult::SUCCESS; |
| } else { |
| unregister_args_list_[unreg_arg_index]->error_callback.Run( |
| device::BluetoothAdvertisement::ErrorCode:: |
| INVALID_ADVERTISEMENT_ERROR_CODE); |
| expected_result = BleSynchronizer::BluetoothAdvertisementResult:: |
| INVALID_ADVERTISEMENT_ERROR_CODE; |
| } |
| |
| histogram_tester_.ExpectBucketCount( |
| "InstantTethering.BluetoothAdvertisementUnregistrationResult", |
| expected_result, expected_unregistration_result_count); |
| |
| // Reset to make sure that this callback is never double-invoked. |
| unregister_args_list_[unreg_arg_index].reset(); |
| test_task_runner_->RunUntilIdle(); |
| } |
| |
| void OnAdvertisementUnregistered() { ++num_unregister_success_; } |
| |
| void OnErrorUnregisteringAdvertisement( |
| device::BluetoothAdvertisement::ErrorCode error_code) { |
| ++num_unregister_error_; |
| } |
| |
| void StartDiscoverySession() { |
| synchronizer_->StartDiscoverySession( |
| base::Bind(&BleSynchronizerTest::OnDiscoverySessionStarted, |
| base::Unretained(this)), |
| base::Bind(&BleSynchronizerTest::OnErrorStartingDiscoverySession, |
| base::Unretained(this))); |
| } |
| |
| void InvokeStartDiscoveryCallback( |
| bool success, |
| size_t start_arg_index, |
| size_t expected_start_discovery_result_count) { |
| EXPECT_TRUE(start_discovery_args_list_.size() >= start_arg_index); |
| |
| if (success) { |
| start_discovery_args_list_[start_arg_index]->callback.Run( |
| std::make_unique<device::MockBluetoothDiscoverySession>()); |
| } else { |
| start_discovery_args_list_[start_arg_index]->error_callback.Run(); |
| } |
| |
| histogram_tester_.ExpectUniqueSample( |
| "InstantTethering.BluetoothDiscoverySessionStarted", success ? 1 : 0, |
| expected_start_discovery_result_count); |
| |
| // Reset to make sure that this callback is never double-invoked. |
| start_discovery_args_list_[start_arg_index].reset(); |
| test_task_runner_->RunUntilIdle(); |
| } |
| |
| void OnDiscoverySessionStarted( |
| std::unique_ptr<device::BluetoothDiscoverySession> discovery_session) { |
| ++num_start_success_; |
| } |
| |
| void OnErrorStartingDiscoverySession() { ++num_start_error_; } |
| |
| void StopDiscoverySession( |
| base::WeakPtr<device::BluetoothDiscoverySession> discovery_session) { |
| synchronizer_->StopDiscoverySession( |
| discovery_session, |
| base::Bind(&BleSynchronizerTest::OnDiscoverySessionStopped, |
| base::Unretained(this)), |
| base::Bind(&BleSynchronizerTest::OnErrorStoppingDiscoverySession, |
| base::Unretained(this))); |
| } |
| |
| void InvokeStopDiscoveryCallback( |
| bool success, |
| size_t stop_arg_index, |
| size_t expected_stop_discovery_result_count) { |
| EXPECT_TRUE(stop_discovery_args_list_.size() >= stop_arg_index); |
| |
| if (success) |
| stop_discovery_args_list_[stop_arg_index]->callback.Run(); |
| else |
| stop_discovery_args_list_[stop_arg_index]->error_callback.Run(); |
| |
| histogram_tester_.ExpectUniqueSample( |
| "InstantTethering.BluetoothDiscoverySessionStopped", success ? 1 : 0, |
| expected_stop_discovery_result_count); |
| |
| // Reset to make sure that this callback is never double-invoked. |
| stop_discovery_args_list_[stop_arg_index].reset(); |
| test_task_runner_->RunUntilIdle(); |
| } |
| |
| void OnDiscoverySessionStopped() { ++num_stop_success_; } |
| |
| void OnErrorStoppingDiscoverySession() { ++num_stop_error_; } |
| |
| void FireTimer() { |
| EXPECT_TRUE(mock_timer_->IsRunning()); |
| mock_timer_->Fire(); |
| } |
| |
| void OnUnregisterCalled( |
| const device::BluetoothAdvertisement::SuccessCallback& callback, |
| const device::BluetoothAdvertisement::ErrorCallback& error_callback) { |
| unregister_args_list_.emplace_back(base::WrapUnique( |
| new UnregisterAdvertisementArgs(callback, error_callback))); |
| } |
| |
| void OnStopCalled( |
| const base::Closure& callback, |
| const device::BluetoothDiscoverySession::ErrorCallback& error_callback) { |
| stop_discovery_args_list_.emplace_back(base::WrapUnique( |
| new StopDiscoverySessionArgs(callback, error_callback))); |
| } |
| |
| const base::test::ScopedTaskEnvironment scoped_task_environment_; |
| const scoped_refptr<FakeBluetoothAdvertisement> fake_advertisement_; |
| const std::unique_ptr<device::MockBluetoothDiscoverySession> |
| fake_discovery_session_; |
| base::WeakPtrFactory<device::MockBluetoothDiscoverySession> |
| fake_discovery_session_weak_ptr_factory_; |
| |
| scoped_refptr<NiceMock<MockBluetoothAdapterWithAdvertisements>> mock_adapter_; |
| |
| base::MockTimer* mock_timer_; |
| base::SimpleTestClock* test_clock_; |
| scoped_refptr<base::TestSimpleTaskRunner> test_task_runner_; |
| |
| std::vector<std::unique_ptr<RegisterAdvertisementArgs>> register_args_list_; |
| std::vector<std::unique_ptr<UnregisterAdvertisementArgs>> |
| unregister_args_list_; |
| std::vector<std::unique_ptr<StartDiscoverySessionArgs>> |
| start_discovery_args_list_; |
| std::vector<std::unique_ptr<StopDiscoverySessionArgs>> |
| stop_discovery_args_list_; |
| |
| int num_register_success_; |
| int num_register_error_; |
| int num_unregister_success_; |
| int num_unregister_error_; |
| int num_start_success_; |
| int num_start_error_; |
| int num_stop_success_; |
| int num_stop_error_; |
| |
| bool stopped_callback_called_; |
| |
| std::unique_ptr<BleSynchronizer> synchronizer_; |
| |
| base::HistogramTester histogram_tester_; |
| |
| private: |
| DISALLOW_COPY_AND_ASSIGN(BleSynchronizerTest); |
| }; |
| |
| TEST_F(BleSynchronizerTest, TestRegisterSuccess) { |
| RegisterAdvertisement(kId1); |
| InvokeRegisterCallback(true /* success */, kId1, 0u /* reg_arg_index */, |
| 1u /* expected_registration_result_count */); |
| EXPECT_EQ(1, num_register_success_); |
| } |
| |
| TEST_F(BleSynchronizerTest, TestRegisterError) { |
| RegisterAdvertisement(kId1); |
| InvokeRegisterCallback(false /* success */, kId1, 0u /* reg_arg_index */, |
| 1u /* expected_registration_result_count */); |
| EXPECT_EQ(1, num_register_error_); |
| } |
| |
| TEST_F(BleSynchronizerTest, TestUnregisterSuccess) { |
| UnregisterAdvertisement(); |
| InvokeUnregisterCallback(true /* success */, 0u /* reg_arg_index */, |
| 1 /* expected_unregistration_result_count */); |
| EXPECT_EQ(1, num_unregister_success_); |
| } |
| |
| TEST_F(BleSynchronizerTest, TestUnregisterError) { |
| UnregisterAdvertisement(); |
| InvokeUnregisterCallback(false /* success */, 0u /* reg_arg_index */, |
| 1 /* expected_unregistration_result_count */); |
| EXPECT_EQ(1, num_unregister_error_); |
| } |
| |
| TEST_F(BleSynchronizerTest, TestStartSuccess) { |
| StartDiscoverySession(); |
| InvokeStartDiscoveryCallback(true /* success */, 0u /* reg_arg_index */, |
| 1 /* expected_start_discovery_result_count */); |
| EXPECT_EQ(1, num_start_success_); |
| } |
| |
| TEST_F(BleSynchronizerTest, TestStartError) { |
| StartDiscoverySession(); |
| InvokeStartDiscoveryCallback(false /* success */, 0u /* reg_arg_index */, |
| 1 /* expected_start_discovery_result_count */); |
| EXPECT_EQ(1, num_start_error_); |
| } |
| |
| TEST_F(BleSynchronizerTest, TestStopSuccess) { |
| StopDiscoverySession(fake_discovery_session_weak_ptr_factory_.GetWeakPtr()); |
| InvokeStopDiscoveryCallback(true /* success */, 0u /* unreg_arg_index */, |
| 1 /* expected_stop_discovery_result_count */); |
| EXPECT_EQ(1, num_stop_success_); |
| } |
| |
| TEST_F(BleSynchronizerTest, TestStopError) { |
| StopDiscoverySession(fake_discovery_session_weak_ptr_factory_.GetWeakPtr()); |
| InvokeStopDiscoveryCallback(false /* success */, 0u /* unreg_arg_index */, |
| 1 /* expected_stop_discovery_result_count */); |
| EXPECT_EQ(1, num_stop_error_); |
| } |
| |
| TEST_F(BleSynchronizerTest, TestStop_DeletedDiscoverySession) { |
| // Simulate an invalidated WeakPtr being processed. |
| StopDiscoverySession(base::WeakPtr<device::MockBluetoothDiscoverySession>()); |
| RegisterAdvertisement(kId1); |
| |
| // Stop() should not have been called. |
| EXPECT_TRUE(stop_discovery_args_list_.empty()); |
| |
| // The RegisterAdvertisement() command should be sent without the need for a |
| // delay, since the previous command was not actually sent. |
| InvokeRegisterCallback(true /* success */, kId1, 0u /* reg_arg_index */, |
| 1u /* expected_registration_result_count */); |
| EXPECT_EQ(1, num_register_success_); |
| } |
| |
| TEST_F(BleSynchronizerTest, TestThrottling) { |
| RegisterAdvertisement(kId1); |
| InvokeRegisterCallback(true /* success */, kId1, 0u /* reg_arg_index */, |
| 1u /* expected_registration_result_count */); |
| EXPECT_EQ(1, num_register_success_); |
| |
| // Advance to one millisecond before the limit. |
| test_clock_->Advance(TimeDeltaMillis(kTimeBetweenEachCommandMs - 1)); |
| UnregisterAdvertisement(); |
| |
| // Should still be empty since it should have been throttled, and the timer |
| // should be running. |
| EXPECT_TRUE(unregister_args_list_.empty()); |
| EXPECT_TRUE(mock_timer_->IsRunning()); |
| |
| // Advance the clock and fire the timer. This should result in the next |
| // command being executed. |
| test_clock_->Advance(TimeDeltaMillis(kTimeBetweenEachCommandMs)); |
| mock_timer_->Fire(); |
| |
| InvokeUnregisterCallback(true /* success */, 0u /* reg_arg_index */, |
| 1 /* expected_unregistration_result_count */); |
| EXPECT_EQ(1, num_unregister_success_); |
| |
| // Now, register 2 advertisements at the same time. |
| RegisterAdvertisement(kId2); |
| RegisterAdvertisement(kId3); |
| |
| // Should still only have the original register command.. |
| EXPECT_EQ(1u, register_args_list_.size()); |
| |
| // Advance the clock and fire the timer. This should result in the next |
| // command being executed. |
| test_clock_->Advance(TimeDeltaMillis(kTimeBetweenEachCommandMs)); |
| mock_timer_->Fire(); |
| |
| EXPECT_EQ(2u, register_args_list_.size()); |
| InvokeRegisterCallback(false /* success */, kId2, 1u /* reg_arg_index */, |
| 1u /* expected_registration_result_count */); |
| EXPECT_EQ(1, num_register_error_); |
| |
| // Advance the clock and fire the timer. This should result in the next |
| // command being executed. |
| test_clock_->Advance(TimeDeltaMillis(kTimeBetweenEachCommandMs)); |
| mock_timer_->Fire(); |
| |
| EXPECT_EQ(3u, register_args_list_.size()); |
| InvokeRegisterCallback(true /* success */, kId3, 2u /* reg_arg_index */, |
| 2u /* expected_registration_result_count */); |
| EXPECT_EQ(2, num_register_success_); |
| |
| // Advance the clock before doing anything else. The next request should not |
| // be throttled. |
| EXPECT_FALSE(mock_timer_->IsRunning()); |
| test_clock_->Advance(TimeDeltaMillis(kTimeBetweenEachCommandMs)); |
| |
| UnregisterAdvertisement(); |
| InvokeUnregisterCallback(false /* success */, 1u /* reg_arg_index */, |
| 1 /* expected_unregistration_result_count */); |
| EXPECT_EQ(1, num_unregister_error_); |
| } |
| |
| } // namespace tether |
| |
| } // namespace chromeos |