1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491 |
- // Copyright 2014 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 "device/bluetooth/bluetooth_device.h"
- #include <stddef.h>
- #include "base/bind.h"
- #include "base/containers/contains.h"
- #include "base/logging.h"
- #include "base/run_loop.h"
- #include "base/strings/utf_string_conversions.h"
- #include "base/test/bind.h"
- #include "base/test/test_future.h"
- #include "base/threading/sequenced_task_runner_handle.h"
- #include "build/build_config.h"
- #include "device/bluetooth/bluetooth_remote_gatt_service.h"
- #include "device/bluetooth/public/cpp/bluetooth_address.h"
- #include "device/bluetooth/test/mock_pairing_delegate.h"
- #include "device/bluetooth/test/test_bluetooth_adapter_observer.h"
- #include "testing/gtest/include/gtest/gtest.h"
- #if BUILDFLAG(IS_ANDROID)
- #include "device/bluetooth/test/bluetooth_test_android.h"
- #elif BUILDFLAG(IS_MAC)
- #include "device/bluetooth/test/bluetooth_test_mac.h"
- #elif BUILDFLAG(IS_WIN)
- #include "device/bluetooth/test/bluetooth_test_win.h"
- #elif defined(USE_CAST_BLUETOOTH_ADAPTER)
- #include "device/bluetooth/test/bluetooth_test_cast.h"
- #elif BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_LINUX)
- #include "device/bluetooth/test/bluetooth_test_bluez.h"
- #elif BUILDFLAG(IS_FUCHSIA)
- #include "device/bluetooth/test/bluetooth_test_fuchsia.h"
- #endif
- namespace device {
- namespace {
- using ::testing::_;
- using ::testing::StrictMock;
- int8_t ToInt8(BluetoothTest::TestRSSI rssi) {
- return static_cast<int8_t>(rssi);
- }
- int8_t ToInt8(BluetoothTest::TestTxPower tx_power) {
- return static_cast<int8_t>(tx_power);
- }
- #if BUILDFLAG(IS_WIN)
- void ScheduleAsynchronousCancelPairing(BluetoothDevice* device) {
- base::SequencedTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, base::BindOnce(&BluetoothDevice::CancelPairing,
- base::Unretained(device)));
- }
- void ScheduleAsynchronousRejectPairing(BluetoothDevice* device) {
- base::SequencedTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, base::BindOnce(&BluetoothDevice::RejectPairing,
- base::Unretained(device)));
- }
- #endif // BUILDFLAG(IS_WIN)
- } // namespace
- using UUIDSet = BluetoothDevice::UUIDSet;
- using ServiceDataMap = BluetoothDevice::ServiceDataMap;
- using ManufacturerDataMap = BluetoothDevice::ManufacturerDataMap;
- TEST(BluetoothDeviceTest, CanonicalizeAddressFormat_AcceptsAllValidFormats) {
- // There are three valid separators (':', '-', and none).
- // Case shouldn't matter.
- const char* const kValidFormats[] = {
- "1A:2B:3C:4D:5E:6F",
- "1a:2B:3c:4D:5e:6F",
- "1a:2b:3c:4d:5e:6f",
- "1A-2B-3C-4D-5E-6F",
- "1a-2B-3c-4D-5e-6F",
- "1a-2b-3c-4d-5e-6f",
- "1A2B3C4D5E6F",
- "1a2B3c4D5e6F",
- "1a2b3c4d5e6f",
- };
- for (size_t i = 0; i < std::size(kValidFormats); ++i) {
- SCOPED_TRACE(std::string("Input format: '") + kValidFormats[i] + "'");
- EXPECT_EQ("1A:2B:3C:4D:5E:6F",
- CanonicalizeBluetoothAddress(kValidFormats[i]));
- std::array<uint8_t, 6> parsed;
- EXPECT_TRUE(ParseBluetoothAddress(kValidFormats[i], parsed));
- EXPECT_EQ("\x1a\x2b\x3c\x4d\x5e\x6f",
- std::string(parsed.begin(), parsed.end()));
- }
- }
- TEST(BluetoothDeviceTest,
- CanonicalizeAddressFormat_AcceptsAllValidFormatsBytes) {
- std::array<uint8_t, 6> kValidBytes = {12, 14, 76, 200, 5, 8};
- EXPECT_EQ("0C:0E:4C:C8:05:08", CanonicalizeBluetoothAddress(kValidBytes));
- }
- TEST(BluetoothDeviceTest, CanonicalizeAddressFormat_RejectsInvalidFormats) {
- const char* const kInvalidFormats[] = {
- // Empty string.
- "",
- // Too short.
- "1A:2B:3C:4D:5E",
- // Too long.
- "1A:2B:3C:4D:5E:6F:70",
- // Missing a separator.
- "1A:2B:3C:4D:5E6F",
- // Mixed separators.
- "1A:2B-3C:4D-5E:6F",
- // Invalid hex (6X)
- "1A:2B:3C:4D:5E:6X",
- // Separators in the wrong place.
- "1:A2:B3:C4:D5:E6F",
- // Wrong separator
- "1A|2B|3C|4D|5E|6F",
- };
- for (size_t i = 0; i < std::size(kInvalidFormats); ++i) {
- SCOPED_TRACE(std::string("Input format: '") + kInvalidFormats[i] + "'");
- EXPECT_EQ(std::string(), CanonicalizeBluetoothAddress(kInvalidFormats[i]));
- std::array<uint8_t, 6> parsed;
- EXPECT_FALSE(ParseBluetoothAddress(kInvalidFormats[i], parsed));
- }
- }
- #if BUILDFLAG(IS_WIN)
- TEST_P(BluetoothTestWinrtOnly, DeviceIsPaired) {
- if (!PlatformSupportsLowEnergy()) {
- LOG(WARNING) << "Low Energy Bluetooth unavailable, skipping unit test.";
- return;
- }
- InitWithFakeAdapter();
- StartLowEnergyDiscoverySession();
- BluetoothDevice* device = SimulateLowEnergyDevice(1);
- // By default a device should not be paired.
- EXPECT_FALSE(device->IsPaired());
- // Connect to the device and simulate a paired state.
- ASSERT_TRUE(ConnectGatt(device));
- SimulateDevicePaired(device, true);
- EXPECT_TRUE(device->IsPaired());
- SimulateDevicePaired(device, false);
- EXPECT_FALSE(device->IsPaired());
- }
- // Tests that providing a correct pin code results in a paired device.
- TEST_P(BluetoothTestWinrtOnly, DevicePairRequestPinCodeCorrect) {
- if (!PlatformSupportsLowEnergy()) {
- LOG(WARNING) << "Low Energy Bluetooth unavailable, skipping unit test.";
- return;
- }
- InitWithFakeAdapter();
- StartLowEnergyDiscoverySession();
- BluetoothDevice* device = SimulateLowEnergyDevice(1);
- ASSERT_TRUE(ConnectGatt(device));
- EXPECT_FALSE(device->IsPaired());
- EXPECT_FALSE(device->ExpectingPinCode());
- SimulatePairingPinCode(device, "123456");
- StrictMock<MockPairingDelegate> pairing_delegate;
- EXPECT_CALL(pairing_delegate, RequestPinCode)
- .WillOnce([](BluetoothDevice* device) {
- ASSERT_NE(device, nullptr);
- device->SetPinCode("123456");
- });
- base::RunLoop run_loop;
- device->Pair(
- &pairing_delegate,
- base::BindLambdaForTesting(
- [&](absl::optional<BluetoothDevice::ConnectErrorCode> error_code) {
- EXPECT_FALSE(error_code.has_value());
- run_loop.Quit();
- }));
- run_loop.Run();
- EXPECT_TRUE(device->IsPaired());
- EXPECT_FALSE(device->ExpectingPinCode());
- }
- // Tests that providing a wrong pin code does not result in a paired device.
- TEST_P(BluetoothTestWinrtOnly, DevicePairRequestPinCodeWrong) {
- if (!PlatformSupportsLowEnergy()) {
- LOG(WARNING) << "Low Energy Bluetooth unavailable, skipping unit test.";
- return;
- }
- InitWithFakeAdapter();
- StartLowEnergyDiscoverySession();
- BluetoothDevice* device = SimulateLowEnergyDevice(1);
- ASSERT_TRUE(ConnectGatt(device));
- EXPECT_FALSE(device->IsPaired());
- EXPECT_FALSE(device->ExpectingPinCode());
- SimulatePairingPinCode(device, "123456");
- StrictMock<MockPairingDelegate> pairing_delegate;
- EXPECT_CALL(pairing_delegate, RequestPinCode)
- .WillOnce([](BluetoothDevice* device) {
- ASSERT_NE(device, nullptr);
- device->SetPinCode("000000");
- });
- base::RunLoop run_loop;
- device->Pair(
- &pairing_delegate,
- base::BindLambdaForTesting(
- [&](absl::optional<BluetoothDevice::ConnectErrorCode> error_code) {
- EXPECT_EQ(BluetoothDevice::ERROR_FAILED, error_code);
- run_loop.Quit();
- }));
- run_loop.Run();
- EXPECT_FALSE(device->IsPaired());
- EXPECT_FALSE(device->ExpectingPinCode());
- }
- // Tests that rejecting the pairing does not result in a paired device.
- TEST_P(BluetoothTestWinrtOnly, DevicePairRequestPinCodeRejectPairing) {
- if (!PlatformSupportsLowEnergy()) {
- LOG(WARNING) << "Low Energy Bluetooth unavailable, skipping unit test.";
- return;
- }
- InitWithFakeAdapter();
- StartLowEnergyDiscoverySession();
- BluetoothDevice* device = SimulateLowEnergyDevice(1);
- ASSERT_TRUE(ConnectGatt(device));
- EXPECT_FALSE(device->IsPaired());
- EXPECT_FALSE(device->ExpectingPinCode());
- SimulatePairingPinCode(device, "123456");
- StrictMock<MockPairingDelegate> pairing_delegate;
- EXPECT_CALL(pairing_delegate, RequestPinCode)
- .WillOnce([](BluetoothDevice* device) {
- ASSERT_NE(device, nullptr);
- ScheduleAsynchronousRejectPairing(device);
- });
- base::RunLoop run_loop;
- device->Pair(
- &pairing_delegate,
- base::BindLambdaForTesting(
- [&](absl::optional<BluetoothDevice::ConnectErrorCode> error_code) {
- EXPECT_EQ(BluetoothDevice::ERROR_AUTH_REJECTED, error_code);
- run_loop.Quit();
- }));
- run_loop.Run();
- EXPECT_FALSE(device->IsPaired());
- EXPECT_FALSE(device->ExpectingPinCode());
- }
- // Tests that cancelling the pairing does not result in a paired device.
- TEST_P(BluetoothTestWinrtOnly, DevicePairRequestPinCodeCancelPairing) {
- if (!PlatformSupportsLowEnergy()) {
- LOG(WARNING) << "Low Energy Bluetooth unavailable, skipping unit test.";
- return;
- }
- InitWithFakeAdapter();
- StartLowEnergyDiscoverySession();
- BluetoothDevice* device = SimulateLowEnergyDevice(1);
- ASSERT_TRUE(ConnectGatt(device));
- EXPECT_FALSE(device->IsPaired());
- EXPECT_FALSE(device->ExpectingPinCode());
- SimulatePairingPinCode(device, "123456");
- StrictMock<MockPairingDelegate> pairing_delegate;
- EXPECT_CALL(pairing_delegate, RequestPinCode)
- .WillOnce([](BluetoothDevice* device) {
- ASSERT_NE(device, nullptr);
- ScheduleAsynchronousCancelPairing(device);
- });
- base::RunLoop run_loop;
- device->Pair(
- &pairing_delegate,
- base::BindLambdaForTesting(
- [&](absl::optional<BluetoothDevice::ConnectErrorCode> error_code) {
- EXPECT_EQ(BluetoothDevice::ERROR_AUTH_CANCELED, error_code);
- run_loop.Quit();
- }));
- run_loop.Run();
- EXPECT_FALSE(device->IsPaired());
- EXPECT_FALSE(device->ExpectingPinCode());
- }
- TEST_P(BluetoothTestWinrtOnly, DevicePairRequestConfirmOnlyAccept) {
- if (!PlatformSupportsLowEnergy()) {
- LOG(WARNING) << "Low Energy Bluetooth unavailable, skipping unit test.";
- return;
- }
- InitWithFakeAdapter();
- StartLowEnergyDiscoverySession();
- BluetoothDevice* device = SimulateLowEnergyDevice(1);
- ASSERT_TRUE(ConnectGatt(device));
- EXPECT_FALSE(device->IsPaired());
- SimulateConfirmOnly(device);
- StrictMock<MockPairingDelegate> pairing_delegate;
- EXPECT_CALL(pairing_delegate, AuthorizePairing)
- .WillOnce([](BluetoothDevice* device) {
- ASSERT_NE(device, nullptr);
- device->ConfirmPairing();
- });
- base::test::TestFuture<absl::optional<BluetoothDevice::ConnectErrorCode>>
- error_code_future;
- device->Pair(&pairing_delegate, error_code_future.GetCallback());
- EXPECT_FALSE(error_code_future.Get().has_value());
- EXPECT_TRUE(device->IsPaired());
- }
- TEST_P(BluetoothTestWinrtOnly, DevicePairRequestConfirmOnlyCancel) {
- if (!PlatformSupportsLowEnergy()) {
- LOG(WARNING) << "Low Energy Bluetooth unavailable, skipping unit test.";
- return;
- }
- InitWithFakeAdapter();
- StartLowEnergyDiscoverySession();
- BluetoothDevice* device = SimulateLowEnergyDevice(1);
- ASSERT_TRUE(ConnectGatt(device));
- EXPECT_FALSE(device->IsPaired());
- SimulateConfirmOnly(device);
- StrictMock<MockPairingDelegate> pairing_delegate;
- EXPECT_CALL(pairing_delegate, AuthorizePairing)
- .WillOnce([](BluetoothDevice* device) {
- ASSERT_NE(device, nullptr);
- ScheduleAsynchronousCancelPairing(device);
- });
- base::test::TestFuture<absl::optional<BluetoothDevice::ConnectErrorCode>>
- error_code_future;
- device->Pair(&pairing_delegate, error_code_future.GetCallback());
- EXPECT_EQ(error_code_future.Get(), BluetoothDevice::ERROR_AUTH_CANCELED);
- EXPECT_FALSE(device->IsPaired());
- }
- TEST_P(BluetoothTestWinrtOnly, DevicePairRequestConfirmPinAccept) {
- if (!PlatformSupportsLowEnergy()) {
- LOG(WARNING) << "Low Energy Bluetooth unavailable, skipping unit test.";
- return;
- }
- InitWithFakeAdapter();
- StartLowEnergyDiscoverySession();
- BluetoothDevice* device = SimulateLowEnergyDevice(1);
- ASSERT_TRUE(ConnectGatt(device));
- EXPECT_FALSE(device->IsPaired());
- SimulateDisplayPin(device, "123456");
- StrictMock<MockPairingDelegate> pairing_delegate;
- EXPECT_CALL(pairing_delegate, ConfirmPasskey)
- .WillOnce([](BluetoothDevice* device, uint32_t passkey) {
- ASSERT_NE(device, nullptr);
- ASSERT_EQ(passkey, 123456u);
- device->ConfirmPairing();
- });
- base::test::TestFuture<absl::optional<BluetoothDevice::ConnectErrorCode>>
- error_code_future;
- device->Pair(&pairing_delegate, error_code_future.GetCallback());
- EXPECT_FALSE(error_code_future.Get().has_value());
- EXPECT_TRUE(device->IsPaired());
- }
- TEST_P(BluetoothTestWinrtOnly, DevicePairRequestConfirmPinCancel) {
- if (!PlatformSupportsLowEnergy()) {
- LOG(WARNING) << "Low Energy Bluetooth unavailable, skipping unit test.";
- return;
- }
- InitWithFakeAdapter();
- StartLowEnergyDiscoverySession();
- BluetoothDevice* device = SimulateLowEnergyDevice(1);
- ASSERT_TRUE(ConnectGatt(device));
- EXPECT_FALSE(device->IsPaired());
- SimulateDisplayPin(device, "123456");
- StrictMock<MockPairingDelegate> pairing_delegate;
- EXPECT_CALL(pairing_delegate, ConfirmPasskey)
- .WillOnce([](BluetoothDevice* device, uint32_t passkey) {
- ASSERT_NE(device, nullptr);
- ASSERT_EQ(passkey, 123456u);
- ScheduleAsynchronousCancelPairing(device);
- });
- base::test::TestFuture<absl::optional<BluetoothDevice::ConnectErrorCode>>
- error_code_future;
- device->Pair(&pairing_delegate, error_code_future.GetCallback());
- EXPECT_EQ(error_code_future.Get(), BluetoothDevice::ERROR_AUTH_CANCELED);
- EXPECT_FALSE(device->IsPaired());
- }
- TEST_P(BluetoothTestWinrtOnly, DevicePairRequestConfirmPinLeadingZeroAccept) {
- if (!PlatformSupportsLowEnergy()) {
- LOG(WARNING) << "Low Energy Bluetooth unavailable, skipping unit test.";
- return;
- }
- InitWithFakeAdapter();
- StartLowEnergyDiscoverySession();
- BluetoothDevice* device = SimulateLowEnergyDevice(1);
- ASSERT_TRUE(ConnectGatt(device));
- EXPECT_FALSE(device->IsPaired());
- SimulateDisplayPin(device, "000001");
- StrictMock<MockPairingDelegate> pairing_delegate;
- EXPECT_CALL(pairing_delegate, ConfirmPasskey)
- .WillOnce([](BluetoothDevice* device, uint32_t passkey) {
- ASSERT_NE(device, nullptr);
- ASSERT_EQ(passkey, 1u);
- device->ConfirmPairing();
- });
- base::test::TestFuture<absl::optional<BluetoothDevice::ConnectErrorCode>>
- error_code_future;
- device->Pair(&pairing_delegate, error_code_future.GetCallback());
- EXPECT_FALSE(error_code_future.Get().has_value());
- EXPECT_TRUE(device->IsPaired());
- }
- TEST_P(BluetoothTestWinrtOnly, DevicePairRequestConfirmPinInvalid) {
- if (!PlatformSupportsLowEnergy()) {
- LOG(WARNING) << "Low Energy Bluetooth unavailable, skipping unit test.";
- return;
- }
- InitWithFakeAdapter();
- StartLowEnergyDiscoverySession();
- BluetoothDevice* device = SimulateLowEnergyDevice(1);
- ASSERT_TRUE(ConnectGatt(device));
- EXPECT_FALSE(device->IsPaired());
- SimulateDisplayPin(device, "1000000");
- StrictMock<MockPairingDelegate> pairing_delegate;
- EXPECT_CALL(pairing_delegate, ConfirmPasskey).Times(0);
- base::test::TestFuture<absl::optional<BluetoothDevice::ConnectErrorCode>>
- error_code_future;
- device->Pair(&pairing_delegate, error_code_future.GetCallback());
- EXPECT_EQ(error_code_future.Get(), BluetoothDevice::ERROR_AUTH_FAILED);
- EXPECT_FALSE(device->IsPaired());
- }
- #endif // BUILDFLAG(IS_WIN)
- // Verifies basic device properties, e.g. GetAddress, GetName, ...
- #if BUILDFLAG(IS_WIN)
- TEST_P(BluetoothTestWinrt, LowEnergyDeviceProperties) {
- #else
- TEST_F(BluetoothTest, LowEnergyDeviceProperties) {
- #endif
- if (!PlatformSupportsLowEnergy()) {
- LOG(WARNING) << "Low Energy Bluetooth unavailable, skipping unit test.";
- return;
- }
- InitWithFakeAdapter();
- StartLowEnergyDiscoverySession();
- BluetoothDevice* device = SimulateLowEnergyDevice(1);
- ASSERT_TRUE(device);
- // Bluetooth class information for BLE device is not available on Windows.
- #if !BUILDFLAG(IS_WIN)
- EXPECT_EQ(0x1F00u, device->GetBluetoothClass());
- #endif
- EXPECT_EQ(kTestDeviceAddress1, device->GetAddress());
- EXPECT_EQ(BluetoothDevice::VENDOR_ID_UNKNOWN, device->GetVendorIDSource());
- EXPECT_EQ(0, device->GetVendorID());
- EXPECT_EQ(0, device->GetProductID());
- EXPECT_EQ(0, device->GetDeviceID());
- EXPECT_EQ(base::UTF8ToUTF16(kTestDeviceName), device->GetNameForDisplay());
- EXPECT_FALSE(device->IsPaired());
- UUIDSet uuids = device->GetUUIDs();
- EXPECT_TRUE(base::Contains(uuids, BluetoothUUID(kTestUUIDGenericAccess)));
- EXPECT_TRUE(base::Contains(uuids, BluetoothUUID(kTestUUIDGenericAttribute)));
- }
- // Verifies that the device name can be populated by later advertisement
- // packets and is persistent.
- #if BUILDFLAG(IS_WIN)
- TEST_P(BluetoothTestWinrt, LowEnergyDeviceNameDelayed) {
- #else
- // This test does not yet pass on any other platform.
- TEST_F(BluetoothTest, DISABLED_LowEnergyDeviceNameDelayed) {
- #endif
- if (!PlatformSupportsLowEnergy()) {
- LOG(WARNING) << "Low Energy Bluetooth unavailable, skipping unit test.";
- return;
- }
- InitWithFakeAdapter();
- StartLowEnergyDiscoverySession();
- BluetoothDevice* device = SimulateLowEnergyDevice(3);
- ASSERT_TRUE(device);
- // GetName() returns a absl::optional<std:string> however some backends still
- // return an empty string rather than nullopt when no name is available.
- EXPECT_TRUE(!device->GetName().has_value() || device->GetName()->empty());
- SimulateLowEnergyDevice(1);
- EXPECT_EQ(base::UTF8ToUTF16(kTestDeviceName), device->GetNameForDisplay());
- }
- // Device with no advertised Service UUIDs.
- #if BUILDFLAG(IS_WIN)
- TEST_P(BluetoothTestWinrt, LowEnergyDeviceNoUUIDs) {
- #else
- TEST_F(BluetoothTest, LowEnergyDeviceNoUUIDs) {
- #endif
- if (!PlatformSupportsLowEnergy()) {
- LOG(WARNING) << "Low Energy Bluetooth unavailable, skipping unit test.";
- return;
- }
- InitWithFakeAdapter();
- StartLowEnergyDiscoverySession();
- BluetoothDevice* device = SimulateLowEnergyDevice(3);
- ASSERT_TRUE(device);
- UUIDSet uuids = device->GetUUIDs();
- EXPECT_EQ(0u, uuids.size());
- }
- #if BUILDFLAG(IS_MAC) || BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_LINUX) || \
- BUILDFLAG(IS_ANDROID)
- #define MAYBE_GetServiceDataUUIDs_GetServiceDataForUUID \
- GetServiceDataUUIDs_GetServiceDataForUUID
- #else
- #define MAYBE_GetServiceDataUUIDs_GetServiceDataForUUID \
- DISABLED_GetServiceDataUUIDs_GetServiceDataForUUID
- #endif
- #if BUILDFLAG(IS_WIN)
- TEST_P(BluetoothTestWinrtOnly, GetServiceDataUUIDs_GetServiceDataForUUID) {
- #else
- TEST_F(BluetoothTest, MAYBE_GetServiceDataUUIDs_GetServiceDataForUUID) {
- #endif
- if (!PlatformSupportsLowEnergy()) {
- LOG(WARNING) << "Low Energy Bluetooth unavailable, skipping unit test.";
- return;
- }
- InitWithFakeAdapter();
- #if !BUILDFLAG(IS_LINUX) && !BUILDFLAG(IS_CHROMEOS)
- // TODO(crbug.com/706043): Remove #if once StartLowEnergyDiscoverySession is
- // implemented for bluez.
- StartLowEnergyDiscoverySession();
- #endif // !BUILDFLAG(IS_LINUX) && !BUILDFLAG(IS_CHROMEOS)
- // Receive Advertisement with empty service data.
- BluetoothDevice* device1 = SimulateLowEnergyDevice(4);
- EXPECT_FALSE(device1->GetAdvertisingDataFlags().has_value());
- EXPECT_TRUE(device1->GetServiceData().empty());
- EXPECT_TRUE(device1->GetServiceDataUUIDs().empty());
- EXPECT_TRUE(device1->GetManufacturerData().empty());
- // Receive Advertisement with service data.
- BluetoothDevice* device2 = SimulateLowEnergyDevice(1);
- #if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_ANDROID)
- EXPECT_TRUE(device2->GetAdvertisingDataFlags().has_value());
- EXPECT_EQ(0x04, device2->GetAdvertisingDataFlags().value());
- #endif
- EXPECT_EQ(ServiceDataMap({{BluetoothUUID(kTestUUIDHeartRate), {1}}}),
- device2->GetServiceData());
- EXPECT_EQ(UUIDSet({BluetoothUUID(kTestUUIDHeartRate)}),
- device2->GetServiceDataUUIDs());
- EXPECT_EQ(std::vector<uint8_t>({1}),
- *device2->GetServiceDataForUUID(BluetoothUUID(kTestUUIDHeartRate)));
- EXPECT_EQ(std::vector<uint8_t>({1, 2, 3, 4}),
- *device2->GetManufacturerDataForID(kTestManufacturerId));
- // Receive Advertisement with no flags and no service and manufacturer data.
- SimulateLowEnergyDevice(3);
- // TODO(crbug.com/707039): Remove #if once the BlueZ caching behavior is
- // changed.
- #if (BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_LINUX)) && \
- !defined(USE_CAST_BLUETOOTH_ADAPTER)
- // On ChromeOS and Linux, BlueZ persists all service data meaning if
- // a device stops advertising service data for a UUID, BlueZ will
- // still return the cached value for that UUID.
- EXPECT_EQ(ServiceDataMap({{BluetoothUUID(kTestUUIDHeartRate), {1}}}),
- device2->GetServiceData());
- EXPECT_EQ(UUIDSet({BluetoothUUID(kTestUUIDHeartRate)}),
- device2->GetServiceDataUUIDs());
- EXPECT_EQ(std::vector<uint8_t>({1}),
- *device2->GetServiceDataForUUID(BluetoothUUID(kTestUUIDHeartRate)));
- #else
- EXPECT_FALSE(device2->GetAdvertisingDataFlags().has_value());
- EXPECT_TRUE(device2->GetServiceData().empty());
- EXPECT_TRUE(device2->GetServiceDataUUIDs().empty());
- EXPECT_TRUE(device2->GetManufacturerData().empty());
- EXPECT_EQ(nullptr,
- device2->GetServiceDataForUUID(BluetoothUUID(kTestUUIDHeartRate)));
- #endif
- // Receive Advertisement with new service data and empty manufacturer data.
- SimulateLowEnergyDevice(2);
- #if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_ANDROID)
- EXPECT_TRUE(device2->GetAdvertisingDataFlags().has_value());
- EXPECT_EQ(0x05, device2->GetAdvertisingDataFlags().value());
- #endif
- EXPECT_EQ(ServiceDataMap(
- {{BluetoothUUID(kTestUUIDHeartRate), std::vector<uint8_t>({})},
- {BluetoothUUID(kTestUUIDImmediateAlert), {0, 2}}}),
- device2->GetServiceData());
- EXPECT_EQ(UUIDSet({BluetoothUUID(kTestUUIDHeartRate),
- BluetoothUUID(kTestUUIDImmediateAlert)}),
- device2->GetServiceDataUUIDs());
- EXPECT_EQ(std::vector<uint8_t>({}),
- *device2->GetServiceDataForUUID(BluetoothUUID(kTestUUIDHeartRate)));
- EXPECT_EQ(std::vector<uint8_t>({}),
- *device2->GetManufacturerDataForID(kTestManufacturerId));
- EXPECT_EQ(
- std::vector<uint8_t>({0, 2}),
- *device2->GetServiceDataForUUID(BluetoothUUID(kTestUUIDImmediateAlert)));
- #if !BUILDFLAG(IS_LINUX) && !BUILDFLAG(IS_CHROMEOS)
- // TODO(crbug.com/706043): Remove #if once StartLowEnergyDiscoverySession is
- // implemented for bluez.
- // Stop discovery.
- discovery_sessions_[0]->Stop(GetCallback(Call::EXPECTED),
- GetErrorCallback(Call::NOT_EXPECTED));
- base::RunLoop().RunUntilIdle();
- ASSERT_FALSE(adapter_->IsDiscovering());
- ASSERT_FALSE(discovery_sessions_[0]->IsActive());
- EXPECT_FALSE(device2->GetAdvertisingDataFlags().has_value());
- EXPECT_TRUE(device2->GetServiceData().empty());
- EXPECT_TRUE(device2->GetServiceDataUUIDs().empty());
- EXPECT_EQ(nullptr,
- device2->GetServiceDataForUUID(BluetoothUUID(kTestUUIDHeartRate)));
- EXPECT_EQ(nullptr, device2->GetServiceDataForUUID(
- BluetoothUUID(kTestUUIDImmediateAlert)));
- #endif // !BUILDFLAG(IS_LINUX) && !BUILDFLAG(IS_CHROMEOS)
- }
- #if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_MAC)
- #define MAYBE_AdvertisementData_Discovery AdvertisementData_Discovery
- #else
- #define MAYBE_AdvertisementData_Discovery DISABLED_AdvertisementData_Discovery
- #endif
- // Tests that the Advertisement Data fields are correctly updated during
- // discovery.
- #if BUILDFLAG(IS_WIN)
- TEST_P(BluetoothTestWinrtOnly, AdvertisementData_Discovery) {
- #else
- TEST_F(BluetoothTest, MAYBE_AdvertisementData_Discovery) {
- #endif
- if (!PlatformSupportsLowEnergy()) {
- LOG(WARNING) << "Low Energy Bluetooth unavailable, skipping unit test.";
- return;
- }
- InitWithFakeAdapter();
- TestBluetoothAdapterObserver observer(adapter_);
- // Start Discovery Session and receive Advertisement, should
- // not notify of device changed because the device is new.
- // - GetInquiryRSSI: Should return the packet's rssi.
- // - GetAdvertisingDataFlags: Should return advertised flags.
- // - GetUUIDs: Should return Advertised UUIDs.
- // - GetServiceData: Should return advertised Service Data.
- // - GetInquiryTxPower: Should return the packet's advertised Tx Power.
- StartLowEnergyDiscoverySession();
- BluetoothDevice* device = SimulateLowEnergyDevice(1);
- EXPECT_EQ(0, observer.device_changed_count());
- EXPECT_EQ(ToInt8(TestRSSI::LOWEST), device->GetInquiryRSSI().value());
- #if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_ANDROID)
- EXPECT_TRUE(device->GetAdvertisingDataFlags().has_value());
- EXPECT_EQ(0x04, device->GetAdvertisingDataFlags().value());
- #endif
- EXPECT_EQ(UUIDSet({BluetoothUUID(kTestUUIDGenericAccess),
- BluetoothUUID(kTestUUIDGenericAttribute)}),
- device->GetUUIDs());
- EXPECT_EQ(ServiceDataMap({{BluetoothUUID(kTestUUIDHeartRate), {1}}}),
- device->GetServiceData());
- EXPECT_EQ(ManufacturerDataMap({{kTestManufacturerId, {1, 2, 3, 4}}}),
- device->GetManufacturerData());
- EXPECT_EQ(ToInt8(TestTxPower::LOWEST), device->GetInquiryTxPower().value());
- // Receive Advertisement with no flags, no UUIDs, Service Data, or Tx Power,
- // should notify device changed.
- // - GetInquiryRSSI: Should return packet's rssi.
- // - GetAdvertisingDataFlags: Should return nullopt because of no flags.
- // - GetUUIDs: Should return no UUIDs.
- // - GetServiceData: Should return empty map.
- // - GetInquiryTxPower: Should return nullopt because of no Tx Power.
- SimulateLowEnergyDevice(3);
- EXPECT_EQ(1, observer.device_changed_count());
- EXPECT_EQ(ToInt8(TestRSSI::LOW), device->GetInquiryRSSI().value());
- EXPECT_FALSE(device->GetAdvertisingDataFlags().has_value());
- EXPECT_TRUE(device->GetUUIDs().empty());
- EXPECT_TRUE(device->GetServiceData().empty());
- EXPECT_TRUE(device->GetManufacturerData().empty());
- EXPECT_FALSE(device->GetInquiryTxPower());
- // Receive Advertisement with different UUIDs, Service Data, and Tx Power,
- // should notify device changed.
- // - GetInquiryRSSI: Should return last packet's rssi.
- // - GetAdvertisingDataFlags: Should return last advertised flags.
- // - GetUUIDs: Should return latest Advertised UUIDs.
- // - GetServiceData: Should return last advertised Service Data.
- // - GetInquiryTxPower: Should return last advertised Tx Power.
- SimulateLowEnergyDevice(2);
- EXPECT_EQ(2, observer.device_changed_count());
- EXPECT_EQ(ToInt8(TestRSSI::LOWER), device->GetInquiryRSSI().value());
- #if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_ANDROID)
- EXPECT_TRUE(device->GetAdvertisingDataFlags().has_value());
- EXPECT_EQ(0x05, device->GetAdvertisingDataFlags().value());
- #endif
- EXPECT_EQ(UUIDSet({BluetoothUUID(kTestUUIDImmediateAlert),
- BluetoothUUID(kTestUUIDLinkLoss)}),
- device->GetUUIDs());
- EXPECT_EQ(ServiceDataMap(
- {{BluetoothUUID(kTestUUIDHeartRate), std::vector<uint8_t>({})},
- {BluetoothUUID(kTestUUIDImmediateAlert), {0, 2}}}),
- device->GetServiceData());
- EXPECT_EQ(ManufacturerDataMap({{kTestManufacturerId, {}}}),
- device->GetManufacturerData());
- EXPECT_EQ(ToInt8(TestTxPower::LOWER), device->GetInquiryTxPower().value());
- // Stop discovery session, should notify of device changed.
- // - GetInquiryRSSI: Should return nullopt because we are no longer
- // discovering.
- // - GetAdvertisingDataFlags: Should return no flags.
- // - GetUUIDs: Should not return any UUIDs.
- // - GetServiceData: Should return empty map.
- // - GetMAnufacturerData: Should return empty map.
- // - GetInquiryTxPower: Should return nullopt because we are no longer
- // discovering.
- discovery_sessions_[0]->Stop(GetCallback(Call::EXPECTED),
- GetErrorCallback(Call::NOT_EXPECTED));
- base::RunLoop().RunUntilIdle();
- ASSERT_FALSE(adapter_->IsDiscovering());
- ASSERT_FALSE(discovery_sessions_[0]->IsActive());
- EXPECT_EQ(3, observer.device_changed_count());
- EXPECT_FALSE(device->GetInquiryRSSI());
- EXPECT_FALSE(device->GetAdvertisingDataFlags().has_value());
- EXPECT_TRUE(device->GetUUIDs().empty());
- EXPECT_TRUE(device->GetServiceData().empty());
- EXPECT_TRUE(device->GetManufacturerData().empty());
- EXPECT_FALSE(device->GetInquiryTxPower());
- // Discover the device again with different UUIDs, should notify of device
- // changed.
- // - GetInquiryRSSI: Should return last packet's rssi.
- // - GetAdvertisingDataFlags: Should return last advertised flags.
- // - GetUUIDs: Should return only the latest Advertised UUIDs.
- // - GetServiceData: Should return last advertise Service Data.
- // - GetInquiryTxPower: Should return last advertised Tx Power.
- StartLowEnergyDiscoverySession();
- device = SimulateLowEnergyDevice(1);
- EXPECT_EQ(4, observer.device_changed_count());
- EXPECT_EQ(ToInt8(TestRSSI::LOWEST), device->GetInquiryRSSI().value());
- #if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_ANDROID)
- EXPECT_TRUE(device->GetAdvertisingDataFlags().has_value());
- EXPECT_EQ(0x04, device->GetAdvertisingDataFlags().value());
- #endif
- EXPECT_EQ(UUIDSet({BluetoothUUID(kTestUUIDGenericAccess),
- BluetoothUUID(kTestUUIDGenericAttribute)}),
- device->GetUUIDs());
- EXPECT_EQ(ServiceDataMap({{BluetoothUUID(kTestUUIDHeartRate), {1}}}),
- device->GetServiceData());
- EXPECT_EQ(ManufacturerDataMap({{kTestManufacturerId, {1, 2, 3, 4}}}),
- device->GetManufacturerData());
- EXPECT_EQ(ToInt8(TestTxPower::LOWEST), device->GetInquiryTxPower().value());
- }
- // TODO(dougt) As I turn on new platforms for WebBluetooth Scanning,
- // I will relax this #ifdef
- #if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_WIN)
- #define MAYBE_DeviceAdvertisementReceived DeviceAdvertisementReceived
- #else
- #define MAYBE_DeviceAdvertisementReceived DISABLED_DeviceAdvertisementReceived
- #endif
- // Tests that the Bluetooth adapter observer is notified when a device
- // advertisement is received.
- #if BUILDFLAG(IS_WIN)
- TEST_P(BluetoothTestWinrtOnly, DeviceAdvertisementReceived) {
- #else
- TEST_F(BluetoothTest, MAYBE_DeviceAdvertisementReceived) {
- #endif
- if (!PlatformSupportsLowEnergy()) {
- LOG(WARNING) << "Low Energy Bluetooth unavailable, skipping unit test.";
- return;
- }
- InitWithFakeAdapter();
- TestBluetoothAdapterObserver observer(adapter_);
- StartLowEnergyDiscoverySession();
- SimulateLowEnergyDevice(1);
- ASSERT_EQ(1, observer.device_advertisement_raw_received_count());
- EXPECT_EQ(kTestDeviceName, observer.last_device_name().value_or(""));
- EXPECT_EQ(kTestDeviceName, observer.last_advertisement_name().value_or(""));
- EXPECT_EQ(static_cast<int>(TestRSSI::LOWEST),
- observer.last_rssi().value_or(-1));
- EXPECT_EQ(static_cast<int>(TestTxPower::LOWEST),
- observer.last_tx_power().value_or(-1));
- // BluetoothDevice::GetAppearance() is not implemented on all platforms.
- // TODO(crbug.com/588083): Check this property when it is implemented.
- const device::BluetoothDevice::UUIDList kTestAdvertisedUUIDs = {
- BluetoothUUID(kTestUUIDGenericAccess),
- BluetoothUUID(kTestUUIDGenericAttribute)};
- EXPECT_EQ(kTestAdvertisedUUIDs, observer.last_advertised_uuids());
- const device::BluetoothDevice::ServiceDataMap kTestServiceDataMap = {
- {BluetoothUUID(kTestUUIDHeartRate), {1}}};
- EXPECT_EQ(kTestServiceDataMap, observer.last_service_data_map());
- const device::BluetoothDevice::ManufacturerDataMap kTestManufacturerDataMap =
- {{kTestManufacturerId, {1, 2, 3, 4}}};
- EXPECT_EQ(kTestManufacturerDataMap, observer.last_manufacturer_data_map());
- // Double check that we can receive another advertisement.
- SimulateLowEnergyDevice(2);
- EXPECT_EQ(2, observer.device_advertisement_raw_received_count());
- }
- #if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_MAC)
- #define MAYBE_GetUUIDs_Connection GetUUIDs_Connection
- #else
- #define MAYBE_GetUUIDs_Connection DISABLED_GetUUIDs_Connection
- #endif
- // Tests Advertisement Data is updated correctly during a connection.
- #if BUILDFLAG(IS_WIN)
- TEST_P(BluetoothTestWinrtOnly, GetUUIDs_Connection) {
- #else
- TEST_F(BluetoothTest, MAYBE_GetUUIDs_Connection) {
- #endif
- if (!PlatformSupportsLowEnergy()) {
- LOG(WARNING) << "Low Energy Bluetooth unavailable, skipping unit test.";
- return;
- }
- InitWithFakeAdapter();
- TestBluetoothAdapterObserver observer(adapter_);
- StartLowEnergyDiscoverySession();
- BluetoothDevice* device = SimulateLowEnergyDevice(1);
- discovery_sessions_[0]->Stop(GetCallback(Call::EXPECTED),
- GetErrorCallback(Call::NOT_EXPECTED));
- // Connect to the device.
- // - GetUUIDs: Should return no UUIDs because Services have not been
- // discovered.
- ASSERT_TRUE(ConnectGatt(device));
- ASSERT_TRUE(device->IsConnected());
- EXPECT_TRUE(device->GetUUIDs().empty());
- observer.Reset();
- // Discover services, should notify of device changed.
- // - GetUUIDs: Should return the device's services' UUIDs.
- std::vector<std::string> services;
- services.push_back(kTestUUIDGenericAccess);
- SimulateGattServicesDiscovered(device, services);
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(1, observer.device_changed_count());
- EXPECT_EQ(UUIDSet({BluetoothUUID(kTestUUIDGenericAccess)}),
- device->GetUUIDs());
- #if BUILDFLAG(IS_MAC) || BUILDFLAG(IS_WIN)
- // TODO(ortuno): Enable in Android and classic Windows.
- // Android and Windows don't yet support service changed events.
- // http://crbug.com/548280
- // http://crbug.com/579202
- observer.Reset();
- // Notify of services changed, should notify of device changed.
- // - GetUUIDs: Should return no UUIDs because we no longer know what services
- // the device has.
- SimulateGattServicesChanged(device);
- ASSERT_FALSE(device->IsGattServicesDiscoveryComplete());
- EXPECT_EQ(1, observer.device_changed_count());
- EXPECT_TRUE(device->GetUUIDs().empty());
- // Services discovered again, should notify of device changed.
- // - GetUUIDs: Should return Service UUIDs.
- SimulateGattServicesDiscovered(device, {} /* services */);
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(2, observer.device_changed_count());
- EXPECT_EQ(UUIDSet({BluetoothUUID(kTestUUIDGenericAccess)}),
- device->GetUUIDs());
- #endif // BUILDFLAG(IS_MAC) || BUILDFLAG(IS_WIN)
- observer.Reset();
- // Disconnect, should notify device changed.
- // - GetUUIDs: Should return no UUIDs since we no longer know what services
- // the device holds and notify of device changed.
- gatt_connections_[0]->Disconnect();
- SimulateGattDisconnection(device);
- base::RunLoop().RunUntilIdle();
- ASSERT_FALSE(device->IsGattConnected());
- EXPECT_EQ(1, observer.device_changed_count());
- EXPECT_TRUE(device->GetUUIDs().empty());
- }
- #if BUILDFLAG(IS_MAC)
- // Tests that receiving 2 notifications in a row from macOS that services has
- // changed is handled correctly. Each notification should generate a
- // notification that the gatt device has changed, and each notification should
- // ask to macOS to scan for services. Only after the second service scan is
- // received, the device changed notification should be sent and the
- // characteristic discovery procedure should be started.
- // Android: This test doesn't apply to Android because there is no services
- // changed event that could arrive during a discovery procedure.
- TEST_F(BluetoothTest, TwoPendingServiceDiscoveryRequests) {
- if (!PlatformSupportsLowEnergy()) {
- LOG(WARNING) << "Low Energy Bluetooth unavailable, skipping unit test.";
- return;
- }
- InitWithFakeAdapter();
- TestBluetoothAdapterObserver observer(adapter_);
- BluetoothDevice* device = SimulateLowEnergyDevice(1);
- ASSERT_TRUE(ConnectGatt(device));
- EXPECT_EQ(1, observer.device_changed_count());
- EXPECT_FALSE(device->IsGattServicesDiscoveryComplete());
- observer.Reset();
- SimulateGattServicesChanged(device);
- EXPECT_EQ(1, observer.device_changed_count());
- EXPECT_FALSE(device->IsGattServicesDiscoveryComplete());
- // First system call to
- // -[id<CBPeripheralDelegate> peripheral:didDiscoverServices:] using
- // SimulateDidDiscoverServicesMac().
- observer.Reset();
- AddServicesToDeviceMac(device, {kTestUUIDHeartRate});
- SimulateDidDiscoverServicesMac(device);
- EXPECT_EQ(0, observer.device_changed_count());
- EXPECT_FALSE(device->IsGattServicesDiscoveryComplete());
- EXPECT_EQ(gatt_characteristic_discovery_attempts_, 0);
- // Second system call to
- // -[id<CBPeripheralDelegate> peripheral:didDiscoverServices:] using the
- // generic call to SimulateGattServicesDiscovered(). This method triggers
- // the full discovery cycles (services, characteristics and descriptors),
- // which includes -[id<CBPeripheralDelegate> peripheral:didDiscoverServices:].
- SimulateGattServicesDiscovered(
- device, std::vector<std::string>({kTestUUIDImmediateAlert}));
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(1, observer.device_changed_count());
- EXPECT_TRUE(device->IsGattServicesDiscoveryComplete());
- // Characteristics are discovered once for each service.
- EXPECT_EQ(gatt_characteristic_discovery_attempts_, 2);
- EXPECT_EQ(2u, device->GetGattServices().size());
- }
- // Simulate an unexpected call to -[id<CBPeripheralDelegate>
- // peripheral:didDiscoverServices:]. This should not happen, but if it does
- // (buggy device?), a discovery cycle should be done.
- TEST_F(BluetoothTest, ExtraDidDiscoverServicesCall) {
- if (!PlatformSupportsLowEnergy()) {
- LOG(WARNING) << "Low Energy Bluetooth unavailable, skipping unit test.";
- return;
- }
- InitWithFakeAdapter();
- TestBluetoothAdapterObserver observer(adapter_);
- BluetoothDevice* device = SimulateLowEnergyDevice(1);
- ASSERT_TRUE(ConnectGatt(device));
- EXPECT_EQ(1, observer.device_changed_count());
- EXPECT_FALSE(device->IsGattServicesDiscoveryComplete());
- // Legitimate system call to
- // -[id<CBPeripheralDelegate> peripheral:didDiscoverServices:].
- observer.Reset();
- SimulateGattServicesDiscovered(
- device, std::vector<std::string>({kTestUUIDHeartRate}));
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(1, observer.device_changed_count());
- EXPECT_TRUE(device->IsGattServicesDiscoveryComplete());
- EXPECT_EQ(gatt_characteristic_discovery_attempts_, 1);
- EXPECT_EQ(1u, device->GetGattServices().size());
- // Unexpected system call to
- // -[id<CBPeripheralDelegate> peripheral:didDiscoverServices:]:
- // This system call is expected only once after -[CBCentralManager
- // discoverServices:]. The call to -[CBCentralManager discoverServices:] and
- // its answer with -[id<CBPeripheralDelegate> peripheral:didDiscoverServices:]
- // is done with SimulateGattServicesDiscovered(). So a second system call to
- // -[id<CBPeripheralDelegate> peripheral:didDiscoverServices:] is not expected
- // and should be ignored.
- AddServicesToDeviceMac(device, {kTestUUIDImmediateAlert});
- SimulateDidDiscoverServicesMac(device);
- EXPECT_EQ(1, observer.device_changed_count());
- EXPECT_TRUE(device->IsGattServicesDiscoveryComplete());
- EXPECT_EQ(1u, device->GetGattServices().size());
- }
- #endif
- #if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_MAC)
- #define MAYBE_AdvertisementData_DiscoveryDuringConnection \
- AdvertisementData_DiscoveryDuringConnection
- #else
- #define MAYBE_AdvertisementData_DiscoveryDuringConnection \
- DISABLED_AdvertisementData_DiscoveryDuringConnection
- #endif
- // Tests Advertisement Data is updated correctly when we start discovery
- // during a connection.
- #if BUILDFLAG(IS_WIN)
- TEST_P(BluetoothTestWinrtOnly, AdvertisementData_DiscoveryDuringConnection) {
- #else
- TEST_F(BluetoothTest, MAYBE_AdvertisementData_DiscoveryDuringConnection) {
- #endif
- if (!PlatformSupportsLowEnergy()) {
- LOG(WARNING) << "Low Energy Bluetooth unavailable, skipping unit test.";
- return;
- }
- InitWithFakeAdapter();
- TestBluetoothAdapterObserver observer(adapter_);
- StartLowEnergyDiscoverySession();
- BluetoothDevice* device = SimulateLowEnergyDevice(1);
- EXPECT_EQ(UUIDSet({BluetoothUUID(kTestUUIDGenericAccess),
- BluetoothUUID(kTestUUIDGenericAttribute)}),
- device->GetUUIDs());
- discovery_sessions_[0]->Stop(GetCallback(Call::EXPECTED),
- GetErrorCallback(Call::NOT_EXPECTED));
- base::RunLoop().RunUntilIdle();
- ASSERT_FALSE(adapter_->IsDiscovering());
- ASSERT_FALSE(discovery_sessions_[0]->IsActive());
- ASSERT_EQ(0u, device->GetUUIDs().size());
- discovery_sessions_.clear();
- // Connect.
- ASSERT_TRUE(ConnectGatt(device));
- ASSERT_TRUE(device->IsConnected());
- observer.Reset();
- // Start Discovery and receive advertisement during connection,
- // should notify of device changed.
- // - GetInquiryRSSI: Should return the packet's rssi.
- // - GetAdvertisingDataFlags: Should return last advertised flags.
- // - GetUUIDs: Should return only Advertised UUIDs since services haven't
- // been discovered yet.
- // - GetServiceData: Should return last advertised Service Data.
- // - GetInquiryTxPower: Should return the packet's advertised Tx Power.
- StartLowEnergyDiscoverySession();
- ASSERT_TRUE(adapter_->IsDiscovering());
- ASSERT_TRUE(discovery_sessions_[0]->IsActive());
- device = SimulateLowEnergyDevice(1);
- EXPECT_EQ(1, observer.device_changed_count());
- EXPECT_EQ(ToInt8(TestRSSI::LOWEST), device->GetInquiryRSSI().value());
- EXPECT_EQ(UUIDSet({BluetoothUUID(kTestUUIDGenericAccess),
- BluetoothUUID(kTestUUIDGenericAttribute)}),
- device->GetUUIDs());
- #if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_ANDROID)
- EXPECT_TRUE(device->GetAdvertisingDataFlags().has_value());
- EXPECT_EQ(0x04, device->GetAdvertisingDataFlags().value());
- #endif
- EXPECT_EQ(ServiceDataMap({{BluetoothUUID(kTestUUIDHeartRate), {1}}}),
- device->GetServiceData());
- EXPECT_EQ(ToInt8(TestTxPower::LOWEST), device->GetInquiryTxPower().value());
- // Discover services, should notify of device changed.
- // - GetUUIDs: Should return both Advertised UUIDs and Service UUIDs.
- std::vector<std::string> services;
- services.push_back(kTestUUIDHeartRate);
- SimulateGattServicesDiscovered(device, services);
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(2, observer.device_changed_count());
- EXPECT_EQ(UUIDSet({BluetoothUUID(kTestUUIDGenericAccess),
- BluetoothUUID(kTestUUIDGenericAttribute),
- BluetoothUUID(kTestUUIDHeartRate)}),
- device->GetUUIDs());
- // Receive advertisement again, notify of device changed.
- // - GetInquiryRSSI: Should return last packet's rssi.
- // - GetAdvertisingDataFlags: Should return last advertised flags.
- // - GetUUIDs: Should return only new Advertised UUIDs and Service UUIDs.
- // - GetServiceData: Should return last advertised Service Data.
- // - GetInquiryTxPower: Should return the last packet's advertised Tx Power.
- device = SimulateLowEnergyDevice(2);
- EXPECT_EQ(3, observer.device_changed_count());
- EXPECT_EQ(ToInt8(TestRSSI::LOWER), device->GetInquiryRSSI().value());
- #if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_ANDROID)
- EXPECT_TRUE(device->GetAdvertisingDataFlags().has_value());
- EXPECT_EQ(0x05, device->GetAdvertisingDataFlags().value());
- #endif
- EXPECT_EQ(UUIDSet({BluetoothUUID(kTestUUIDLinkLoss),
- BluetoothUUID(kTestUUIDImmediateAlert),
- BluetoothUUID(kTestUUIDHeartRate)}),
- device->GetUUIDs());
- EXPECT_EQ(ServiceDataMap(
- {{BluetoothUUID(kTestUUIDHeartRate), std::vector<uint8_t>({})},
- {BluetoothUUID(kTestUUIDImmediateAlert), {0, 2}}}),
- device->GetServiceData());
- EXPECT_EQ(ToInt8(TestTxPower::LOWER), device->GetInquiryTxPower().value());
- // Stop discovery session, should notify of device changed.
- // - GetInquiryRSSI: Should return nullopt because we are no longer
- // discovering.
- // - GetAdvertisingDataFlags: Should return no flags since we are no longer
- // discovering.
- // - GetUUIDs: Should only return Service UUIDs.
- // - GetServiceData: Should return an empty map since we are no longer
- // discovering.
- // - GetInquiryTxPower: Should return nullopt because we are no longer
- // discovering.
- discovery_sessions_[0]->Stop(GetCallback(Call::EXPECTED),
- GetErrorCallback(Call::NOT_EXPECTED));
- base::RunLoop().RunUntilIdle();
- ASSERT_FALSE(adapter_->IsDiscovering());
- ASSERT_FALSE(discovery_sessions_[0]->IsActive());
- EXPECT_EQ(4, observer.device_changed_count());
- EXPECT_FALSE(device->GetInquiryRSSI());
- EXPECT_FALSE(device->GetAdvertisingDataFlags().has_value());
- EXPECT_EQ(UUIDSet({BluetoothUUID(kTestUUIDHeartRate)}), device->GetUUIDs());
- EXPECT_EQ(ServiceDataMap(), device->GetServiceData());
- EXPECT_FALSE(device->GetInquiryTxPower());
- // Disconnect device, should notify of device changed.
- // - GetUUIDs: Should return no UUIDs.
- gatt_connections_[0]->Disconnect();
- SimulateGattDisconnection(device);
- base::RunLoop().RunUntilIdle();
- ASSERT_FALSE(device->IsGattConnected());
- EXPECT_EQ(5, observer.device_changed_count());
- EXPECT_TRUE(device->GetUUIDs().empty());
- }
- #if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_MAC)
- #define MAYBE_AdvertisementData_ConnectionDuringDiscovery \
- AdvertisementData_ConnectionDuringDiscovery
- #else
- #define MAYBE_AdvertisementData_ConnectionDuringDiscovery \
- DISABLED_AdvertisementData_ConnectionDuringDiscovery
- #endif
- #if BUILDFLAG(IS_WIN)
- TEST_P(BluetoothTestWinrtOnly, AdvertisementData_ConnectionDuringDiscovery) {
- #else
- TEST_F(BluetoothTest, MAYBE_AdvertisementData_ConnectionDuringDiscovery) {
- #endif
- // Tests that the Advertisement Data is correctly updated when
- // the device connects during discovery.
- if (!PlatformSupportsLowEnergy()) {
- LOG(WARNING) << "Low Energy Bluetooth unavailable, skipping unit test.";
- return;
- }
- InitWithFakeAdapter();
- TestBluetoothAdapterObserver observer(adapter_);
- // Start discovery session and receive and advertisement. No device changed
- // notification because it's a new device.
- // - GetInquiryRSSI: Should return the packet's rssi.
- // - GetAdvertisingDataFlags: Should return advertised flags.
- // - GetUUIDs: Should return Advertised UUIDs.
- // - GetServiceData: Should return advertised Service Data.
- // - GetInquiryTxPower: Should return the packet's advertised Tx Power.
- StartLowEnergyDiscoverySession();
- ASSERT_TRUE(adapter_->IsDiscovering());
- ASSERT_TRUE(discovery_sessions_[0]->IsActive());
- BluetoothDevice* device = SimulateLowEnergyDevice(1);
- EXPECT_EQ(0, observer.device_changed_count());
- EXPECT_EQ(ToInt8(TestRSSI::LOWEST), device->GetInquiryRSSI().value());
- #if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_ANDROID)
- EXPECT_TRUE(device->GetAdvertisingDataFlags().has_value());
- EXPECT_EQ(0x04, device->GetAdvertisingDataFlags().value());
- #endif
- EXPECT_EQ(UUIDSet({BluetoothUUID(kTestUUIDGenericAccess),
- BluetoothUUID(kTestUUIDGenericAttribute)}),
- device->GetUUIDs());
- EXPECT_EQ(ServiceDataMap({{BluetoothUUID(kTestUUIDHeartRate), {1}}}),
- device->GetServiceData());
- EXPECT_EQ(ToInt8(TestTxPower::LOWEST), device->GetInquiryTxPower().value());
- // Connect, should notify of device changed.
- // - GetUUIDs: Should return Advertised UUIDs even before GATT Discovery.
- ASSERT_TRUE(ConnectGatt(device));
- ASSERT_TRUE(device->IsConnected());
- observer.Reset();
- EXPECT_EQ(UUIDSet({BluetoothUUID(kTestUUIDGenericAccess),
- BluetoothUUID(kTestUUIDGenericAttribute)}),
- device->GetUUIDs());
- // Receive Advertisement with new UUIDs, should notify of device changed.
- // - GetInquiryRSSI: Should return the packet's rssi.
- // - GetAdvertisingDataFlags: Should return advertised flags.
- // - GetUUIDs: Should return new Advertised UUIDs.
- // - GetServiceData: Should return new advertised Service Data.
- // - GetInquiryTxPower: Should return the packet's advertised Tx Power.
- device = SimulateLowEnergyDevice(2);
- EXPECT_EQ(1, observer.device_changed_count());
- EXPECT_EQ(ToInt8(TestRSSI::LOWER), device->GetInquiryRSSI().value());
- #if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_ANDROID)
- EXPECT_TRUE(device->GetAdvertisingDataFlags().has_value());
- EXPECT_EQ(0x05, device->GetAdvertisingDataFlags().value());
- #endif
- EXPECT_EQ(UUIDSet({BluetoothUUID(kTestUUIDLinkLoss),
- BluetoothUUID(kTestUUIDImmediateAlert)}),
- device->GetUUIDs());
- EXPECT_EQ(ServiceDataMap(
- {{BluetoothUUID(kTestUUIDHeartRate), std::vector<uint8_t>({})},
- {BluetoothUUID(kTestUUIDImmediateAlert), {0, 2}}}),
- device->GetServiceData());
- EXPECT_EQ(ToInt8(TestTxPower::LOWER), device->GetInquiryTxPower().value());
- // Discover Services, should notify of device changed.
- // - GetUUIDs: Should return Advertised UUIDs and Service UUIDs.
- std::vector<std::string> services;
- services.push_back(kTestUUIDHeartRate);
- SimulateGattServicesDiscovered(device, services);
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(2, observer.device_changed_count());
- EXPECT_EQ(UUIDSet({BluetoothUUID(kTestUUIDLinkLoss),
- BluetoothUUID(kTestUUIDImmediateAlert),
- BluetoothUUID(kTestUUIDHeartRate)}),
- device->GetUUIDs());
- // Disconnect, should notify of device changed.
- // - GetInquiryRSSI: Should return last packet's rssi.
- // - GetAdvertisingDataFlags: Should return same advertised flags.
- // - GetUUIDs: Should return only Advertised UUIDs.
- // - GetServiceData: Should still return same advertised Service Data.
- // - GetInquiryTxPower: Should return the last packet's advertised Tx Power.
- gatt_connections_[0]->Disconnect();
- SimulateGattDisconnection(device);
- base::RunLoop().RunUntilIdle();
- ASSERT_FALSE(device->IsGattConnected());
- EXPECT_EQ(3, observer.device_changed_count());
- EXPECT_EQ(ToInt8(TestRSSI::LOWER), device->GetInquiryRSSI().value());
- #if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_ANDROID)
- EXPECT_TRUE(device->GetAdvertisingDataFlags().has_value());
- EXPECT_EQ(0x05, device->GetAdvertisingDataFlags().value());
- #endif
- EXPECT_EQ(UUIDSet({BluetoothUUID(kTestUUIDLinkLoss),
- BluetoothUUID(kTestUUIDImmediateAlert)}),
- device->GetUUIDs());
- EXPECT_EQ(ServiceDataMap(
- {{BluetoothUUID(kTestUUIDHeartRate), std::vector<uint8_t>({})},
- {BluetoothUUID(kTestUUIDImmediateAlert), {0, 2}}}),
- device->GetServiceData());
- EXPECT_EQ(ToInt8(TestTxPower::LOWER), device->GetInquiryTxPower().value());
- // Receive Advertisement with new UUIDs, should notify of device changed.
- // - GetInquiryRSSI: Should return last packet's rssi.
- // - GetAdvertisingDataFlags: Should return the new advertised flags.
- // - GetUUIDs: Should return only new Advertised UUIDs.
- // - GetServiceData: Should return only new advertised Service Data.
- // - GetInquiryTxPower: Should return the last packet's advertised Tx Power.
- device = SimulateLowEnergyDevice(1);
- EXPECT_EQ(4, observer.device_changed_count());
- EXPECT_EQ(ToInt8(TestRSSI::LOWEST), device->GetInquiryRSSI().value());
- #if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_ANDROID)
- EXPECT_TRUE(device->GetAdvertisingDataFlags().has_value());
- EXPECT_EQ(0x04, device->GetAdvertisingDataFlags().value());
- #endif
- EXPECT_EQ(UUIDSet({BluetoothUUID(kTestUUIDGenericAccess),
- BluetoothUUID(kTestUUIDGenericAttribute)}),
- device->GetUUIDs());
- EXPECT_EQ(ServiceDataMap({{BluetoothUUID(kTestUUIDHeartRate), {1}}}),
- device->GetServiceData());
- EXPECT_EQ(ToInt8(TestTxPower::LOWEST), device->GetInquiryTxPower().value());
- // Stop discovery session, should notify of device changed.
- // - GetInquiryRSSI: Should return nullopt because we are no longer
- // discovering.
- // - GetAdvertisingDataFlags: Should return no advertised flags since we are
- // no longer discovering.
- // - GetUUIDs: Should return no UUIDs.
- // - GetServiceData: Should return no UUIDs since we are no longer
- // discovering.
- // - GetInquiryTxPower: Should return nullopt because we are no longer
- // discovering.
- discovery_sessions_[0]->Stop(GetCallback(Call::EXPECTED),
- GetErrorCallback(Call::NOT_EXPECTED));
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(5, observer.device_changed_count());
- EXPECT_FALSE(device->GetInquiryRSSI());
- EXPECT_FALSE(device->GetAdvertisingDataFlags().has_value());
- EXPECT_TRUE(device->GetUUIDs().empty());
- EXPECT_TRUE(device->GetServiceData().empty());
- EXPECT_FALSE(device->GetInquiryTxPower());
- }
- #if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_MAC) || \
- BUILDFLAG(IS_LINUX)
- #define MAYBE_GetName_NullName GetName_NullName
- #else
- #define MAYBE_GetName_NullName DISABLED_GetName_NullName
- #endif
- // GetName for Device with no name.
- TEST_F(BluetoothTest, MAYBE_GetName_NullName) {
- if (!PlatformSupportsLowEnergy()) {
- LOG(WARNING) << "Low Energy Bluetooth unavailable, skipping unit test.";
- return;
- }
- InitWithFakeAdapter();
- // StartLowEnergyDiscoverySession is not yet implemented on ChromeOS|bluez,
- // and is non trivial to implement. On ChromeOS, it is not essential for
- // this test to operate, and so it is simply skipped. Android at least
- // does require this step.
- #if !BUILDFLAG(IS_CHROMEOS)
- StartLowEnergyDiscoverySession();
- #endif // !BUILDFLAG(IS_CHROMEOS)
- BluetoothDevice* device = SimulateLowEnergyDevice(5);
- EXPECT_FALSE(device->GetName());
- // The check below is not currently working on Android and Mac because the
- // GetAppearance() method is not implemented on those platforms.
- // TODO(https://crbug.com/588083): Enable the check below when GetAppearance()
- // is implemented for Android and Mac.
- #if !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_MAC)
- EXPECT_EQ(device->GetNameForDisplay(),
- u"Unknown or Unsupported Device (01:00:00:90:1E:BE)");
- #endif
- }
- #if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_MAC)
- #define MAYBE_CreateGattConnection CreateGattConnection
- #else
- #define MAYBE_CreateGattConnection DISABLED_CreateGattConnection
- #endif
- // Basic CreateGattConnection test.
- #if BUILDFLAG(IS_WIN)
- TEST_P(BluetoothTestWinrtOnly, CreateGattConnection) {
- #else
- TEST_F(BluetoothTest, MAYBE_CreateGattConnection) {
- #endif
- if (!PlatformSupportsLowEnergy()) {
- LOG(WARNING) << "Low Energy Bluetooth unavailable, skipping unit test.";
- return;
- }
- InitWithFakeAdapter();
- StartLowEnergyDiscoverySession();
- BluetoothDevice* device = SimulateLowEnergyDevice(3);
- ResetEventCounts();
- ASSERT_TRUE(ConnectGatt(device));
- ASSERT_EQ(1u, gatt_connections_.size());
- EXPECT_TRUE(device->IsGattConnected());
- EXPECT_TRUE(gatt_connections_[0]->IsConnected());
- }
- #if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_MAC)
- #define MAYBE_DisconnectionNotifiesDeviceChanged \
- DisconnectionNotifiesDeviceChanged
- #else
- #define MAYBE_DisconnectionNotifiesDeviceChanged \
- DISABLED_DisconnectionNotifiesDeviceChanged
- #endif
- #if BUILDFLAG(IS_WIN)
- TEST_P(BluetoothTestWinrtOnly, DisconnectionNotifiesDeviceChanged) {
- #else
- TEST_F(BluetoothTest, MAYBE_DisconnectionNotifiesDeviceChanged) {
- #endif
- if (!PlatformSupportsLowEnergy()) {
- LOG(WARNING) << "Low Energy Bluetooth unavailable, skipping unit test.";
- return;
- }
- InitWithFakeAdapter();
- TestBluetoothAdapterObserver observer(adapter_);
- StartLowEnergyDiscoverySession();
- BluetoothDevice* device = SimulateLowEnergyDevice(3);
- ASSERT_TRUE(ConnectGatt(device));
- EXPECT_EQ(1, observer.device_changed_count());
- EXPECT_TRUE(device->IsConnected());
- EXPECT_TRUE(device->IsGattConnected());
- SimulateDeviceBreaksConnection(device);
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(2, observer.device_changed_count());
- EXPECT_FALSE(device->IsConnected());
- EXPECT_FALSE(device->IsGattConnected());
- }
- #if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_MAC)
- #define MAYBE_BluetoothGattConnection BluetoothGattConnection
- #else
- #define MAYBE_BluetoothGattConnection DISABLED_BluetoothGattConnection
- #endif
- // Creates BluetoothGattConnection instances and tests that the interface
- // functions even when some Disconnect and the BluetoothDevice is destroyed.
- #if BUILDFLAG(IS_WIN)
- TEST_P(BluetoothTestWinrtOnly, BluetoothGattConnection) {
- #else
- TEST_F(BluetoothTest, MAYBE_BluetoothGattConnection) {
- #endif
- if (!PlatformSupportsLowEnergy()) {
- LOG(WARNING) << "Low Energy Bluetooth unavailable, skipping unit test.";
- return;
- }
- InitWithFakeAdapter();
- StartLowEnergyDiscoverySession();
- BluetoothDevice* device = SimulateLowEnergyDevice(3);
- std::string device_address = device->GetAddress();
- // CreateGattConnection
- ResetEventCounts();
- ASSERT_TRUE(ConnectGatt(device));
- ASSERT_EQ(1u, gatt_connections_.size());
- EXPECT_TRUE(device->IsGattConnected());
- EXPECT_TRUE(gatt_connections_[0]->IsConnected());
- // Connect again once already connected.
- ResetEventCounts();
- ASSERT_TRUE(ConnectGatt(device));
- ASSERT_TRUE(ConnectGatt(device));
- EXPECT_EQ(0, gatt_connection_attempts_);
- ASSERT_EQ(3u, gatt_connections_.size());
- // Test GetDeviceAddress
- EXPECT_EQ(device_address, gatt_connections_[0]->GetDeviceAddress());
- // Test IsConnected
- EXPECT_TRUE(gatt_connections_[0]->IsConnected());
- EXPECT_TRUE(gatt_connections_[1]->IsConnected());
- EXPECT_TRUE(gatt_connections_[2]->IsConnected());
- // Disconnect & Delete connection objects. Device stays connected.
- gatt_connections_[0]->Disconnect(); // Disconnect first.
- gatt_connections_.pop_back(); // Delete last.
- EXPECT_FALSE(gatt_connections_[0]->IsConnected());
- EXPECT_TRUE(gatt_connections_[1]->IsConnected());
- EXPECT_TRUE(device->IsGattConnected());
- EXPECT_EQ(0, gatt_disconnection_attempts_);
- // Delete device, connection objects should all be disconnected.
- gatt_disconnection_attempts_ = 0;
- DeleteDevice(device);
- EXPECT_EQ(1, gatt_disconnection_attempts_);
- EXPECT_FALSE(gatt_connections_[0]->IsConnected());
- EXPECT_FALSE(gatt_connections_[1]->IsConnected());
- // Test GetDeviceAddress after device deleted.
- EXPECT_EQ(device_address, gatt_connections_[0]->GetDeviceAddress());
- EXPECT_EQ(device_address, gatt_connections_[1]->GetDeviceAddress());
- }
- #if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_MAC)
- #define MAYBE_BluetoothGattConnection_ConnectWithMultipleOSConnections \
- BluetoothGattConnection_ConnectWithMultipleOSConnections
- #else
- #define MAYBE_BluetoothGattConnection_ConnectWithMultipleOSConnections \
- DISABLED_BluetoothGattConnection_ConnectWithMultipleOSConnections
- #endif
- // Calls CreateGattConnection then simulates multiple connections from platform.
- TEST_F(BluetoothTest,
- MAYBE_BluetoothGattConnection_ConnectWithMultipleOSConnections) {
- if (!PlatformSupportsLowEnergy()) {
- LOG(WARNING) << "Low Energy Bluetooth unavailable, skipping unit test.";
- return;
- }
- InitWithFakeAdapter();
- TestBluetoothAdapterObserver observer(adapter_);
- StartLowEnergyDiscoverySession();
- BluetoothDevice* device = SimulateLowEnergyDevice(3);
- // CreateGattConnection, & multiple connections from platform only invoke
- // callbacks once:
- ResetEventCounts();
- ASSERT_TRUE(
- ConnectGatt(device, /*service_uuid=*/absl::nullopt,
- base::BindLambdaForTesting([this](BluetoothDevice* device) {
- SimulateGattConnection(device);
- SimulateGattConnection(device);
- })));
- EXPECT_EQ(1, gatt_discovery_attempts_);
- EXPECT_EQ(1, observer.device_changed_count());
- EXPECT_EQ(1, gatt_connection_attempts_);
- EXPECT_TRUE(gatt_connections_[0]->IsConnected());
- // Become disconnected:
- SimulateGattDisconnection(device);
- base::RunLoop().RunUntilIdle();
- EXPECT_FALSE(gatt_connections_[0]->IsConnected());
- }
- #if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_MAC)
- #define MAYBE_BluetoothGattConnection_AlreadyConnected \
- BluetoothGattConnection_AlreadyConnected
- #else
- #define MAYBE_BluetoothGattConnection_AlreadyConnected \
- DISABLED_BluetoothGattConnection_AlreadyConnected
- #endif
- // Calls CreateGattConnection after already connected.
- #if BUILDFLAG(IS_WIN)
- TEST_P(BluetoothTestWinrtOnly, BluetoothGattConnection_AlreadyConnected) {
- #else
- TEST_F(BluetoothTest, MAYBE_BluetoothGattConnection_AlreadyConnected) {
- #endif
- if (!PlatformSupportsLowEnergy()) {
- LOG(WARNING) << "Low Energy Bluetooth unavailable, skipping unit test.";
- return;
- }
- InitWithFakeAdapter();
- StartLowEnergyDiscoverySession();
- BluetoothDevice* device = SimulateLowEnergyDevice(3);
- // Be already connected:
- ASSERT_TRUE(ConnectGatt(device));
- EXPECT_TRUE(gatt_connections_[0]->IsConnected());
- // Then CreateGattConnection:
- ResetEventCounts();
- ASSERT_TRUE(ConnectGatt(device));
- EXPECT_EQ(0, gatt_connection_attempts_);
- EXPECT_TRUE(gatt_connections_[1]->IsConnected());
- }
- #if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_MAC)
- #define MAYBE_BluetoothGattConnection_NewConnectionLeavesPreviousDisconnected \
- BluetoothGattConnection_NewConnectionLeavesPreviousDisconnected
- #else
- #define MAYBE_BluetoothGattConnection_NewConnectionLeavesPreviousDisconnected \
- DISABLED_BluetoothGattConnection_NewConnectionLeavesPreviousDisconnected
- #endif
- // Creates BluetoothGattConnection after one exists that has disconnected.
- #if BUILDFLAG(IS_WIN)
- TEST_P(BluetoothTestWinrtOnly,
- BluetoothGattConnection_NewConnectionLeavesPreviousDisconnected) {
- #else
- TEST_F(BluetoothTest,
- MAYBE_BluetoothGattConnection_NewConnectionLeavesPreviousDisconnected) {
- #endif
- if (!PlatformSupportsLowEnergy()) {
- LOG(WARNING) << "Low Energy Bluetooth unavailable, skipping unit test.";
- return;
- }
- InitWithFakeAdapter();
- StartLowEnergyDiscoverySession();
- BluetoothDevice* device = SimulateLowEnergyDevice(3);
- // Create connection:
- ASSERT_TRUE(ConnectGatt(device));
- // Disconnect connection:
- gatt_connections_[0]->Disconnect();
- SimulateGattDisconnection(device);
- base::RunLoop().RunUntilIdle();
- // Create 2nd connection:
- ASSERT_TRUE(ConnectGatt(device));
- EXPECT_FALSE(gatt_connections_[0]->IsConnected())
- << "The disconnected connection shouldn't become connected when another "
- "connection is created.";
- EXPECT_TRUE(gatt_connections_[1]->IsConnected());
- }
- #if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_MAC)
- #define MAYBE_BluetoothGattConnection_DisconnectWhenObjectsDestroyed \
- BluetoothGattConnection_DisconnectWhenObjectsDestroyed
- #else
- #define MAYBE_BluetoothGattConnection_DisconnectWhenObjectsDestroyed \
- DISABLED_BluetoothGattConnection_DisconnectWhenObjectsDestroyed
- #endif
- // Deletes BluetoothGattConnection causing disconnection.
- #if BUILDFLAG(IS_WIN)
- TEST_P(BluetoothTestWinrtOnly,
- BluetoothGattConnection_DisconnectWhenObjectsDestroyed) {
- #else
- TEST_F(BluetoothTest,
- MAYBE_BluetoothGattConnection_DisconnectWhenObjectsDestroyed) {
- #endif
- if (!PlatformSupportsLowEnergy()) {
- LOG(WARNING) << "Low Energy Bluetooth unavailable, skipping unit test.";
- return;
- }
- InitWithFakeAdapter();
- StartLowEnergyDiscoverySession();
- BluetoothDevice* device = SimulateLowEnergyDevice(3);
- // Create multiple connections and simulate connection complete:
- ASSERT_TRUE(
- ConnectGatt(device,
- /*service_uuid=*/absl::nullopt,
- base::BindLambdaForTesting([this](BluetoothDevice* device) {
- ConnectGatt(device);
- })));
- EXPECT_EQ(2u, gatt_connections_.size());
- // Delete all CreateGattConnection objects, observe disconnection:
- ResetEventCounts();
- gatt_connections_.clear();
- EXPECT_EQ(1, gatt_disconnection_attempts_);
- }
- #if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_MAC)
- #define MAYBE_BluetoothGattConnection_DisconnectInProgress \
- BluetoothGattConnection_DisconnectInProgress
- #else
- #define MAYBE_BluetoothGattConnection_DisconnectInProgress \
- DISABLED_BluetoothGattConnection_DisconnectInProgress
- #endif
- // Starts process of disconnecting and then calls BluetoothGattConnection.
- #if BUILDFLAG(IS_WIN)
- TEST_P(BluetoothTestWinrtOnly, BluetoothGattConnection_DisconnectInProgress) {
- #else
- TEST_F(BluetoothTest, MAYBE_BluetoothGattConnection_DisconnectInProgress) {
- #endif
- if (!PlatformSupportsLowEnergy()) {
- LOG(WARNING) << "Low Energy Bluetooth unavailable, skipping unit test.";
- return;
- }
- InitWithFakeAdapter();
- StartLowEnergyDiscoverySession();
- BluetoothDevice* device = SimulateLowEnergyDevice(3);
- // Create multiple connections and simulate connection complete:
- ASSERT_TRUE(
- ConnectGatt(device,
- /*service_uuid=*/absl::nullopt,
- base::BindLambdaForTesting([this](BluetoothDevice* device) {
- ConnectGatt(device);
- })));
- EXPECT_EQ(2u, gatt_connections_.size());
- // Disconnect all CreateGattConnection objects & create a new connection.
- // But, don't yet simulate the device disconnecting:
- ResetEventCounts();
- for (const auto& connection : gatt_connections_)
- connection->Disconnect();
- EXPECT_EQ(1, gatt_disconnection_attempts_);
- // Create a connection.
- ASSERT_TRUE(ConnectGatt(device));
- EXPECT_EQ(0, gatt_connection_attempts_); // No connection attempt.
- EXPECT_FALSE(gatt_connections_.front()->IsConnected());
- EXPECT_TRUE(gatt_connections_.back()->IsConnected());
- // Actually disconnect:
- SimulateGattDisconnection(device);
- base::RunLoop().RunUntilIdle();
- for (const auto& connection : gatt_connections_)
- EXPECT_FALSE(connection->IsConnected());
- }
- #if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_MAC)
- #define MAYBE_BluetoothGattConnection_SimulateDisconnect \
- BluetoothGattConnection_SimulateDisconnect
- #else
- #define MAYBE_BluetoothGattConnection_SimulateDisconnect \
- DISABLED_BluetoothGattConnection_SimulateDisconnect
- #endif
- // Calls CreateGattConnection but receives notice that the device disconnected
- // before it ever connects.
- #if BUILDFLAG(IS_WIN)
- TEST_P(BluetoothTestWinrtOnly, BluetoothGattConnection_SimulateDisconnect) {
- #else
- TEST_F(BluetoothTest, MAYBE_BluetoothGattConnection_SimulateDisconnect) {
- #endif
- if (!PlatformSupportsLowEnergy()) {
- LOG(WARNING) << "Low Energy Bluetooth unavailable, skipping unit test.";
- return;
- }
- InitWithFakeAdapter();
- StartLowEnergyDiscoverySession();
- BluetoothDevice* device = SimulateLowEnergyDevice(3);
- ResetEventCounts();
- EXPECT_FALSE(
- ConnectGatt(device,
- /*service_uuid=*/absl::nullopt,
- base::BindLambdaForTesting([this](BluetoothDevice* device) {
- SimulateGattDisconnection(device);
- })));
- EXPECT_EQ(BluetoothDevice::ERROR_FAILED, last_connect_error_code_);
- for (const auto& connection : gatt_connections_)
- EXPECT_FALSE(connection->IsConnected());
- }
- #if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_MAC)
- #define MAYBE_BluetoothGattConnection_DisconnectGatt_SimulateConnect \
- BluetoothGattConnection_DisconnectGatt_SimulateConnect
- #else
- #define MAYBE_BluetoothGattConnection_DisconnectGatt_SimulateConnect \
- DISABLED_BluetoothGattConnection_DisconnectGatt_SimulateConnect
- #endif
- // Calls CreateGattConnection & DisconnectGatt, then simulates connection.
- #if BUILDFLAG(IS_WIN)
- TEST_P(BluetoothTestWinrtOnly,
- BluetoothGattConnection_DisconnectGatt_SimulateConnect) {
- #else
- TEST_F(BluetoothTest,
- MAYBE_BluetoothGattConnection_DisconnectGatt_SimulateConnect) {
- #endif
- if (!PlatformSupportsLowEnergy()) {
- LOG(WARNING) << "Low Energy Bluetooth unavailable, skipping unit test.";
- return;
- }
- InitWithFakeAdapter();
- StartLowEnergyDiscoverySession();
- BluetoothDevice* device = SimulateLowEnergyDevice(3);
- ResetEventCounts();
- EXPECT_TRUE(
- ConnectGatt(device,
- /*service_uuid=*/absl::nullopt,
- base::BindLambdaForTesting([this](BluetoothDevice* device) {
- #if !BUILDFLAG(IS_WIN)
- // On Windows there is currently no way to cancel a
- // pending GATT connection from the caller's side.
- device->DisconnectGatt();
- #endif
- SimulateGattConnection(device);
- })));
- #if !BUILDFLAG(IS_WIN)
- EXPECT_EQ(1, gatt_disconnection_attempts_);
- #endif
- EXPECT_EQ(1, gatt_connection_attempts_);
- EXPECT_TRUE(gatt_connections_.back()->IsConnected());
- ResetEventCounts();
- SimulateGattDisconnection(device);
- base::RunLoop().RunUntilIdle();
- }
- #if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_MAC)
- #define MAYBE_BluetoothGattConnection_DisconnectGatt_SimulateDisconnect \
- BluetoothGattConnection_DisconnectGatt_SimulateDisconnect
- #else
- #define MAYBE_BluetoothGattConnection_DisconnectGatt_SimulateDisconnect \
- DISABLED_BluetoothGattConnection_DisconnectGatt_SimulateDisconnect
- #endif
- // Calls CreateGattConnection & DisconnectGatt, then simulates disconnection.
- #if BUILDFLAG(IS_WIN)
- TEST_P(BluetoothTestWinrtOnly,
- BluetoothGattConnection_DisconnectGatt_SimulateDisconnect) {
- #else
- TEST_F(BluetoothTest,
- MAYBE_BluetoothGattConnection_DisconnectGatt_SimulateDisconnect) {
- #endif
- if (!PlatformSupportsLowEnergy()) {
- LOG(WARNING) << "Low Energy Bluetooth unavailable, skipping unit test.";
- return;
- }
- InitWithFakeAdapter();
- StartLowEnergyDiscoverySession();
- BluetoothDevice* device = SimulateLowEnergyDevice(3);
- ResetEventCounts();
- ASSERT_FALSE(
- ConnectGatt(device,
- /*service_uuid=*/absl::nullopt,
- base::BindLambdaForTesting([this](BluetoothDevice* device) {
- device->DisconnectGatt();
- SimulateGattDisconnection(device);
- })));
- EXPECT_EQ(1, gatt_connection_attempts_);
- EXPECT_EQ(
- #if BUILDFLAG(IS_ANDROID)
- // Closing a GATT connection also disconnects on Android.
- // TODO(crbug.com/1045648): this value probably shouldn't be different on
- // Android.
- 2,
- #else
- 1,
- #endif
- gatt_disconnection_attempts_);
- EXPECT_EQ(BluetoothDevice::ERROR_FAILED, last_connect_error_code_);
- for (const auto& connection : gatt_connections_)
- EXPECT_FALSE(connection->IsConnected());
- }
- #if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_MAC)
- #define MAYBE_BluetoothGattConnection_DisconnectGatt_Cleanup \
- BluetoothGattConnection_DisconnectGatt_Cleanup
- #else
- #define MAYBE_BluetoothGattConnection_DisconnectGatt_Cleanup \
- DISABLED_BluetoothGattConnection_DisconnectGatt_Cleanup
- #endif
- // Calls CreateGattConnection & DisconnectGatt, then checks that gatt services
- // have been cleaned up.
- #if BUILDFLAG(IS_WIN)
- TEST_P(BluetoothTestWinrtOnly, BluetoothGattConnection_DisconnectGatt_Cleanup) {
- #else
- TEST_F(BluetoothTest, MAYBE_BluetoothGattConnection_DisconnectGatt_Cleanup) {
- #endif
- if (!PlatformSupportsLowEnergy()) {
- LOG(WARNING) << "Low Energy Bluetooth unavailable, skipping unit test.";
- return;
- }
- InitWithFakeAdapter();
- StartLowEnergyDiscoverySession();
- BluetoothDevice* device = SimulateLowEnergyDevice(3);
- EXPECT_FALSE(device->IsConnected());
- // Connect to the device
- ResetEventCounts();
- TestBluetoothAdapterObserver observer(adapter_);
- ASSERT_TRUE(ConnectGatt(device));
- EXPECT_TRUE(device->IsConnected());
- // Discover services
- SimulateGattServicesDiscovered(
- device,
- std::vector<std::string>({kTestUUIDGenericAccess, kTestUUIDHeartRate}));
- base::RunLoop().RunUntilIdle();
- EXPECT_TRUE(device->IsGattServicesDiscoveryComplete());
- EXPECT_EQ(2u, device->GetGattServices().size());
- EXPECT_EQ(1, observer.gatt_services_discovered_count());
- // Disconnect from the device
- device->DisconnectGatt();
- SimulateGattDisconnection(device);
- base::RunLoop().RunUntilIdle();
- EXPECT_FALSE(device->IsConnected());
- EXPECT_FALSE(device->IsGattServicesDiscoveryComplete());
- EXPECT_EQ(0u, device->GetGattServices().size());
- // Verify that the device can be connected to again
- ASSERT_TRUE(ConnectGatt(device));
- EXPECT_TRUE(device->IsConnected());
- // Verify that service discovery can be done again
- SimulateGattServicesDiscovered(
- device, std::vector<std::string>({kTestUUIDGenericAttribute}));
- base::RunLoop().RunUntilIdle();
- EXPECT_TRUE(device->IsGattServicesDiscoveryComplete());
- EXPECT_EQ(1u, device->GetGattServices().size());
- EXPECT_EQ(2, observer.gatt_services_discovered_count());
- }
- #if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_MAC)
- #define MAYBE_BluetoothGattConnection_ErrorAfterConnection \
- BluetoothGattConnection_ErrorAfterConnection
- #else
- #define MAYBE_BluetoothGattConnection_ErrorAfterConnection \
- DISABLED_BluetoothGattConnection_ErrorAfterConnection
- #endif
- // Calls CreateGattConnection, but simulate errors connecting. Also, verifies
- // multiple errors should only invoke callbacks once.
- #if BUILDFLAG(IS_WIN)
- TEST_P(BluetoothTestWinrtOnly, BluetoothGattConnection_ErrorAfterConnection) {
- #else
- TEST_F(BluetoothTest, MAYBE_BluetoothGattConnection_ErrorAfterConnection) {
- #endif
- if (!PlatformSupportsLowEnergy()) {
- LOG(WARNING) << "Low Energy Bluetooth unavailable, skipping unit test.";
- return;
- }
- InitWithFakeAdapter();
- StartLowEnergyDiscoverySession();
- BluetoothDevice* device = SimulateLowEnergyDevice(3);
- ResetEventCounts();
- EXPECT_FALSE(ConnectGatt(
- device,
- /*service_uuid=*/absl::nullopt,
- base::BindLambdaForTesting([this](BluetoothDevice* device) {
- SimulateGattConnectionError(device, BluetoothDevice::ERROR_AUTH_FAILED);
- SimulateGattConnectionError(device, BluetoothDevice::ERROR_FAILED);
- })));
- EXPECT_EQ(1, gatt_connection_attempts_);
- #if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_WIN)
- // TODO(crbug.com/578191): Change to ERROR_AUTH_FAILED. We should be getting a
- // callback only with the first error, but our android framework doesn't yet
- // support sending different errors.
- // On Windows, any GattConnectionError will result in ERROR_FAILED.
- EXPECT_EQ(BluetoothDevice::ERROR_FAILED, last_connect_error_code_);
- #else
- EXPECT_EQ(BluetoothDevice::ERROR_AUTH_FAILED, last_connect_error_code_);
- #endif
- for (const auto& connection : gatt_connections_)
- EXPECT_FALSE(connection->IsConnected());
- }
- #if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC)
- #define MAYBE_GattServices_ObserversCalls GattServices_ObserversCalls
- #else
- #define MAYBE_GattServices_ObserversCalls DISABLED_GattServices_ObserversCalls
- #endif
- #if BUILDFLAG(IS_WIN)
- TEST_P(BluetoothTestWinrtOnly, GattServices_ObserversCalls) {
- #else
- TEST_F(BluetoothTest, MAYBE_GattServices_ObserversCalls) {
- #endif
- if (!PlatformSupportsLowEnergy()) {
- LOG(WARNING) << "Low Energy Bluetooth unavailable, skipping unit test.";
- return;
- }
- InitWithFakeAdapter();
- StartLowEnergyDiscoverySession();
- BluetoothDevice* device = SimulateLowEnergyDevice(3);
- TestBluetoothAdapterObserver observer(adapter_);
- ResetEventCounts();
- ASSERT_TRUE(ConnectGatt(device));
- EXPECT_EQ(1, gatt_discovery_attempts_);
- SimulateGattServicesDiscovered(
- device,
- std::vector<std::string>({kTestUUIDGenericAccess, kTestUUIDHeartRate}));
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(1, observer.gatt_services_discovered_count());
- }
- #if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC)
- #define MAYBE_GattServicesDiscovered_Success GattServicesDiscovered_Success
- #else
- #define MAYBE_GattServicesDiscovered_Success \
- DISABLED_GattServicesDiscovered_Success
- #endif
- #if BUILDFLAG(IS_WIN)
- TEST_P(BluetoothTestWinrtOnly, GattServicesDiscovered_Success) {
- #else
- TEST_F(BluetoothTest, MAYBE_GattServicesDiscovered_Success) {
- #endif
- if (!PlatformSupportsLowEnergy()) {
- LOG(WARNING) << "Low Energy Bluetooth unavailable, skipping unit test.";
- return;
- }
- InitWithFakeAdapter();
- StartLowEnergyDiscoverySession();
- TestBluetoothAdapterObserver observer(adapter_);
- BluetoothDevice* device = SimulateLowEnergyDevice(3);
- ResetEventCounts();
- ASSERT_TRUE(ConnectGatt(device));
- EXPECT_EQ(1, gatt_discovery_attempts_);
- EXPECT_EQ(0, observer.gatt_services_discovered_count());
- SimulateGattServicesDiscovered(
- device,
- std::vector<std::string>({kTestUUIDGenericAccess, kTestUUIDHeartRate}));
- base::RunLoop().RunUntilIdle();
- EXPECT_TRUE(device->IsGattServicesDiscoveryComplete());
- EXPECT_EQ(1, observer.gatt_services_discovered_count());
- EXPECT_EQ(2u, device->GetGattServices().size());
- }
- #if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_WIN)
- #define MAYBE_GattServicesDiscovered_AfterDeleted \
- GattServicesDiscovered_AfterDeleted
- #else
- #define MAYBE_GattServicesDiscovered_AfterDeleted \
- DISABLED_GattServicesDiscovered_AfterDeleted
- #endif
- // macOS: Not applicable: This can never happen because when
- // the device gets destroyed the CBPeripheralDelegate is also destroyed
- // and no more events are dispatched.
- TEST_F(BluetoothTest, MAYBE_GattServicesDiscovered_AfterDeleted) {
- // Tests that we don't crash if services are discovered after
- // the device object is deleted.
- if (!PlatformSupportsLowEnergy()) {
- LOG(WARNING) << "Low Energy Bluetooth unavailable, skipping unit test.";
- return;
- }
- InitWithFakeAdapter();
- StartLowEnergyDiscoverySession();
- BluetoothDevice* device = SimulateLowEnergyDevice(3);
- ResetEventCounts();
- ASSERT_TRUE(ConnectGatt(device));
- EXPECT_EQ(1, gatt_discovery_attempts_);
- RememberDeviceForSubsequentAction(device);
- DeleteDevice(device);
- SimulateGattServicesDiscovered(
- nullptr /* use remembered device */,
- std::vector<std::string>({kTestUUIDGenericAccess, kTestUUIDHeartRate}));
- }
- #if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_WIN)
- #define MAYBE_GattServicesDiscoveredError_AfterDeleted \
- GattServicesDiscoveredError_AfterDeleted
- #else
- #define MAYBE_GattServicesDiscoveredError_AfterDeleted \
- DISABLED_GattServicesDiscoveredError_AfterDeleted
- #endif
- // macOS: Not applicable: This can never happen because when
- // the device gets destroyed the CBPeripheralDelegate is also destroyed
- // and no more events are dispatched.
- TEST_F(BluetoothTest, MAYBE_GattServicesDiscoveredError_AfterDeleted) {
- // Tests that we don't crash if there was an error discoverying services
- // after the device object is deleted.
- if (!PlatformSupportsLowEnergy()) {
- LOG(WARNING) << "Low Energy Bluetooth unavailable, skipping unit test.";
- return;
- }
- InitWithFakeAdapter();
- StartLowEnergyDiscoverySession();
- BluetoothDevice* device = SimulateLowEnergyDevice(3);
- ResetEventCounts();
- ASSERT_TRUE(ConnectGatt(device));
- EXPECT_EQ(1, gatt_discovery_attempts_);
- RememberDeviceForSubsequentAction(device);
- DeleteDevice(device);
- SimulateGattServicesDiscoveryError(nullptr /* use remembered device */);
- base::RunLoop().RunUntilIdle();
- }
- #if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_MAC)
- #define MAYBE_GattServicesDiscovered_AfterDisconnection \
- GattServicesDiscovered_AfterDisconnection
- #else
- #define MAYBE_GattServicesDiscovered_AfterDisconnection \
- DISABLED_GattServicesDiscovered_AfterDisconnection
- #endif
- // Classic Windows does not support disconnection.
- #if BUILDFLAG(IS_WIN)
- TEST_P(BluetoothTestWinrtOnly, GattServicesDiscovered_AfterDisconnection) {
- #else
- TEST_F(BluetoothTest, MAYBE_GattServicesDiscovered_AfterDisconnection) {
- #endif
- // Tests that we don't crash if there was an error discovering services after
- // the device disconnects.
- if (!PlatformSupportsLowEnergy()) {
- LOG(WARNING) << "Low Energy Bluetooth unavailable, skipping unit test.";
- return;
- }
- InitWithFakeAdapter();
- StartLowEnergyDiscoverySession();
- BluetoothDevice* device = SimulateLowEnergyDevice(3);
- ResetEventCounts();
- ASSERT_TRUE(ConnectGatt(device));
- EXPECT_EQ(1, gatt_discovery_attempts_);
- SimulateDeviceBreaksConnection(device);
- base::RunLoop().RunUntilIdle();
- SimulateGattServicesDiscovered(
- device,
- std::vector<std::string>({kTestUUIDGenericAccess, kTestUUIDHeartRate}));
- base::RunLoop().RunUntilIdle();
- EXPECT_FALSE(device->IsGattServicesDiscoveryComplete());
- EXPECT_EQ(0u, device->GetGattServices().size());
- }
- #if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_MAC)
- #define MAYBE_GattServicesDiscoveredError_AfterDisconnection \
- GattServicesDiscoveredError_AfterDisconnection
- #else
- #define MAYBE_GattServicesDiscoveredError_AfterDisconnection \
- DISABLED_GattServicesDiscoveredError_AfterDisconnection
- #endif
- // Windows does not support disconnecting.
- #if BUILDFLAG(IS_WIN)
- TEST_P(BluetoothTestWinrtOnly, GattServicesDiscoveredError_AfterDisconnection) {
- #else
- TEST_F(BluetoothTest, MAYBE_GattServicesDiscoveredError_AfterDisconnection) {
- #endif
- // Tests that we don't crash if services are discovered after
- // the device disconnects.
- if (!PlatformSupportsLowEnergy()) {
- LOG(WARNING) << "Low Energy Bluetooth unavailable, skipping unit test.";
- return;
- }
- InitWithFakeAdapter();
- StartLowEnergyDiscoverySession();
- BluetoothDevice* device = SimulateLowEnergyDevice(3);
- ResetEventCounts();
- ASSERT_TRUE(ConnectGatt(device));
- EXPECT_EQ(1, gatt_discovery_attempts_);
- SimulateGattDisconnection(device);
- base::RunLoop().RunUntilIdle();
- SimulateGattServicesDiscoveryError(device);
- base::RunLoop().RunUntilIdle();
- EXPECT_FALSE(device->IsGattServicesDiscoveryComplete());
- EXPECT_EQ(0u, device->GetGattServices().size());
- }
- #if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_MAC)
- #define MAYBE_GetGattServices_and_GetGattService \
- GetGattServices_and_GetGattService
- #else
- #define MAYBE_GetGattServices_and_GetGattService \
- DISABLED_GetGattServices_and_GetGattService
- #endif
- #if BUILDFLAG(IS_WIN)
- TEST_P(BluetoothTestWinrt, GetGattServices_and_GetGattService) {
- #else
- TEST_F(BluetoothTest, MAYBE_GetGattServices_and_GetGattService) {
- #endif
- if (!PlatformSupportsLowEnergy()) {
- LOG(WARNING) << "Low Energy Bluetooth unavailable, skipping unit test.";
- return;
- }
- InitWithFakeAdapter();
- StartLowEnergyDiscoverySession();
- BluetoothDevice* device = SimulateLowEnergyDevice(3);
- ResetEventCounts();
- ASSERT_TRUE(ConnectGatt(device));
- EXPECT_EQ(1, gatt_discovery_attempts_);
- // 2 duplicate UUIDs creating 2 instances.
- SimulateGattServicesDiscovered(
- device,
- std::vector<std::string>(
- {kTestUUIDGenericAccess, kTestUUIDHeartRate, kTestUUIDHeartRate}));
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(3u, device->GetGattServices().size());
- // Test GetGattService:
- std::string service_id1 = device->GetGattServices()[0]->GetIdentifier();
- std::string service_id2 = device->GetGattServices()[1]->GetIdentifier();
- std::string service_id3 = device->GetGattServices()[2]->GetIdentifier();
- EXPECT_TRUE(device->GetGattService(service_id1));
- EXPECT_TRUE(device->GetGattService(service_id2));
- EXPECT_TRUE(device->GetGattService(service_id3));
- }
- #if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_MAC)
- #define MAYBE_GetGattServices_FindNone GetGattServices_FindNone
- #else
- #define MAYBE_GetGattServices_FindNone DISABLED_GetGattServices_FindNone
- #endif
- #if BUILDFLAG(IS_WIN)
- TEST_P(BluetoothTestWinrtOnly, GetGattServices_FindNone) {
- #else
- TEST_F(BluetoothTest, MAYBE_GetGattServices_FindNone) {
- #endif
- if (!PlatformSupportsLowEnergy()) {
- LOG(WARNING) << "Low Energy Bluetooth unavailable, skipping unit test.";
- return;
- }
- InitWithFakeAdapter();
- StartLowEnergyDiscoverySession();
- BluetoothDevice* device = SimulateLowEnergyDevice(3);
- ResetEventCounts();
- ASSERT_TRUE(ConnectGatt(device));
- EXPECT_EQ(1, gatt_discovery_attempts_);
- // Simulate an empty set of discovered services.
- SimulateGattServicesDiscovered(device, {} /* uuids */);
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(0u, device->GetGattServices().size());
- }
- #if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_MAC)
- #define MAYBE_GetGattServices_DiscoveryError GetGattServices_DiscoveryError
- #else
- #define MAYBE_GetGattServices_DiscoveryError \
- DISABLED_GetGattServices_DiscoveryError
- #endif
- #if BUILDFLAG(IS_WIN)
- TEST_P(BluetoothTestWinrtOnly, GetGattServices_DiscoveryError) {
- #else
- TEST_F(BluetoothTest, MAYBE_GetGattServices_DiscoveryError) {
- #endif
- if (!PlatformSupportsLowEnergy()) {
- LOG(WARNING) << "Low Energy Bluetooth unavailable, skipping unit test.";
- return;
- }
- InitWithFakeAdapter();
- StartLowEnergyDiscoverySession();
- BluetoothDevice* device = SimulateLowEnergyDevice(3);
- ResetEventCounts();
- ASSERT_TRUE(ConnectGatt(device));
- EXPECT_EQ(1, gatt_discovery_attempts_);
- SimulateGattServicesDiscoveryError(device);
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(0u, device->GetGattServices().size());
- }
- #if BUILDFLAG(IS_WIN)
- TEST_P(BluetoothTestWinrtOnly, GattServicesDiscovered_SomeServicesBlocked) {
- #else
- TEST_F(BluetoothTest, DISABLED_GattServicesDiscovered_SomeServicesBlocked) {
- #endif
- if (!PlatformSupportsLowEnergy()) {
- LOG(WARNING) << "Low Energy Bluetooth unavailable, skipping unit test.";
- return;
- }
- InitWithFakeAdapter();
- StartLowEnergyDiscoverySession();
- TestBluetoothAdapterObserver observer(adapter_);
- BluetoothDevice* device = SimulateLowEnergyDevice(3);
- ResetEventCounts();
- ASSERT_TRUE(ConnectGatt(device));
- EXPECT_EQ(1, gatt_discovery_attempts_);
- EXPECT_EQ(0, observer.gatt_services_discovered_count());
- SimulateGattServicesDiscovered(
- device,
- /*uuids=*/{kTestUUIDGenericAccess, kTestUUIDHeartRate},
- /*blocked_uuids=*/{kTestUUIDU2f});
- base::RunLoop().RunUntilIdle();
- EXPECT_TRUE(device->IsGattServicesDiscoveryComplete());
- EXPECT_EQ(1, observer.gatt_services_discovered_count());
- // Even though some services are blocked they should still appear in the list.
- EXPECT_EQ(3u, device->GetGattServices().size());
- }
- #if BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_LINUX)
- TEST_F(BluetoothTest, GetDeviceTransportType) {
- if (!PlatformSupportsLowEnergy()) {
- LOG(WARNING) << "Low Energy Bluetooth unavailable, skipping unit test.";
- return;
- }
- InitWithFakeAdapter();
- BluetoothDevice* device = SimulateLowEnergyDevice(1);
- EXPECT_EQ(BLUETOOTH_TRANSPORT_LE, device->GetType());
- #if !defined(USE_CAST_BLUETOOTH_ADAPTER)
- BluetoothDevice* device2 = SimulateLowEnergyDevice(6);
- EXPECT_EQ(BLUETOOTH_TRANSPORT_DUAL, device2->GetType());
- BluetoothDevice* device3 = SimulateClassicDevice();
- EXPECT_EQ(BLUETOOTH_TRANSPORT_CLASSIC, device3->GetType());
- #endif // !defined(USE_CAST_BLUETOOTH_ADAPTER)
- }
- #endif // BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_LINUX)
- #if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_MAC)
- #define MAYBE_GetPrimaryServices GetPrimaryServices
- #else
- #define MAYBE_GetPrimaryServices DISABLED_GetPrimaryServices
- #endif
- #if BUILDFLAG(IS_WIN)
- TEST_P(BluetoothTestWinrt, GetPrimaryServices) {
- #else
- TEST_F(BluetoothTest, MAYBE_GetPrimaryServices) {
- #endif
- if (!PlatformSupportsLowEnergy()) {
- LOG(WARNING) << "Low Energy Bluetooth unavailable, skipping unit test.";
- return;
- }
- InitWithFakeAdapter();
- StartLowEnergyDiscoverySession();
- BluetoothDevice* device = SimulateLowEnergyDevice(3);
- EXPECT_FALSE(device->IsConnected());
- // Connect to the device.
- ResetEventCounts();
- ASSERT_TRUE(ConnectGatt(device));
- EXPECT_TRUE(device->IsGattConnected());
- // Discover services: Two unique UUIDs, of which the second is duplicated.
- SimulateGattServicesDiscovered(
- device, {kTestUUIDGenericAccess, kTestUUIDHeartRate, kTestUUIDHeartRate});
- base::RunLoop().RunUntilIdle();
- EXPECT_TRUE(device->IsGattServicesDiscoveryComplete());
- EXPECT_EQ(3u, device->GetPrimaryServices().size());
- }
- #if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_MAC)
- #define MAYBE_GetPrimaryServicesByUUID GetPrimaryServicesByUUID
- #else
- #define MAYBE_GetPrimaryServicesByUUID DISABLED_GetPrimaryServicesByUUID
- #endif
- #if BUILDFLAG(IS_WIN)
- TEST_P(BluetoothTestWinrt, GetPrimaryServicesByUUID) {
- #else
- TEST_F(BluetoothTest, MAYBE_GetPrimaryServicesByUUID) {
- #endif
- if (!PlatformSupportsLowEnergy()) {
- LOG(WARNING) << "Low Energy Bluetooth unavailable, skipping unit test.";
- return;
- }
- InitWithFakeAdapter();
- StartLowEnergyDiscoverySession();
- BluetoothDevice* device = SimulateLowEnergyDevice(3);
- EXPECT_FALSE(device->IsConnected());
- // Connect to the device.
- ResetEventCounts();
- ASSERT_TRUE(ConnectGatt(device));
- EXPECT_TRUE(device->IsGattConnected());
- // Discover services: Two unique UUIDs, of which the second is duplicated.
- SimulateGattServicesDiscovered(
- device, {kTestUUIDGenericAccess, kTestUUIDHeartRate, kTestUUIDHeartRate});
- base::RunLoop().RunUntilIdle();
- EXPECT_TRUE(device->IsGattServicesDiscoveryComplete());
- {
- const BluetoothUUID unique_service_uuid(kTestUUIDGenericAccess);
- std::vector<BluetoothRemoteGattService*> services =
- device->GetPrimaryServicesByUUID(unique_service_uuid);
- EXPECT_EQ(1u, services.size());
- EXPECT_EQ(unique_service_uuid, services[0]->GetUUID());
- }
- {
- const BluetoothUUID duplicate_service_uuid(kTestUUIDHeartRate);
- std::vector<BluetoothRemoteGattService*> services =
- device->GetPrimaryServicesByUUID(duplicate_service_uuid);
- EXPECT_EQ(2u, services.size());
- EXPECT_EQ(duplicate_service_uuid, services[0]->GetUUID());
- EXPECT_EQ(duplicate_service_uuid, services[1]->GetUUID());
- EXPECT_TRUE(
- device
- ->GetPrimaryServicesByUUID(BluetoothUUID(kTestUUIDGenericAttribute))
- .empty());
- EXPECT_NE(services[0]->GetIdentifier(), services[1]->GetIdentifier());
- }
- }
- #if BUILDFLAG(IS_WIN)
- TEST_P(BluetoothTestWinrtOnly, GattConnectedNameChange) {
- #else
- // The SimulateGattNameChange() function is not yet available on other
- // platforms.
- TEST_F(BluetoothTest, DISABLED_GattConnectedNameChange) {
- #endif
- if (!PlatformSupportsLowEnergy()) {
- LOG(WARNING) << "Low Energy Bluetooth unavailable, skipping unit test.";
- return;
- }
- InitWithFakeAdapter();
- StartLowEnergyDiscoverySession();
- BluetoothDevice* device = SimulateLowEnergyDevice(3);
- ASSERT_TRUE(ConnectGatt(device));
- // GetName() returns a absl::optional<std:string> however some backends still
- // return an empty string rather than nullopt when no name is available.
- EXPECT_TRUE(!device->GetName() || device->GetName()->empty());
- TestBluetoothAdapterObserver observer(adapter_);
- SimulateGattNameChange(device, kTestDeviceName);
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(1, observer.device_changed_count());
- EXPECT_EQ(base::UTF8ToUTF16(kTestDeviceName), device->GetNameForDisplay());
- }
- #if BUILDFLAG(IS_WIN)
- // WinRT sometimes calls OnConnectionStatusChanged when the status is
- // initialized and not when changed.
- TEST_P(BluetoothTestWinrtOnly, FalseStatusChangedTest) {
- if (!PlatformSupportsLowEnergy()) {
- LOG(WARNING) << "Low Energy Bluetooth unavailable, skipping unit test.";
- return;
- }
- InitWithFakeAdapter();
- StartLowEnergyDiscoverySession();
- BluetoothDevice* device = SimulateLowEnergyDevice(3);
- EXPECT_FALSE(device->IsConnected());
- device->CreateGattConnection(
- GetGattConnectionCallback(Call::NOT_EXPECTED, Result::FAILURE));
- SimulateStatusChangeToDisconnect(device);
- base::RunLoop().RunUntilIdle();
- }
- #endif
- #if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_MAC)
- #define MAYBE_ServiceSpecificDiscovery ServiceSpecificDiscovery
- #else
- #define MAYBE_ServiceSpecificDiscovery DISABLED_ServiceSpecificDiscovery
- #endif
- #if !BUILDFLAG(IS_WIN)
- TEST_F(BluetoothTest, MAYBE_ServiceSpecificDiscovery) {
- #else
- TEST_P(BluetoothTestWinrtOnly, ServiceSpecificDiscovery) {
- #endif
- if (!PlatformSupportsLowEnergy()) {
- LOG(WARNING) << "Low Energy Bluetooth unavailable, skipping unit test.";
- return;
- }
- InitWithFakeAdapter();
- StartLowEnergyDiscoverySession();
- BluetoothDevice* device = SimulateLowEnergyDevice(1);
- // Create a GATT connection and specify a specific UUID for discovery.
- ASSERT_TRUE(ConnectGatt(device, BluetoothUUID(kTestUUIDGenericAccess)));
- EXPECT_TRUE(device->IsGattConnected());
- SimulateGattServicesDiscovered(device, {kTestUUIDGenericAccess});
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(1, gatt_connection_attempts_);
- EXPECT_EQ(1, gatt_discovery_attempts_);
- #if !BUILDFLAG(IS_WIN)
- // Outside of WinRT, service-specific discovery should be ignored.
- ASSERT_FALSE(device->supports_service_specific_discovery());
- EXPECT_FALSE(GetTargetGattService(device).has_value());
- EXPECT_TRUE(device->IsGattServicesDiscoveryComplete());
- #else
- ASSERT_TRUE(device->supports_service_specific_discovery());
- absl::optional<BluetoothUUID> service_uuid = GetTargetGattService(device);
- ASSERT_TRUE(service_uuid.has_value());
- EXPECT_EQ(*service_uuid, BluetoothUUID(kTestUUIDGenericAccess));
- EXPECT_FALSE(device->IsGattServicesDiscoveryComplete());
- // Next, simulate a second GATT request that requests the same service.
- // The connection request should be ignored because of the existing,
- // compatible connection.
- ASSERT_TRUE(ConnectGatt(device, BluetoothUUID(kTestUUIDGenericAccess)));
- EXPECT_EQ(1, gatt_connection_attempts_);
- EXPECT_EQ(1, gatt_discovery_attempts_);
- // A third GATT request is same without any UUID.
- ASSERT_TRUE(ConnectGatt(device));
- // This should restart discovery.
- EXPECT_EQ(2, gatt_discovery_attempts_);
- SimulateGattServicesDiscovered(device, {kTestUUIDGenericAccess});
- base::RunLoop().RunUntilIdle();
- EXPECT_TRUE(device->IsGattServicesDiscoveryComplete());
- // Another GATT request with a specific UUID should be ignored because any
- // specific service is a subset of a complete discovery.
- ASSERT_TRUE(ConnectGatt(device, BluetoothUUID(kTestUUIDGenericAccess)));
- EXPECT_EQ(2, gatt_discovery_attempts_);
- #endif
- }
- } // namespace device
|