| // Copyright 2021 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "ash/quick_pair/message_stream/message_stream.h" |
| |
| #include <memory> |
| |
| #include "ash/quick_pair/common/logging.h" |
| #include "ash/quick_pair/message_stream/fake_bluetooth_socket.h" |
| #include "base/functional/callback.h" |
| #include "base/functional/callback_helpers.h" |
| #include "base/memory/raw_ptr.h" |
| #include "base/memory/scoped_refptr.h" |
| #include "base/run_loop.h" |
| #include "base/test/metrics/histogram_tester.h" |
| #include "base/test/mock_callback.h" |
| #include "base/test/task_environment.h" |
| #include "chromeos/ash/services/quick_pair/fast_pair_data_parser.h" |
| #include "chromeos/ash/services/quick_pair/mock_quick_pair_process_manager.h" |
| #include "chromeos/ash/services/quick_pair/quick_pair_process.h" |
| #include "chromeos/ash/services/quick_pair/quick_pair_process_manager.h" |
| #include "chromeos/ash/services/quick_pair/quick_pair_process_manager_impl.h" |
| #include "device/bluetooth/bluetooth_socket.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| |
| namespace { |
| |
| const std::vector<uint8_t> kModelIdBytes = {/*mesage_group=*/0x03, |
| /*mesage_code=*/0x01, |
| /*additional_data_length=*/0x00, |
| 0x03, |
| /*additional_data=*/0xAA, |
| 0xBB, |
| 0xCC}; |
| const std::vector<uint8_t> kInvalidBytes = {/*mesage_group=*/0x03, |
| /*mesage_code=*/0x09, |
| /*additional_data_length=*/0x00, |
| 0x03, |
| /*additional_data=*/0xAA, |
| 0xBB, |
| 0xCC}; |
| const std::vector<uint8_t> kModelIdBleAddressBytes = { |
| /*mesage_group=*/0x03, |
| /*mesage_code=*/0x01, |
| /*additional_data_length=*/0x00, |
| 0x03, |
| /*additional_data=*/0xAA, |
| 0xBB, |
| 0xCC, |
| /*mesage_group=*/0x03, |
| /*mesage_code=*/0x02, |
| /*additional_data_length=*/0x00, |
| 0x06, |
| /*additional_data=*/0xAA, |
| 0xBB, |
| 0xCC, |
| 0xDD, |
| 0xEE, |
| 0xFF}; |
| const std::vector<uint8_t> kNakBytes = {/*mesage_group=*/0xFF, |
| /*mesage_code=*/0x02, |
| /*additional_data_length=*/0x00, |
| 0x03, |
| /*additional_data=*/0x00, |
| 0x04, |
| 0x01}; |
| const std::vector<uint8_t> kRingDeviceBytes = {/*mesage_group=*/0x04, |
| /*mesage_code=*/0x01, |
| /*additional_data_length=*/0x00, |
| 0x02, |
| /*additional_data=*/0x01, |
| 0x3C}; |
| const std::vector<uint8_t> kPlatformBytes = {/*mesage_group=*/0x03, |
| /*mesage_code=*/0x08, |
| /*additional_data_length=*/0x00, |
| 0x02, |
| /*additional_data=*/0x01, |
| 0x1C}; |
| const std::vector<uint8_t> kActiveComponentBytes = { |
| /*mesage_group=*/0x03, /*mesage_code=*/0x06, |
| /*additional_data_length=*/0x00, 0x01, |
| /*additional_data=*/0x03}; |
| const std::vector<uint8_t> kRemainingBatteryTimeBytes = { |
| /*mesage_group=*/0x03, /*mesage_code=*/0x04, |
| /*additional_data_length=*/0x00, 0x02, |
| /*additional_data=*/0x01, 0x0F}; |
| const std::vector<uint8_t> kBatteryUpdateBytes = { |
| /*mesage_group=*/0x03, |
| /*mesage_code=*/0x03, |
| /*additional_data_length=*/0x00, |
| 0x03, |
| /*additional_data=*/0x57, |
| 0x41, |
| 0x7F}; |
| const std::vector<uint8_t> kEnableSilenceModeBytes = { |
| /*mesage_group=*/0x01, |
| /*mesage_code=*/0x01, |
| /*additional_data_length=*/0x00, 0x00}; |
| const std::vector<uint8_t> kCompanionAppLogBufferFullBytes = { |
| /*mesage_group=*/0x02, |
| /*mesage_code=*/0x01, |
| /*additional_data_length=*/0x00, 0x00}; |
| const std::string kModelIdString = "AABBCC"; |
| const std::string kBleAddressString = "AA:BB:CC:DD:EE:FF"; |
| |
| constexpr int kMaxRetryCount = 10; |
| constexpr int kMessageStorageCapacity = 1000; |
| constexpr char kTestDeviceAddress[] = "11:12:13:14:15:16"; |
| |
| const char kMessageStreamReceiveResultMetric[] = |
| "Bluetooth.ChromeOS.FastPair.MessageStream.Receive.Result"; |
| const char kMessageStreamReceiveErrorMetric[] = |
| "Bluetooth.ChromeOS.FastPair.MessageStream.Receive.ErrorReason"; |
| |
| class FakeQuickPairProcessManager |
| : public ash::quick_pair::QuickPairProcessManager { |
| public: |
| FakeQuickPairProcessManager( |
| base::test::SingleThreadTaskEnvironment* task_environment) |
| : task_enviornment_(task_environment) { |
| data_parser_ = std::make_unique<ash::quick_pair::FastPairDataParser>( |
| fast_pair_data_parser_.InitWithNewPipeAndPassReceiver()); |
| |
| data_parser_remote_.Bind(std::move(fast_pair_data_parser_), |
| task_enviornment_->GetMainThreadTaskRunner()); |
| } |
| |
| ~FakeQuickPairProcessManager() override = default; |
| |
| std::unique_ptr<ProcessReference> GetProcessReference( |
| ProcessStoppedCallback on_process_stopped_callback) override { |
| on_process_stopped_callback_ = std::move(on_process_stopped_callback); |
| |
| if (process_stopped_) { |
| std::move(on_process_stopped_callback_) |
| .Run(ash::quick_pair::QuickPairProcessManager::ShutdownReason:: |
| kFastPairDataParserMojoPipeDisconnection); |
| } |
| |
| return std::make_unique< |
| ash::quick_pair::QuickPairProcessManagerImpl::ProcessReferenceImpl>( |
| data_parser_remote_, base::DoNothing()); |
| } |
| |
| void SetProcessStopped(bool process_stopped) { |
| process_stopped_ = process_stopped; |
| } |
| |
| private: |
| bool process_stopped_ = false; |
| mojo::SharedRemote<ash::quick_pair::mojom::FastPairDataParser> |
| data_parser_remote_; |
| mojo::PendingRemote<ash::quick_pair::mojom::FastPairDataParser> |
| fast_pair_data_parser_; |
| std::unique_ptr<ash::quick_pair::FastPairDataParser> data_parser_; |
| raw_ptr<base::test::SingleThreadTaskEnvironment> task_enviornment_; |
| ProcessStoppedCallback on_process_stopped_callback_; |
| }; |
| |
| } // namespace |
| |
| namespace ash { |
| namespace quick_pair { |
| |
| class MessageStreamTest : public testing::Test, public MessageStream::Observer { |
| public: |
| void SetUp() override { |
| process_manager_ = |
| std::make_unique<FakeQuickPairProcessManager>(&task_enviornment_); |
| quick_pair_process::SetProcessManager(process_manager_.get()); |
| fake_process_manager_ = |
| static_cast<FakeQuickPairProcessManager*>(process_manager_.get()); |
| |
| message_stream_ = |
| std::make_unique<MessageStream>(kTestDeviceAddress, fake_socket_.get()); |
| } |
| |
| void AddObserver() { message_stream_->AddObserver(this); } |
| |
| MockQuickPairProcessManager* mock_process_manager() { |
| return static_cast<MockQuickPairProcessManager*>(process_manager_.get()); |
| } |
| |
| void SetSuccessMessageStreamMessage(const std::vector<uint8_t>& bytes) { |
| fake_socket_->SetIOBufferFromBytes(bytes); |
| } |
| |
| void TriggerReceiveSuccessCallback() { |
| fake_socket_->TriggerReceiveCallback(); |
| } |
| |
| void OnModelIdMessage(const std::string& device_address, |
| const std::string& model_id) override { |
| model_id_ = std::move(model_id); |
| } |
| |
| void OnMessageStreamDestroyed(const std::string& device_address) override { |
| on_destroyed_ = true; |
| } |
| |
| void CleanUpMemory() { message_stream_.reset(); } |
| |
| void DisconnectSocket() { |
| fake_socket_->SetErrorReason( |
| device::BluetoothSocket::ErrorReason::kDisconnected); |
| } |
| |
| void SetEmptyBuffer() { fake_socket_->SetEmptyBuffer(); } |
| |
| void OnDisconnected(const std::string& device_address) override { |
| on_socket_disconnected_ = true; |
| } |
| |
| void OnBleAddressUpdateMessage(const std::string& device_address, |
| const std::string& ble_address) override { |
| ble_address_ = std::move(ble_address); |
| } |
| |
| void OnBatteryUpdateMessage( |
| const std::string& device_address, |
| const mojom::BatteryUpdatePtr& battery_update) override { |
| battery_update_ = true; |
| } |
| |
| void OnRemainingBatteryTimeMessage(const std::string& device_address, |
| uint16_t remaining_battery_time) override { |
| remaining_battery_time_ = remaining_battery_time; |
| } |
| |
| void OnEnableSilenceModeMessage(const std::string& device_address, |
| bool enable_silence_mode) override { |
| enable_silence_mode_ = enable_silence_mode; |
| } |
| |
| void OnCompanionAppLogBufferFullMessage( |
| const std::string& device_address) override { |
| log_buffer_full_ = true; |
| } |
| |
| void OnActiveComponentsMessage(const std::string& device_address, |
| uint8_t active_components_byte) override { |
| active_components_byte_ = active_components_byte; |
| } |
| |
| void OnRingDeviceMessage(const std::string& device_address, |
| const mojom::RingDevicePtr& ring_device) override { |
| ring_device_ = true; |
| } |
| |
| void OnAcknowledgementMessage( |
| const std::string& device_address, |
| const mojom::AcknowledgementMessagePtr& acknowledgement) override { |
| acknowledgement_ = true; |
| } |
| |
| void OnAndroidSdkVersionMessage(const std::string& device_address, |
| uint8_t sdk_version) override { |
| sdk_version_ = sdk_version; |
| } |
| |
| base::HistogramTester& histogram_tester() { return histogram_tester_; } |
| |
| protected: |
| base::HistogramTester histogram_tester_; |
| scoped_refptr<FakeBluetoothSocket> fake_socket_ = |
| base::MakeRefCounted<FakeBluetoothSocket>(); |
| std::unique_ptr<MessageStream> message_stream_; |
| std::string model_id_; |
| std::string ble_address_; |
| base::test::SingleThreadTaskEnvironment task_enviornment_; |
| std::unique_ptr<QuickPairProcessManager> process_manager_; |
| mojo::SharedRemote<mojom::FastPairDataParser> data_parser_remote_; |
| mojo::PendingRemote<mojom::FastPairDataParser> fast_pair_data_parser_; |
| std::unique_ptr<FastPairDataParser> data_parser_; |
| raw_ptr<FakeQuickPairProcessManager> fake_process_manager_; |
| bool battery_update_ = false; |
| uint16_t remaining_battery_time_ = 0; |
| bool enable_silence_mode_ = false; |
| bool on_destroyed_ = false; |
| bool on_socket_disconnected_ = false; |
| bool log_buffer_full_ = false; |
| uint8_t active_components_byte_ = 0x0F; |
| bool ring_device_ = false; |
| bool acknowledgement_ = false; |
| uint8_t sdk_version_ = 0; |
| }; |
| |
| TEST_F(MessageStreamTest, ReceiveMessages_Observation_SuccessfulMessage) { |
| histogram_tester().ExpectTotalCount(kMessageStreamReceiveResultMetric, 0); |
| histogram_tester().ExpectTotalCount(kMessageStreamReceiveErrorMetric, 0); |
| |
| EXPECT_TRUE(model_id_.empty()); |
| EXPECT_TRUE(message_stream_->messages().empty()); |
| |
| AddObserver(); |
| SetSuccessMessageStreamMessage(kModelIdBytes); |
| TriggerReceiveSuccessCallback(); |
| base::RunLoop().RunUntilIdle(); |
| |
| EXPECT_EQ(model_id_, kModelIdString); |
| EXPECT_FALSE(message_stream_->messages().empty()); |
| |
| histogram_tester().ExpectTotalCount(kMessageStreamReceiveResultMetric, 1); |
| histogram_tester().ExpectTotalCount(kMessageStreamReceiveErrorMetric, 0); |
| } |
| |
| TEST_F(MessageStreamTest, ReceiveMessages_Observation_NullMessage) { |
| histogram_tester().ExpectTotalCount(kMessageStreamReceiveResultMetric, 0); |
| histogram_tester().ExpectTotalCount(kMessageStreamReceiveErrorMetric, 0); |
| |
| EXPECT_TRUE(model_id_.empty()); |
| EXPECT_TRUE(message_stream_->messages().empty()); |
| |
| AddObserver(); |
| SetSuccessMessageStreamMessage(kInvalidBytes); |
| TriggerReceiveSuccessCallback(); |
| base::RunLoop().RunUntilIdle(); |
| |
| EXPECT_TRUE(message_stream_->messages().empty()); |
| EXPECT_TRUE(model_id_.empty()); |
| |
| histogram_tester().ExpectTotalCount(kMessageStreamReceiveResultMetric, 1); |
| histogram_tester().ExpectTotalCount(kMessageStreamReceiveErrorMetric, 0); |
| } |
| |
| TEST_F(MessageStreamTest, ReceiveMessages_GetMessages) { |
| EXPECT_TRUE(model_id_.empty()); |
| EXPECT_TRUE(message_stream_->messages().empty()); |
| |
| SetSuccessMessageStreamMessage(kModelIdBytes); |
| TriggerReceiveSuccessCallback(); |
| base::RunLoop().RunUntilIdle(); |
| |
| EXPECT_FALSE(message_stream_->messages().empty()); |
| EXPECT_EQ(message_stream_->messages()[0]->get_model_id(), kModelIdString); |
| } |
| |
| TEST_F(MessageStreamTest, ReceiveMessages_CleanUp) { |
| EXPECT_TRUE(model_id_.empty()); |
| EXPECT_TRUE(message_stream_->messages().empty()); |
| |
| AddObserver(); |
| SetSuccessMessageStreamMessage(kModelIdBytes); |
| TriggerReceiveSuccessCallback(); |
| base::RunLoop().RunUntilIdle(); |
| |
| EXPECT_FALSE(message_stream_->messages().empty()); |
| EXPECT_FALSE(on_destroyed_); |
| CleanUpMemory(); |
| EXPECT_TRUE(on_destroyed_); |
| } |
| |
| TEST_F(MessageStreamTest, ReceiveMessages_SocketDisconnect) { |
| histogram_tester().ExpectTotalCount(kMessageStreamReceiveResultMetric, 0); |
| histogram_tester().ExpectTotalCount(kMessageStreamReceiveErrorMetric, 0); |
| |
| EXPECT_FALSE(on_socket_disconnected_); |
| EXPECT_TRUE(message_stream_->messages().empty()); |
| |
| DisconnectSocket(); |
| |
| AddObserver(); |
| TriggerReceiveSuccessCallback(); |
| base::RunLoop().RunUntilIdle(); |
| |
| EXPECT_TRUE(message_stream_->messages().empty()); |
| EXPECT_TRUE(on_socket_disconnected_); |
| |
| histogram_tester().ExpectTotalCount(kMessageStreamReceiveResultMetric, 1); |
| histogram_tester().ExpectTotalCount(kMessageStreamReceiveErrorMetric, 1); |
| } |
| |
| TEST_F(MessageStreamTest, |
| ReceiveMessages_DisconnectCallback_SocketAlreadyDisconnected) { |
| EXPECT_FALSE(on_socket_disconnected_); |
| EXPECT_TRUE(message_stream_->messages().empty()); |
| DisconnectSocket(); |
| AddObserver(); |
| TriggerReceiveSuccessCallback(); |
| base::RunLoop().RunUntilIdle(); |
| |
| EXPECT_TRUE(message_stream_->messages().empty()); |
| EXPECT_TRUE(on_socket_disconnected_); |
| |
| base::MockCallback<base::OnceClosure> callback; |
| EXPECT_CALL(callback, Run).Times(1); |
| message_stream_->Disconnect(callback.Get()); |
| } |
| |
| TEST_F(MessageStreamTest, ReceiveMessages_FailureAfterMaxRetries) { |
| EXPECT_FALSE(on_socket_disconnected_); |
| EXPECT_TRUE(message_stream_->messages().empty()); |
| |
| AddObserver(); |
| |
| for (int i = 0; i < kMaxRetryCount; ++i) { |
| TriggerReceiveSuccessCallback(); |
| base::RunLoop().RunUntilIdle(); |
| } |
| |
| EXPECT_TRUE(message_stream_->messages().empty()); |
| EXPECT_TRUE(on_socket_disconnected_); |
| } |
| |
| TEST_F(MessageStreamTest, |
| ReceiveMessages_Observation_SuccessfulMultipleMessages) { |
| EXPECT_TRUE(model_id_.empty()); |
| EXPECT_TRUE(ble_address_.empty()); |
| EXPECT_TRUE(message_stream_->messages().empty()); |
| |
| AddObserver(); |
| SetSuccessMessageStreamMessage(kModelIdBleAddressBytes); |
| TriggerReceiveSuccessCallback(); |
| base::RunLoop().RunUntilIdle(); |
| |
| EXPECT_FALSE(message_stream_->messages().empty()); |
| EXPECT_EQ(model_id_, kModelIdString); |
| EXPECT_EQ(ble_address_, kBleAddressString); |
| } |
| |
| TEST_F(MessageStreamTest, ReceiveMessages_GetMultipleMessages) { |
| EXPECT_TRUE(model_id_.empty()); |
| EXPECT_TRUE(ble_address_.empty()); |
| EXPECT_TRUE(message_stream_->messages().empty()); |
| |
| SetSuccessMessageStreamMessage(kModelIdBleAddressBytes); |
| TriggerReceiveSuccessCallback(); |
| base::RunLoop().RunUntilIdle(); |
| |
| EXPECT_FALSE(message_stream_->messages().empty()); |
| EXPECT_EQ(message_stream_->messages()[0]->get_model_id(), kModelIdString); |
| EXPECT_EQ(message_stream_->messages()[1]->get_ble_address_update(), |
| kBleAddressString); |
| } |
| |
| TEST_F(MessageStreamTest, ReceiveMessages_BatteryUpdate) { |
| EXPECT_FALSE(battery_update_); |
| EXPECT_TRUE(message_stream_->messages().empty()); |
| |
| AddObserver(); |
| SetSuccessMessageStreamMessage(kBatteryUpdateBytes); |
| TriggerReceiveSuccessCallback(); |
| base::RunLoop().RunUntilIdle(); |
| |
| EXPECT_FALSE(message_stream_->messages().empty()); |
| EXPECT_TRUE(battery_update_); |
| } |
| |
| TEST_F(MessageStreamTest, ReceiveMessages_RemainingBatteryTime) { |
| EXPECT_EQ(remaining_battery_time_, 0); |
| EXPECT_TRUE(message_stream_->messages().empty()); |
| |
| AddObserver(); |
| SetSuccessMessageStreamMessage(kRemainingBatteryTimeBytes); |
| TriggerReceiveSuccessCallback(); |
| base::RunLoop().RunUntilIdle(); |
| |
| EXPECT_FALSE(message_stream_->messages().empty()); |
| EXPECT_EQ(remaining_battery_time_, 271); |
| } |
| |
| TEST_F(MessageStreamTest, ReceiveMessages_ActiveComponents) { |
| EXPECT_EQ(active_components_byte_, 0x0F); |
| EXPECT_TRUE(message_stream_->messages().empty()); |
| |
| AddObserver(); |
| SetSuccessMessageStreamMessage(kActiveComponentBytes); |
| TriggerReceiveSuccessCallback(); |
| base::RunLoop().RunUntilIdle(); |
| |
| EXPECT_FALSE(message_stream_->messages().empty()); |
| EXPECT_EQ(active_components_byte_, 0x03); |
| } |
| |
| TEST_F(MessageStreamTest, ReceiveMessages_SdkVersion) { |
| EXPECT_EQ(sdk_version_, 0); |
| EXPECT_TRUE(message_stream_->messages().empty()); |
| |
| AddObserver(); |
| SetSuccessMessageStreamMessage(kPlatformBytes); |
| TriggerReceiveSuccessCallback(); |
| base::RunLoop().RunUntilIdle(); |
| |
| EXPECT_FALSE(message_stream_->messages().empty()); |
| EXPECT_EQ(sdk_version_, 28); |
| } |
| |
| TEST_F(MessageStreamTest, ReceiveMessages_RingDevice) { |
| EXPECT_FALSE(ring_device_); |
| EXPECT_TRUE(message_stream_->messages().empty()); |
| |
| AddObserver(); |
| SetSuccessMessageStreamMessage(kRingDeviceBytes); |
| TriggerReceiveSuccessCallback(); |
| base::RunLoop().RunUntilIdle(); |
| |
| EXPECT_FALSE(message_stream_->messages().empty()); |
| EXPECT_TRUE(ring_device_); |
| } |
| |
| TEST_F(MessageStreamTest, ReceiveMessages_EnableSilenceMode) { |
| EXPECT_FALSE(enable_silence_mode_); |
| EXPECT_TRUE(message_stream_->messages().empty()); |
| |
| AddObserver(); |
| SetSuccessMessageStreamMessage(kEnableSilenceModeBytes); |
| TriggerReceiveSuccessCallback(); |
| base::RunLoop().RunUntilIdle(); |
| |
| EXPECT_FALSE(message_stream_->messages().empty()); |
| EXPECT_TRUE(enable_silence_mode_); |
| } |
| |
| TEST_F(MessageStreamTest, ReceiveMessages_CompanionAppLogBuffer) { |
| EXPECT_FALSE(log_buffer_full_); |
| EXPECT_TRUE(message_stream_->messages().empty()); |
| |
| AddObserver(); |
| SetSuccessMessageStreamMessage(kCompanionAppLogBufferFullBytes); |
| TriggerReceiveSuccessCallback(); |
| base::RunLoop().RunUntilIdle(); |
| |
| EXPECT_FALSE(message_stream_->messages().empty()); |
| EXPECT_TRUE(log_buffer_full_); |
| } |
| |
| TEST_F(MessageStreamTest, ReceiveMessages_Nak) { |
| EXPECT_FALSE(acknowledgement_); |
| EXPECT_TRUE(message_stream_->messages().empty()); |
| |
| AddObserver(); |
| SetSuccessMessageStreamMessage(kNakBytes); |
| TriggerReceiveSuccessCallback(); |
| base::RunLoop().RunUntilIdle(); |
| |
| EXPECT_FALSE(message_stream_->messages().empty()); |
| EXPECT_TRUE(acknowledgement_); |
| } |
| |
| TEST_F(MessageStreamTest, ReceiveMessages_EmptyBuffer_SuccessReceive) { |
| EXPECT_TRUE(message_stream_->messages().empty()); |
| |
| SetEmptyBuffer(); |
| SetSuccessMessageStreamMessage(kModelIdBytes); |
| TriggerReceiveSuccessCallback(); |
| base::RunLoop().RunUntilIdle(); |
| |
| EXPECT_TRUE(message_stream_->messages().empty()); |
| TriggerReceiveSuccessCallback(); |
| base::RunLoop().RunUntilIdle(); |
| |
| EXPECT_FALSE(message_stream_->messages().empty()); |
| } |
| |
| TEST_F(MessageStreamTest, ReceiveMessages_EmptyBuffer_ErrorReceive) { |
| EXPECT_TRUE(message_stream_->messages().empty()); |
| |
| SetEmptyBuffer(); |
| TriggerReceiveSuccessCallback(); |
| base::RunLoop().RunUntilIdle(); |
| |
| EXPECT_TRUE(message_stream_->messages().empty()); |
| TriggerReceiveSuccessCallback(); |
| base::RunLoop().RunUntilIdle(); |
| |
| EXPECT_TRUE(message_stream_->messages().empty()); |
| } |
| |
| TEST_F(MessageStreamTest, ReceiveMessages_BufferFull) { |
| EXPECT_TRUE(model_id_.empty()); |
| EXPECT_TRUE(ble_address_.empty()); |
| |
| AddObserver(); |
| |
| for (int i = 0; i < kMessageStorageCapacity + 1; i++) { |
| SetSuccessMessageStreamMessage(kModelIdBytes); |
| TriggerReceiveSuccessCallback(); |
| base::RunLoop().RunUntilIdle(); |
| } |
| |
| EXPECT_EQ(static_cast<int>(message_stream_->messages().size()), |
| kMessageStorageCapacity); |
| } |
| |
| TEST_F(MessageStreamTest, UtilityProcessStopped_RetrySuccess) { |
| EXPECT_TRUE(message_stream_->messages().empty()); |
| fake_process_manager_->SetProcessStopped(true); |
| SetSuccessMessageStreamMessage(kModelIdBytes); |
| TriggerReceiveSuccessCallback(); |
| base::RunLoop().RunUntilIdle(); |
| |
| EXPECT_FALSE(message_stream_->messages().empty()); |
| } |
| |
| } // namespace quick_pair |
| } // namespace ash |