Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(44)

Unified Diff: chromeos/components/tether/ble_advertiser_unittest.cc

Issue 2972263002: [CrOS Tether] Do not register a new Bluetooth advertisement until any previous identical advertisem… (Closed)
Patch Set: hansberry@ comment. Created 3 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « chromeos/components/tether/ble_advertiser.cc ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: chromeos/components/tether/ble_advertiser_unittest.cc
diff --git a/chromeos/components/tether/ble_advertiser_unittest.cc b/chromeos/components/tether/ble_advertiser_unittest.cc
index d9676ce8785b0e0952451b0843e61b506d3ad381..2b2ff64c57148f2606fd34cd59a8ad3dbf733970 100644
--- a/chromeos/components/tether/ble_advertiser_unittest.cc
+++ b/chromeos/components/tether/ble_advertiser_unittest.cc
@@ -4,6 +4,8 @@
#include "chromeos/components/tether/ble_advertiser.h"
+#include "base/bind.h"
+#include "base/callback_forward.h"
#include "base/logging.h"
#include "chromeos/components/tether/ble_constants.h"
#include "components/cryptauth/mock_foreground_eid_generator.h"
@@ -11,8 +13,8 @@
#include "components/cryptauth/mock_remote_beacon_seed_fetcher.h"
#include "components/cryptauth/proto/cryptauth_api.pb.h"
#include "components/cryptauth/remote_device_test_util.h"
+#include "device/bluetooth/bluetooth_advertisement.h"
#include "device/bluetooth/test/mock_bluetooth_adapter.h"
-#include "device/bluetooth/test/mock_bluetooth_advertisement.h"
#include "testing/gtest/include/gtest/gtest.h"
using testing::Invoke;
@@ -80,6 +82,33 @@ class MockBluetoothAdapterWithAdvertisements
~MockBluetoothAdapterWithAdvertisements() override {}
};
+class FakeBluetoothAdvertisement : public device::BluetoothAdvertisement {
+ public:
+ // |unregister_callback| should be called with the success callback passed to
+ // Unregister() whenever an Unregister() call occurs.
+ FakeBluetoothAdvertisement(
+ const base::Callback<
+ void(const device::BluetoothAdvertisement::SuccessCallback&)>&
+ 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);
+ }
+
+ private:
+ ~FakeBluetoothAdvertisement() override {}
+
+ base::Callback<void(const device::BluetoothAdvertisement::SuccessCallback&)>
+ unregister_callback_;
+
+ DISALLOW_COPY_AND_ASSIGN(FakeBluetoothAdvertisement);
+};
+
std::vector<cryptauth::DataWithTimestamp> GenerateFakeAdvertisements() {
cryptauth::DataWithTimestamp advertisement1("advertisement1", 1000L, 2000L);
cryptauth::DataWithTimestamp advertisement2("advertisement2", 2000L, 3000L);
@@ -163,7 +192,7 @@ class BleAdvertiserTest : public testing::Test {
ble_advertiser_.reset();
// All observers should have been removed.
- EXPECT_FALSE(individual_advertisements_.size());
+ EXPECT_TRUE(individual_advertisements_.empty());
}
void OnAdapterAddObserver(device::BluetoothAdapter::Observer* observer) {
@@ -186,11 +215,11 @@ class BleAdvertiserTest : public testing::Test {
scoped_refptr<RegisterAdvertisementArgs> args,
const BleAdvertiser::IndividualAdvertisement* advertisement) {
// First, verify that the service UUID list is correct.
- EXPECT_EQ(static_cast<size_t>(1), args->service_uuids.size());
+ EXPECT_EQ(1u, args->service_uuids.size());
EXPECT_EQ(std::string(kAdvertisingServiceUuid), args->service_uuids[0]);
// Then, verify that the service data is correct.
- EXPECT_EQ(static_cast<size_t>(1), args->service_data.size());
+ EXPECT_EQ(1u, args->service_data.size());
std::vector<uint8_t> service_data_from_args =
args->service_data[std::string(kAdvertisingServiceUuid)];
EXPECT_EQ(service_data_from_args.size(),
@@ -218,8 +247,9 @@ class BleAdvertiserTest : public testing::Test {
}
void InvokeCallback(scoped_refptr<RegisterAdvertisementArgs> args) {
- args->callback.Run(
- make_scoped_refptr(new device::MockBluetoothAdvertisement));
+ args->callback.Run(make_scoped_refptr(new FakeBluetoothAdvertisement(
+ base::Bind(&BleAdvertiserTest::OnAdvertisementUnregistered,
+ base::Unretained(this)))));
}
void ReleaseAdvertisement(
@@ -228,6 +258,18 @@ class BleAdvertiserTest : public testing::Test {
individual_advertisement->advertisement_.get());
}
+ void OnAdvertisementUnregistered(
+ const device::BluetoothAdvertisement::SuccessCallback& success_callback) {
+ unregister_callbacks_.push_back(success_callback);
+ }
+
+ void InvokeLastUnregisterCallbackAndRemove() {
+ DCHECK(!unregister_callbacks_.empty());
+ unregister_callbacks_[unregister_callbacks_.size() - 1].Run();
+ unregister_callbacks_.erase(unregister_callbacks_.begin() +
+ unregister_callbacks_.size() - 1);
+ }
+
std::unique_ptr<BleAdvertiser> ble_advertiser_;
scoped_refptr<StrictMock<MockBluetoothAdapterWithAdvertisements>>
@@ -241,6 +283,8 @@ class BleAdvertiserTest : public testing::Test {
register_advertisement_args_;
std::vector<BleAdvertiser::IndividualAdvertisement*>
individual_advertisements_;
+ std::vector<device::BluetoothAdvertisement::SuccessCallback>
+ unregister_callbacks_;
const std::vector<cryptauth::RemoteDevice> fake_devices_;
const std::vector<cryptauth::DataWithTimestamp> fake_advertisements_;
@@ -299,10 +343,10 @@ TEST_F(BleAdvertiserTest, AdapterPoweredOffWhenAdvertisementRegistered) {
base::MakeUnique<cryptauth::DataWithTimestamp>(fake_advertisements_[0]));
EXPECT_TRUE(ble_advertiser_->StartAdvertisingToDevice(fake_devices_[0]));
- EXPECT_EQ(static_cast<size_t>(1), individual_advertisements_.size());
+ EXPECT_EQ(1u, individual_advertisements_.size());
// RegisterAdvertisement() should not have been called.
- EXPECT_FALSE(register_advertisement_args_.size());
+ EXPECT_TRUE(register_advertisement_args_.empty());
}
TEST_F(BleAdvertiserTest, RegisteringAdvertisementFails) {
@@ -315,8 +359,8 @@ TEST_F(BleAdvertiserTest, RegisteringAdvertisementFails) {
base::MakeUnique<cryptauth::DataWithTimestamp>(fake_advertisements_[0]));
EXPECT_TRUE(ble_advertiser_->StartAdvertisingToDevice(fake_devices_[0]));
- EXPECT_EQ(static_cast<size_t>(1), individual_advertisements_.size());
- EXPECT_EQ(static_cast<size_t>(1), register_advertisement_args_.size());
+ EXPECT_EQ(1u, individual_advertisements_.size());
+ EXPECT_EQ(1u, register_advertisement_args_.size());
VerifyServiceDataMatches(register_advertisement_args_[0],
individual_advertisements_[0]);
@@ -334,8 +378,8 @@ TEST_F(BleAdvertiserTest, AdvertisementRegisteredSuccessfully) {
base::MakeUnique<cryptauth::DataWithTimestamp>(fake_advertisements_[0]));
EXPECT_TRUE(ble_advertiser_->StartAdvertisingToDevice(fake_devices_[0]));
- EXPECT_EQ(static_cast<size_t>(1), individual_advertisements_.size());
- EXPECT_EQ(static_cast<size_t>(1), register_advertisement_args_.size());
+ EXPECT_EQ(1u, individual_advertisements_.size());
+ EXPECT_EQ(1u, register_advertisement_args_.size());
VerifyServiceDataMatches(register_advertisement_args_[0],
individual_advertisements_[0]);
@@ -344,7 +388,8 @@ TEST_F(BleAdvertiserTest, AdvertisementRegisteredSuccessfully) {
// Now, unregister.
EXPECT_TRUE(ble_advertiser_->StopAdvertisingToDevice(fake_devices_[0]));
- EXPECT_FALSE(individual_advertisements_.size());
+ InvokeLastUnregisterCallbackAndRemove();
+ EXPECT_TRUE(individual_advertisements_.empty());
}
TEST_F(BleAdvertiserTest, AdvertisementRegisteredSuccessfully_TwoDevices) {
@@ -358,8 +403,8 @@ TEST_F(BleAdvertiserTest, AdvertisementRegisteredSuccessfully_TwoDevices) {
base::MakeUnique<cryptauth::DataWithTimestamp>(fake_advertisements_[0]));
EXPECT_TRUE(ble_advertiser_->StartAdvertisingToDevice(fake_devices_[0]));
- EXPECT_EQ(static_cast<size_t>(1), individual_advertisements_.size());
- EXPECT_EQ(static_cast<size_t>(1), register_advertisement_args_.size());
+ EXPECT_EQ(1u, individual_advertisements_.size());
+ EXPECT_EQ(1u, register_advertisement_args_.size());
VerifyServiceDataMatches(register_advertisement_args_[0],
individual_advertisements_[0]);
@@ -371,8 +416,8 @@ TEST_F(BleAdvertiserTest, AdvertisementRegisteredSuccessfully_TwoDevices) {
base::MakeUnique<cryptauth::DataWithTimestamp>(fake_advertisements_[1]));
EXPECT_TRUE(ble_advertiser_->StartAdvertisingToDevice(fake_devices_[1]));
- EXPECT_EQ(static_cast<size_t>(2), individual_advertisements_.size());
- EXPECT_EQ(static_cast<size_t>(2), register_advertisement_args_.size());
+ EXPECT_EQ(2u, individual_advertisements_.size());
+ EXPECT_EQ(2u, register_advertisement_args_.size());
VerifyServiceDataMatches(register_advertisement_args_[1],
individual_advertisements_[1]);
@@ -382,9 +427,11 @@ TEST_F(BleAdvertiserTest, AdvertisementRegisteredSuccessfully_TwoDevices) {
// Now, unregister.
EXPECT_TRUE(ble_advertiser_->StopAdvertisingToDevice(fake_devices_[0]));
EXPECT_EQ(1u, individual_advertisements_.size());
+ InvokeLastUnregisterCallbackAndRemove();
EXPECT_TRUE(ble_advertiser_->StopAdvertisingToDevice(fake_devices_[1]));
- EXPECT_EQ(0u, individual_advertisements_.size());
+ EXPECT_TRUE(individual_advertisements_.empty());
+ InvokeLastUnregisterCallbackAndRemove();
}
TEST_F(BleAdvertiserTest, TooManyDevicesRegistered) {
@@ -424,17 +471,17 @@ TEST_F(BleAdvertiserTest, AdapterPowerChange_StartsOffThenTurnsOn) {
base::MakeUnique<cryptauth::DataWithTimestamp>(fake_advertisements_[0]));
EXPECT_TRUE(ble_advertiser_->StartAdvertisingToDevice(fake_devices_[0]));
- EXPECT_EQ(static_cast<size_t>(1), individual_advertisements_.size());
+ EXPECT_EQ(1u, individual_advertisements_.size());
// RegisterAdvertisement() should not have been called.
- EXPECT_FALSE(register_advertisement_args_.size());
+ EXPECT_TRUE(register_advertisement_args_.empty());
// Now, simulate power being changed. Since the power is now on,
// RegisterAdvertisement() should have been called.
individual_advertisements_[0]->AdapterPoweredChanged(mock_adapter_.get(),
true);
- EXPECT_EQ(static_cast<size_t>(1), individual_advertisements_.size());
- EXPECT_EQ(static_cast<size_t>(1), register_advertisement_args_.size());
+ EXPECT_EQ(1u, individual_advertisements_.size());
+ EXPECT_EQ(1u, register_advertisement_args_.size());
VerifyServiceDataMatches(register_advertisement_args_[0],
individual_advertisements_[0]);
}
@@ -449,8 +496,8 @@ TEST_F(BleAdvertiserTest, AdvertisementReleased) {
base::MakeUnique<cryptauth::DataWithTimestamp>(fake_advertisements_[0]));
EXPECT_TRUE(ble_advertiser_->StartAdvertisingToDevice(fake_devices_[0]));
- EXPECT_EQ(static_cast<size_t>(1), individual_advertisements_.size());
- EXPECT_EQ(static_cast<size_t>(1), register_advertisement_args_.size());
+ EXPECT_EQ(1u, individual_advertisements_.size());
+ EXPECT_EQ(1u, register_advertisement_args_.size());
VerifyServiceDataMatches(register_advertisement_args_[0],
individual_advertisements_[0]);
@@ -460,7 +507,7 @@ TEST_F(BleAdvertiserTest, AdvertisementReleased) {
// Now, simulate the advertisement being released. A new advertisement should
// have been created.
ReleaseAdvertisement(individual_advertisements_[0]);
- EXPECT_EQ(static_cast<size_t>(2), register_advertisement_args_.size());
+ EXPECT_EQ(2u, register_advertisement_args_.size());
VerifyServiceDataMatches(register_advertisement_args_[1],
individual_advertisements_[0]);
@@ -469,7 +516,60 @@ TEST_F(BleAdvertiserTest, AdvertisementReleased) {
// Now, unregister.
EXPECT_TRUE(ble_advertiser_->StopAdvertisingToDevice(fake_devices_[0]));
- EXPECT_FALSE(individual_advertisements_.size());
+ InvokeLastUnregisterCallbackAndRemove();
+ EXPECT_TRUE(individual_advertisements_.empty());
+}
+
+// Regression test for crbug.com/739883. This issue arises when the following
+// occurs:
+// (1) BleAdvertiser starts advertising to device A.
+// (2) BleAdvertiser stops advertising to device A. The advertisement starts
+// its asynchyronous unregistration flow.
+// (3) BleAdvertiser starts advertising to device A again, but the previous
+// advertisement has not yet been fully unregistered.
+// Before the fix for crbug.com/739883, this would cause an error of type
+// ERROR_ADVERTISEMENT_ALREADY_EXISTS. However, the fix for this issue ensures
+// that the new advertisement in step (3) above does not start until the
+// previous one has been finished.
+TEST_F(BleAdvertiserTest, SameAdvertisementAdded_FirstHasNotBeenUnregistered) {
+ EXPECT_CALL(*mock_adapter_, AddObserver(_)).Times(2);
+ EXPECT_CALL(*mock_adapter_, RemoveObserver(_)).Times(2);
+ EXPECT_CALL(*mock_adapter_, IsPowered()).Times(3);
+ EXPECT_CALL(*mock_adapter_, RegisterAdvertisementWithArgsStruct(_)).Times(2);
+
+ mock_eid_generator_->set_advertisement(
+ base::MakeUnique<cryptauth::DataWithTimestamp>(fake_advertisements_[0]));
+
+ EXPECT_TRUE(ble_advertiser_->StartAdvertisingToDevice(fake_devices_[0]));
+ EXPECT_EQ(1u, individual_advertisements_.size());
+ EXPECT_EQ(1u, register_advertisement_args_.size());
+ VerifyServiceDataMatches(register_advertisement_args_[0],
+ individual_advertisements_[0]);
+
+ InvokeCallback(register_advertisement_args_[0]);
+ VerifyAdvertisementHasStarted(individual_advertisements_[0]);
+
+ // Unregister, but do not invoke the last unregister callback.
+ EXPECT_TRUE(ble_advertiser_->StopAdvertisingToDevice(fake_devices_[0]));
+ EXPECT_TRUE(individual_advertisements_.empty());
+
+ // Start advertising again, to the same device. A new IndividualAdvertisement
+ // should have been created, but a call to RegisterAdvertisement() should NOT
+ // have occurred, since the previous advertisement has not yet been
+ // unregistered.
+ EXPECT_TRUE(ble_advertiser_->StartAdvertisingToDevice(fake_devices_[0]));
+ EXPECT_EQ(1u, individual_advertisements_.size());
+ // Should still be only one set of RegisterAdvertisement() args.
+ EXPECT_EQ(1u, register_advertisement_args_.size());
+
+ // Now, complete the previous unregistration.
+ InvokeLastUnregisterCallbackAndRemove();
+
+ // RegisterAdvertisement() should be called for the new advertisement.
+ EXPECT_EQ(2u, register_advertisement_args_.size());
+
+ VerifyServiceDataMatches(register_advertisement_args_[1],
+ individual_advertisements_[0]);
}
} // namespace tether
« no previous file with comments | « chromeos/components/tether/ble_advertiser.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698