xref: /aosp_15_r20/external/pigweed/pw_bluetooth_sapphire/peripheral_test.cc (revision 61c4878ac05f98d0ceed94b57d316916de578985)
1*61c4878aSAndroid Build Coastguard Worker // Copyright 2024 The Pigweed Authors
2*61c4878aSAndroid Build Coastguard Worker //
3*61c4878aSAndroid Build Coastguard Worker // Licensed under the Apache License, Version 2.0 (the "License"); you may not
4*61c4878aSAndroid Build Coastguard Worker // use this file except in compliance with the License. You may obtain a copy of
5*61c4878aSAndroid Build Coastguard Worker // the License at
6*61c4878aSAndroid Build Coastguard Worker //
7*61c4878aSAndroid Build Coastguard Worker //     https://www.apache.org/licenses/LICENSE-2.0
8*61c4878aSAndroid Build Coastguard Worker //
9*61c4878aSAndroid Build Coastguard Worker // Unless required by applicable law or agreed to in writing, software
10*61c4878aSAndroid Build Coastguard Worker // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11*61c4878aSAndroid Build Coastguard Worker // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12*61c4878aSAndroid Build Coastguard Worker // License for the specific language governing permissions and limitations under
13*61c4878aSAndroid Build Coastguard Worker // the License.
14*61c4878aSAndroid Build Coastguard Worker 
15*61c4878aSAndroid Build Coastguard Worker #include "pw_bluetooth_sapphire/peripheral.h"
16*61c4878aSAndroid Build Coastguard Worker 
17*61c4878aSAndroid Build Coastguard Worker #include "pw_async/fake_dispatcher.h"
18*61c4878aSAndroid Build Coastguard Worker #include "pw_async2/pend_func_task.h"
19*61c4878aSAndroid Build Coastguard Worker #include "pw_bluetooth_sapphire/internal/host/gap/fake_adapter.h"
20*61c4878aSAndroid Build Coastguard Worker #include "pw_unit_test/framework.h"
21*61c4878aSAndroid Build Coastguard Worker 
22*61c4878aSAndroid Build Coastguard Worker using Peripheral2 = pw::bluetooth::low_energy::Peripheral2;
23*61c4878aSAndroid Build Coastguard Worker using AdvertisedPeripheral2 = pw::bluetooth::low_energy::AdvertisedPeripheral2;
24*61c4878aSAndroid Build Coastguard Worker using ManufacturerData = pw::bluetooth::low_energy::ManufacturerData;
25*61c4878aSAndroid Build Coastguard Worker using AdvertiseError = pw::bluetooth::low_energy::Peripheral2::AdvertiseError;
26*61c4878aSAndroid Build Coastguard Worker 
27*61c4878aSAndroid Build Coastguard Worker template <typename T>
28*61c4878aSAndroid Build Coastguard Worker class ReceiverTask final : public pw::async2::Task {
29*61c4878aSAndroid Build Coastguard Worker  public:
ReceiverTask(pw::async2::OnceReceiver<T> receiver)30*61c4878aSAndroid Build Coastguard Worker   ReceiverTask(pw::async2::OnceReceiver<T> receiver)
31*61c4878aSAndroid Build Coastguard Worker       : receiver_(std::move(receiver)) {}
32*61c4878aSAndroid Build Coastguard Worker 
DoPend(pw::async2::Context & cx)33*61c4878aSAndroid Build Coastguard Worker   pw::async2::Poll<> DoPend(pw::async2::Context& cx) override {
34*61c4878aSAndroid Build Coastguard Worker     pw::async2::Poll<pw::Result<T>> pend = receiver_.Pend(cx);
35*61c4878aSAndroid Build Coastguard Worker     if (pend.IsPending()) {
36*61c4878aSAndroid Build Coastguard Worker       return pw::async2::Pending();
37*61c4878aSAndroid Build Coastguard Worker     }
38*61c4878aSAndroid Build Coastguard Worker     result_ = std::move(pend.value());
39*61c4878aSAndroid Build Coastguard Worker     return pw::async2::Ready();
40*61c4878aSAndroid Build Coastguard Worker   }
41*61c4878aSAndroid Build Coastguard Worker 
result()42*61c4878aSAndroid Build Coastguard Worker   pw::Result<T>& result() { return result_; }
43*61c4878aSAndroid Build Coastguard Worker 
44*61c4878aSAndroid Build Coastguard Worker  private:
45*61c4878aSAndroid Build Coastguard Worker   pw::async2::OnceReceiver<T> receiver_;
46*61c4878aSAndroid Build Coastguard Worker   pw::Result<T> result_;
47*61c4878aSAndroid Build Coastguard Worker };
48*61c4878aSAndroid Build Coastguard Worker 
49*61c4878aSAndroid Build Coastguard Worker class PeripheralTest : public ::testing::Test {
50*61c4878aSAndroid Build Coastguard Worker  public:
SetUp()51*61c4878aSAndroid Build Coastguard Worker   void SetUp() override {}
52*61c4878aSAndroid Build Coastguard Worker 
TearDown()53*61c4878aSAndroid Build Coastguard Worker   void TearDown() override {}
54*61c4878aSAndroid Build Coastguard Worker 
55*61c4878aSAndroid Build Coastguard Worker   // Returns nullopt if OnceReceiver received no result or a OnceReceiver error.
Advertise(Peripheral2::AdvertisingParameters & parameters)56*61c4878aSAndroid Build Coastguard Worker   std::optional<Peripheral2::AdvertiseResult> Advertise(
57*61c4878aSAndroid Build Coastguard Worker       Peripheral2::AdvertisingParameters& parameters) {
58*61c4878aSAndroid Build Coastguard Worker     pw::async2::OnceReceiver<Peripheral2::AdvertiseResult> receiver =
59*61c4878aSAndroid Build Coastguard Worker         peripheral().Advertise(parameters);
60*61c4878aSAndroid Build Coastguard Worker 
61*61c4878aSAndroid Build Coastguard Worker     ReceiverTask<Peripheral2::AdvertiseResult> task(std::move(receiver));
62*61c4878aSAndroid Build Coastguard Worker     dispatcher2().Post(task);
63*61c4878aSAndroid Build Coastguard Worker     EXPECT_TRUE(task.result().status().IsUnknown());
64*61c4878aSAndroid Build Coastguard Worker 
65*61c4878aSAndroid Build Coastguard Worker     dispatcher().RunUntilIdle();
66*61c4878aSAndroid Build Coastguard Worker     EXPECT_TRUE(dispatcher2().RunUntilStalled().IsReady());
67*61c4878aSAndroid Build Coastguard Worker     if (!task.result().status().ok()) {
68*61c4878aSAndroid Build Coastguard Worker       return std::nullopt;
69*61c4878aSAndroid Build Coastguard Worker     }
70*61c4878aSAndroid Build Coastguard Worker     return std::move(task.result().value());
71*61c4878aSAndroid Build Coastguard Worker   }
72*61c4878aSAndroid Build Coastguard Worker 
AdvertiseExpectSuccess(Peripheral2::AdvertisingParameters & parameters)73*61c4878aSAndroid Build Coastguard Worker   AdvertisedPeripheral2::Ptr AdvertiseExpectSuccess(
74*61c4878aSAndroid Build Coastguard Worker       Peripheral2::AdvertisingParameters& parameters) {
75*61c4878aSAndroid Build Coastguard Worker     std::optional<Peripheral2::AdvertiseResult> result = Advertise(parameters);
76*61c4878aSAndroid Build Coastguard Worker     if (!result.has_value()) {
77*61c4878aSAndroid Build Coastguard Worker       ADD_FAILURE();
78*61c4878aSAndroid Build Coastguard Worker       return nullptr;
79*61c4878aSAndroid Build Coastguard Worker     }
80*61c4878aSAndroid Build Coastguard Worker     if (!result.value().has_value()) {
81*61c4878aSAndroid Build Coastguard Worker       ADD_FAILURE();
82*61c4878aSAndroid Build Coastguard Worker       return nullptr;
83*61c4878aSAndroid Build Coastguard Worker     }
84*61c4878aSAndroid Build Coastguard Worker     return std::move(result.value().value());
85*61c4878aSAndroid Build Coastguard Worker   }
86*61c4878aSAndroid Build Coastguard Worker 
peripheral()87*61c4878aSAndroid Build Coastguard Worker   pw::bluetooth_sapphire::Peripheral& peripheral() { return peripheral_; }
88*61c4878aSAndroid Build Coastguard Worker 
adapter()89*61c4878aSAndroid Build Coastguard Worker   bt::gap::testing::FakeAdapter& adapter() { return adapter_; }
90*61c4878aSAndroid Build Coastguard Worker 
dispatcher()91*61c4878aSAndroid Build Coastguard Worker   pw::async::test::FakeDispatcher& dispatcher() { return async_dispatcher_; }
dispatcher2()92*61c4878aSAndroid Build Coastguard Worker   pw::async2::Dispatcher& dispatcher2() { return async2_dispatcher_; }
93*61c4878aSAndroid Build Coastguard Worker 
94*61c4878aSAndroid Build Coastguard Worker  private:
95*61c4878aSAndroid Build Coastguard Worker   pw::async::test::FakeDispatcher async_dispatcher_;
96*61c4878aSAndroid Build Coastguard Worker   pw::async2::Dispatcher async2_dispatcher_;
97*61c4878aSAndroid Build Coastguard Worker   bt::gap::testing::FakeAdapter adapter_{async_dispatcher_};
98*61c4878aSAndroid Build Coastguard Worker   pw::bluetooth_sapphire::Peripheral peripheral_{adapter_.AsWeakPtr(),
99*61c4878aSAndroid Build Coastguard Worker                                                  async_dispatcher_};
100*61c4878aSAndroid Build Coastguard Worker };
101*61c4878aSAndroid Build Coastguard Worker 
TEST_F(PeripheralTest,StartAdvertisingWithNameAndDestroyAdvertisedPeripheralStopsAdvertising)102*61c4878aSAndroid Build Coastguard Worker TEST_F(PeripheralTest,
103*61c4878aSAndroid Build Coastguard Worker        StartAdvertisingWithNameAndDestroyAdvertisedPeripheralStopsAdvertising) {
104*61c4878aSAndroid Build Coastguard Worker   Peripheral2::AdvertisingParameters parameters;
105*61c4878aSAndroid Build Coastguard Worker   parameters.data.name = "pigweed";
106*61c4878aSAndroid Build Coastguard Worker 
107*61c4878aSAndroid Build Coastguard Worker   AdvertisedPeripheral2::Ptr advertised_peripheral =
108*61c4878aSAndroid Build Coastguard Worker       AdvertiseExpectSuccess(parameters);
109*61c4878aSAndroid Build Coastguard Worker 
110*61c4878aSAndroid Build Coastguard Worker   ASSERT_EQ(adapter().fake_le()->registered_advertisements().size(), 1u);
111*61c4878aSAndroid Build Coastguard Worker   auto& advertisement =
112*61c4878aSAndroid Build Coastguard Worker       adapter().fake_le()->registered_advertisements().begin()->second;
113*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(advertisement.data.local_name()->name, parameters.data.name);
114*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(advertisement.data.appearance(),
115*61c4878aSAndroid Build Coastguard Worker             static_cast<uint16_t>(pw::bluetooth::Appearance::kUnknown));
116*61c4878aSAndroid Build Coastguard Worker   EXPECT_FALSE(advertisement.extended_pdu);
117*61c4878aSAndroid Build Coastguard Worker   EXPECT_FALSE(advertisement.include_tx_power_level);
118*61c4878aSAndroid Build Coastguard Worker   EXPECT_FALSE(advertisement.connectable);
119*61c4878aSAndroid Build Coastguard Worker   EXPECT_FALSE(advertisement.anonymous);
120*61c4878aSAndroid Build Coastguard Worker 
121*61c4878aSAndroid Build Coastguard Worker   advertised_peripheral.reset();
122*61c4878aSAndroid Build Coastguard Worker   dispatcher().RunUntilIdle();
123*61c4878aSAndroid Build Coastguard Worker   ASSERT_EQ(adapter().fake_le()->registered_advertisements().size(), 0u);
124*61c4878aSAndroid Build Coastguard Worker }
125*61c4878aSAndroid Build Coastguard Worker 
TEST_F(PeripheralTest,StartAdvertisingWithTooLongName)126*61c4878aSAndroid Build Coastguard Worker TEST_F(PeripheralTest, StartAdvertisingWithTooLongName) {
127*61c4878aSAndroid Build Coastguard Worker   std::string name(300, 'A');
128*61c4878aSAndroid Build Coastguard Worker   Peripheral2::AdvertisingParameters parameters;
129*61c4878aSAndroid Build Coastguard Worker   parameters.data.name = name;
130*61c4878aSAndroid Build Coastguard Worker   std::optional<Peripheral2::AdvertiseResult> result = Advertise(parameters);
131*61c4878aSAndroid Build Coastguard Worker   ASSERT_TRUE(result.has_value());
132*61c4878aSAndroid Build Coastguard Worker   ASSERT_FALSE(result.value().has_value());
133*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(result.value().error(),
134*61c4878aSAndroid Build Coastguard Worker             pw::bluetooth_sapphire::Peripheral::AdvertiseError::
135*61c4878aSAndroid Build Coastguard Worker                 kAdvertisingDataTooLong);
136*61c4878aSAndroid Build Coastguard Worker }
137*61c4878aSAndroid Build Coastguard Worker 
TEST_F(PeripheralTest,StartAdvertisingWithServiceData)138*61c4878aSAndroid Build Coastguard Worker TEST_F(PeripheralTest, StartAdvertisingWithServiceData) {
139*61c4878aSAndroid Build Coastguard Worker   const uint16_t uuid_0 = 42, uuid_1 = 43;
140*61c4878aSAndroid Build Coastguard Worker   pw::bluetooth::low_energy::ServiceData service_data_0;
141*61c4878aSAndroid Build Coastguard Worker   service_data_0.uuid = pw::bluetooth::Uuid(uuid_0);
142*61c4878aSAndroid Build Coastguard Worker   std::array<std::byte, 3> service_data_0_data = {
143*61c4878aSAndroid Build Coastguard Worker       std::byte{0x00}, std::byte{0x01}, std::byte{0x02}};
144*61c4878aSAndroid Build Coastguard Worker   service_data_0.data = pw::span(service_data_0_data);
145*61c4878aSAndroid Build Coastguard Worker 
146*61c4878aSAndroid Build Coastguard Worker   pw::bluetooth::low_energy::ServiceData service_data_1;
147*61c4878aSAndroid Build Coastguard Worker   service_data_1.uuid = pw::bluetooth::Uuid(uuid_1);
148*61c4878aSAndroid Build Coastguard Worker   std::array<std::byte, 3> service_data_1_data = {
149*61c4878aSAndroid Build Coastguard Worker       std::byte{0x10}, std::byte{0x11}, std::byte{0x12}};
150*61c4878aSAndroid Build Coastguard Worker   service_data_1.data = pw::span(service_data_1_data);
151*61c4878aSAndroid Build Coastguard Worker 
152*61c4878aSAndroid Build Coastguard Worker   std::array<pw::bluetooth::low_energy::ServiceData, 2> service_data = {
153*61c4878aSAndroid Build Coastguard Worker       service_data_0, service_data_1};
154*61c4878aSAndroid Build Coastguard Worker   Peripheral2::AdvertisingParameters parameters;
155*61c4878aSAndroid Build Coastguard Worker   parameters.data.service_data = service_data;
156*61c4878aSAndroid Build Coastguard Worker 
157*61c4878aSAndroid Build Coastguard Worker   AdvertisedPeripheral2::Ptr advertised_peripheral =
158*61c4878aSAndroid Build Coastguard Worker       AdvertiseExpectSuccess(parameters);
159*61c4878aSAndroid Build Coastguard Worker 
160*61c4878aSAndroid Build Coastguard Worker   ASSERT_EQ(adapter().fake_le()->registered_advertisements().size(), 1u);
161*61c4878aSAndroid Build Coastguard Worker   auto& advertisement =
162*61c4878aSAndroid Build Coastguard Worker       adapter().fake_le()->registered_advertisements().begin()->second;
163*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(advertisement.data.service_data(bt::UUID(uuid_0)),
164*61c4878aSAndroid Build Coastguard Worker             bt::BufferView(service_data_0.data));
165*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(advertisement.data.service_data(bt::UUID(uuid_1)),
166*61c4878aSAndroid Build Coastguard Worker             bt::BufferView(service_data_1.data));
167*61c4878aSAndroid Build Coastguard Worker }
168*61c4878aSAndroid Build Coastguard Worker 
TEST_F(PeripheralTest,StartAdvertisingWithServiceUuids)169*61c4878aSAndroid Build Coastguard Worker TEST_F(PeripheralTest, StartAdvertisingWithServiceUuids) {
170*61c4878aSAndroid Build Coastguard Worker   const uint16_t uuid_0 = 42, uuid_1 = 43;
171*61c4878aSAndroid Build Coastguard Worker   std::array<pw::bluetooth::Uuid, 2> service_uuids = {
172*61c4878aSAndroid Build Coastguard Worker       pw::bluetooth::Uuid(uuid_0), pw::bluetooth::Uuid(uuid_1)};
173*61c4878aSAndroid Build Coastguard Worker   std::unordered_set<bt::UUID> expected_uuids{bt::UUID(uuid_0),
174*61c4878aSAndroid Build Coastguard Worker                                               bt::UUID(uuid_1)};
175*61c4878aSAndroid Build Coastguard Worker   Peripheral2::AdvertisingParameters parameters;
176*61c4878aSAndroid Build Coastguard Worker   parameters.data.service_uuids = service_uuids;
177*61c4878aSAndroid Build Coastguard Worker 
178*61c4878aSAndroid Build Coastguard Worker   AdvertisedPeripheral2::Ptr advertised_peripheral =
179*61c4878aSAndroid Build Coastguard Worker       AdvertiseExpectSuccess(parameters);
180*61c4878aSAndroid Build Coastguard Worker 
181*61c4878aSAndroid Build Coastguard Worker   ASSERT_EQ(adapter().fake_le()->registered_advertisements().size(), 1u);
182*61c4878aSAndroid Build Coastguard Worker   auto& advertisement =
183*61c4878aSAndroid Build Coastguard Worker       adapter().fake_le()->registered_advertisements().begin()->second;
184*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(advertisement.data.service_uuids(), expected_uuids);
185*61c4878aSAndroid Build Coastguard Worker }
186*61c4878aSAndroid Build Coastguard Worker 
TEST_F(PeripheralTest,StartAdvertisingWithManufacturerData)187*61c4878aSAndroid Build Coastguard Worker TEST_F(PeripheralTest, StartAdvertisingWithManufacturerData) {
188*61c4878aSAndroid Build Coastguard Worker   std::array<std::byte, 3> data_0 = {
189*61c4878aSAndroid Build Coastguard Worker       std::byte{0x00}, std::byte{0x01}, std::byte{0x02}};
190*61c4878aSAndroid Build Coastguard Worker   std::array<std::byte, 3> data_1 = {
191*61c4878aSAndroid Build Coastguard Worker       std::byte{0x03}, std::byte{0x04}, std::byte{0x05}};
192*61c4878aSAndroid Build Coastguard Worker   std::array<ManufacturerData, 2> manufacturer_data{
193*61c4878aSAndroid Build Coastguard Worker       ManufacturerData{.company_id = 0, .data = data_0},
194*61c4878aSAndroid Build Coastguard Worker       ManufacturerData{.company_id = 1, .data = data_1}};
195*61c4878aSAndroid Build Coastguard Worker   Peripheral2::AdvertisingParameters parameters;
196*61c4878aSAndroid Build Coastguard Worker   parameters.data.manufacturer_data = manufacturer_data;
197*61c4878aSAndroid Build Coastguard Worker 
198*61c4878aSAndroid Build Coastguard Worker   AdvertisedPeripheral2::Ptr advertised_peripheral =
199*61c4878aSAndroid Build Coastguard Worker       AdvertiseExpectSuccess(parameters);
200*61c4878aSAndroid Build Coastguard Worker 
201*61c4878aSAndroid Build Coastguard Worker   ASSERT_EQ(adapter().fake_le()->registered_advertisements().size(), 1u);
202*61c4878aSAndroid Build Coastguard Worker   auto& advertisement =
203*61c4878aSAndroid Build Coastguard Worker       adapter().fake_le()->registered_advertisements().begin()->second;
204*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(advertisement.data.manufacturer_data(0), bt::BufferView(data_0));
205*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(advertisement.data.manufacturer_data(1), bt::BufferView(data_1));
206*61c4878aSAndroid Build Coastguard Worker }
207*61c4878aSAndroid Build Coastguard Worker 
TEST_F(PeripheralTest,StartAdvertisingWithUris)208*61c4878aSAndroid Build Coastguard Worker TEST_F(PeripheralTest, StartAdvertisingWithUris) {
209*61c4878aSAndroid Build Coastguard Worker   std::string uri_0("https://abc.xyz");
210*61c4878aSAndroid Build Coastguard Worker   std::string uri_1("https://pigweed.dev");
211*61c4878aSAndroid Build Coastguard Worker   std::array<std::string_view, 2> uris = {uri_0, uri_1};
212*61c4878aSAndroid Build Coastguard Worker   std::unordered_set<std::string> uri_set = {uri_0, uri_1};
213*61c4878aSAndroid Build Coastguard Worker   Peripheral2::AdvertisingParameters parameters;
214*61c4878aSAndroid Build Coastguard Worker   parameters.data.uris = uris;
215*61c4878aSAndroid Build Coastguard Worker 
216*61c4878aSAndroid Build Coastguard Worker   AdvertisedPeripheral2::Ptr advertised_peripheral =
217*61c4878aSAndroid Build Coastguard Worker       AdvertiseExpectSuccess(parameters);
218*61c4878aSAndroid Build Coastguard Worker 
219*61c4878aSAndroid Build Coastguard Worker   ASSERT_EQ(adapter().fake_le()->registered_advertisements().size(), 1u);
220*61c4878aSAndroid Build Coastguard Worker   auto& advertisement =
221*61c4878aSAndroid Build Coastguard Worker       adapter().fake_le()->registered_advertisements().begin()->second;
222*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(advertisement.data.uris(), uri_set);
223*61c4878aSAndroid Build Coastguard Worker }
224*61c4878aSAndroid Build Coastguard Worker 
TEST_F(PeripheralTest,StartAdvertisingWithPublicAddressType)225*61c4878aSAndroid Build Coastguard Worker TEST_F(PeripheralTest, StartAdvertisingWithPublicAddressType) {
226*61c4878aSAndroid Build Coastguard Worker   Peripheral2::AdvertisingParameters parameters;
227*61c4878aSAndroid Build Coastguard Worker   parameters.address_type = pw::bluetooth::Address::Type::kPublic;
228*61c4878aSAndroid Build Coastguard Worker 
229*61c4878aSAndroid Build Coastguard Worker   AdvertisedPeripheral2::Ptr advertised_peripheral =
230*61c4878aSAndroid Build Coastguard Worker       AdvertiseExpectSuccess(parameters);
231*61c4878aSAndroid Build Coastguard Worker 
232*61c4878aSAndroid Build Coastguard Worker   ASSERT_EQ(adapter().fake_le()->registered_advertisements().size(), 1u);
233*61c4878aSAndroid Build Coastguard Worker   auto& advertisement =
234*61c4878aSAndroid Build Coastguard Worker       adapter().fake_le()->registered_advertisements().begin()->second;
235*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(advertisement.addr_type, bt::DeviceAddress::Type::kLEPublic);
236*61c4878aSAndroid Build Coastguard Worker }
237*61c4878aSAndroid Build Coastguard Worker 
TEST_F(PeripheralTest,StartAdvertisingWithRandomAddressType)238*61c4878aSAndroid Build Coastguard Worker TEST_F(PeripheralTest, StartAdvertisingWithRandomAddressType) {
239*61c4878aSAndroid Build Coastguard Worker   adapter().fake_le()->EnablePrivacy(true);
240*61c4878aSAndroid Build Coastguard Worker 
241*61c4878aSAndroid Build Coastguard Worker   Peripheral2::AdvertisingParameters parameters;
242*61c4878aSAndroid Build Coastguard Worker   parameters.address_type =
243*61c4878aSAndroid Build Coastguard Worker       pw::bluetooth::Address::Type::kRandomResolvablePrivate;
244*61c4878aSAndroid Build Coastguard Worker 
245*61c4878aSAndroid Build Coastguard Worker   AdvertisedPeripheral2::Ptr advertised_peripheral =
246*61c4878aSAndroid Build Coastguard Worker       AdvertiseExpectSuccess(parameters);
247*61c4878aSAndroid Build Coastguard Worker 
248*61c4878aSAndroid Build Coastguard Worker   ASSERT_EQ(adapter().fake_le()->registered_advertisements().size(), 1u);
249*61c4878aSAndroid Build Coastguard Worker   auto& advertisement =
250*61c4878aSAndroid Build Coastguard Worker       adapter().fake_le()->registered_advertisements().begin()->second;
251*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(advertisement.addr_type, bt::DeviceAddress::Type::kLERandom);
252*61c4878aSAndroid Build Coastguard Worker }
253*61c4878aSAndroid Build Coastguard Worker 
TEST_F(PeripheralTest,StartAdvertisingWithLegacyProcedureWithScanResponse)254*61c4878aSAndroid Build Coastguard Worker TEST_F(PeripheralTest, StartAdvertisingWithLegacyProcedureWithScanResponse) {
255*61c4878aSAndroid Build Coastguard Worker   pw::bluetooth::low_energy::AdvertisingData scan_rsp;
256*61c4878aSAndroid Build Coastguard Worker   scan_rsp.name = "robot";
257*61c4878aSAndroid Build Coastguard Worker   Peripheral2::AdvertisingParameters parameters;
258*61c4878aSAndroid Build Coastguard Worker   parameters.procedure = Peripheral2::LegacyAdvertising{
259*61c4878aSAndroid Build Coastguard Worker       .scan_response = std::move(scan_rsp), .connection_options = std::nullopt};
260*61c4878aSAndroid Build Coastguard Worker 
261*61c4878aSAndroid Build Coastguard Worker   AdvertisedPeripheral2::Ptr advertised_peripheral =
262*61c4878aSAndroid Build Coastguard Worker       AdvertiseExpectSuccess(parameters);
263*61c4878aSAndroid Build Coastguard Worker 
264*61c4878aSAndroid Build Coastguard Worker   ASSERT_EQ(adapter().fake_le()->registered_advertisements().size(), 1u);
265*61c4878aSAndroid Build Coastguard Worker   auto& advertisement =
266*61c4878aSAndroid Build Coastguard Worker       adapter().fake_le()->registered_advertisements().begin()->second;
267*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(advertisement.scan_response.local_name()->name, "robot");
268*61c4878aSAndroid Build Coastguard Worker }
269*61c4878aSAndroid Build Coastguard Worker 
TEST_F(PeripheralTest,StartAdvertisingWithLegacyProcedureWithConnectionOptionsNonBondable)270*61c4878aSAndroid Build Coastguard Worker TEST_F(PeripheralTest,
271*61c4878aSAndroid Build Coastguard Worker        StartAdvertisingWithLegacyProcedureWithConnectionOptionsNonBondable) {
272*61c4878aSAndroid Build Coastguard Worker   Peripheral2::AdvertisingParameters parameters;
273*61c4878aSAndroid Build Coastguard Worker   Peripheral2::ConnectionOptions connection_options{
274*61c4878aSAndroid Build Coastguard Worker       .bondable_mode = false,
275*61c4878aSAndroid Build Coastguard Worker       .service_filter = std::nullopt,
276*61c4878aSAndroid Build Coastguard Worker       .parameters = std::nullopt,
277*61c4878aSAndroid Build Coastguard Worker       .att_mtu = std::nullopt};
278*61c4878aSAndroid Build Coastguard Worker   parameters.procedure = Peripheral2::LegacyAdvertising{
279*61c4878aSAndroid Build Coastguard Worker       .scan_response = std::nullopt, .connection_options = connection_options};
280*61c4878aSAndroid Build Coastguard Worker 
281*61c4878aSAndroid Build Coastguard Worker   AdvertisedPeripheral2::Ptr advertised_peripheral =
282*61c4878aSAndroid Build Coastguard Worker       AdvertiseExpectSuccess(parameters);
283*61c4878aSAndroid Build Coastguard Worker 
284*61c4878aSAndroid Build Coastguard Worker   ASSERT_EQ(adapter().fake_le()->registered_advertisements().size(), 1u);
285*61c4878aSAndroid Build Coastguard Worker   auto& advertisement =
286*61c4878aSAndroid Build Coastguard Worker       adapter().fake_le()->registered_advertisements().begin()->second;
287*61c4878aSAndroid Build Coastguard Worker   ASSERT_TRUE(advertisement.connectable.has_value());
288*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(advertisement.connectable->bondable_mode,
289*61c4878aSAndroid Build Coastguard Worker             bt::sm::BondableMode::NonBondable);
290*61c4878aSAndroid Build Coastguard Worker }
291*61c4878aSAndroid Build Coastguard Worker 
TEST_F(PeripheralTest,StartAdvertisingWithLegacyProcedureWithConnectionOptionsBondable)292*61c4878aSAndroid Build Coastguard Worker TEST_F(PeripheralTest,
293*61c4878aSAndroid Build Coastguard Worker        StartAdvertisingWithLegacyProcedureWithConnectionOptionsBondable) {
294*61c4878aSAndroid Build Coastguard Worker   Peripheral2::AdvertisingParameters parameters;
295*61c4878aSAndroid Build Coastguard Worker   Peripheral2::ConnectionOptions connection_options{
296*61c4878aSAndroid Build Coastguard Worker       .bondable_mode = true,
297*61c4878aSAndroid Build Coastguard Worker       .service_filter = std::nullopt,
298*61c4878aSAndroid Build Coastguard Worker       .parameters = std::nullopt,
299*61c4878aSAndroid Build Coastguard Worker       .att_mtu = std::nullopt};
300*61c4878aSAndroid Build Coastguard Worker   parameters.procedure = Peripheral2::LegacyAdvertising{
301*61c4878aSAndroid Build Coastguard Worker       .scan_response = std::nullopt, .connection_options = connection_options};
302*61c4878aSAndroid Build Coastguard Worker 
303*61c4878aSAndroid Build Coastguard Worker   AdvertisedPeripheral2::Ptr advertised_peripheral =
304*61c4878aSAndroid Build Coastguard Worker       AdvertiseExpectSuccess(parameters);
305*61c4878aSAndroid Build Coastguard Worker 
306*61c4878aSAndroid Build Coastguard Worker   ASSERT_EQ(adapter().fake_le()->registered_advertisements().size(), 1u);
307*61c4878aSAndroid Build Coastguard Worker   auto& advertisement =
308*61c4878aSAndroid Build Coastguard Worker       adapter().fake_le()->registered_advertisements().begin()->second;
309*61c4878aSAndroid Build Coastguard Worker   ASSERT_TRUE(advertisement.connectable.has_value());
310*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(advertisement.connectable->bondable_mode,
311*61c4878aSAndroid Build Coastguard Worker             bt::sm::BondableMode::Bondable);
312*61c4878aSAndroid Build Coastguard Worker }
313*61c4878aSAndroid Build Coastguard Worker 
TEST_F(PeripheralTest,StartAdvertisingAnonymous)314*61c4878aSAndroid Build Coastguard Worker TEST_F(PeripheralTest, StartAdvertisingAnonymous) {
315*61c4878aSAndroid Build Coastguard Worker   Peripheral2::AdvertisingParameters parameters;
316*61c4878aSAndroid Build Coastguard Worker   parameters.procedure = Peripheral2::ExtendedAdvertising{
317*61c4878aSAndroid Build Coastguard Worker       .configuration = pw::bluetooth::low_energy::Peripheral2::
318*61c4878aSAndroid Build Coastguard Worker           ExtendedAdvertising::Anonymous(),
319*61c4878aSAndroid Build Coastguard Worker       .tx_power = std::nullopt,
320*61c4878aSAndroid Build Coastguard Worker       .primary_phy = pw::bluetooth::low_energy::Phy::k1Megabit,
321*61c4878aSAndroid Build Coastguard Worker       .secondary_phy = pw::bluetooth::low_energy::Phy::k1Megabit};
322*61c4878aSAndroid Build Coastguard Worker 
323*61c4878aSAndroid Build Coastguard Worker   AdvertisedPeripheral2::Ptr advertised_peripheral =
324*61c4878aSAndroid Build Coastguard Worker       AdvertiseExpectSuccess(parameters);
325*61c4878aSAndroid Build Coastguard Worker 
326*61c4878aSAndroid Build Coastguard Worker   ASSERT_EQ(adapter().fake_le()->registered_advertisements().size(), 1u);
327*61c4878aSAndroid Build Coastguard Worker   auto& advertisement =
328*61c4878aSAndroid Build Coastguard Worker       adapter().fake_le()->registered_advertisements().begin()->second;
329*61c4878aSAndroid Build Coastguard Worker   EXPECT_TRUE(advertisement.anonymous);
330*61c4878aSAndroid Build Coastguard Worker }
331*61c4878aSAndroid Build Coastguard Worker 
TEST_F(PeripheralTest,StartAdvertisingWithExtendedProcedureWithScanResponse)332*61c4878aSAndroid Build Coastguard Worker TEST_F(PeripheralTest, StartAdvertisingWithExtendedProcedureWithScanResponse) {
333*61c4878aSAndroid Build Coastguard Worker   Peripheral2::ScanResponse scan_rsp;
334*61c4878aSAndroid Build Coastguard Worker   scan_rsp.name = "robot";
335*61c4878aSAndroid Build Coastguard Worker   Peripheral2::AdvertisingParameters parameters;
336*61c4878aSAndroid Build Coastguard Worker   parameters.procedure = Peripheral2::ExtendedAdvertising{
337*61c4878aSAndroid Build Coastguard Worker       .configuration = scan_rsp,
338*61c4878aSAndroid Build Coastguard Worker       .tx_power = std::nullopt,
339*61c4878aSAndroid Build Coastguard Worker       .primary_phy = pw::bluetooth::low_energy::Phy::k1Megabit,
340*61c4878aSAndroid Build Coastguard Worker       .secondary_phy = pw::bluetooth::low_energy::Phy::k1Megabit};
341*61c4878aSAndroid Build Coastguard Worker 
342*61c4878aSAndroid Build Coastguard Worker   AdvertisedPeripheral2::Ptr advertised_peripheral =
343*61c4878aSAndroid Build Coastguard Worker       AdvertiseExpectSuccess(parameters);
344*61c4878aSAndroid Build Coastguard Worker 
345*61c4878aSAndroid Build Coastguard Worker   ASSERT_EQ(adapter().fake_le()->registered_advertisements().size(), 1u);
346*61c4878aSAndroid Build Coastguard Worker   auto& advertisement =
347*61c4878aSAndroid Build Coastguard Worker       adapter().fake_le()->registered_advertisements().begin()->second;
348*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(advertisement.scan_response.local_name()->name, "robot");
349*61c4878aSAndroid Build Coastguard Worker   EXPECT_FALSE(advertisement.anonymous);
350*61c4878aSAndroid Build Coastguard Worker }
351*61c4878aSAndroid Build Coastguard Worker 
TEST_F(PeripheralTest,StartAdvertisingWithExtendedProcedureWithConnectionOptionsNonBondable)352*61c4878aSAndroid Build Coastguard Worker TEST_F(PeripheralTest,
353*61c4878aSAndroid Build Coastguard Worker        StartAdvertisingWithExtendedProcedureWithConnectionOptionsNonBondable) {
354*61c4878aSAndroid Build Coastguard Worker   Peripheral2::AdvertisingParameters parameters;
355*61c4878aSAndroid Build Coastguard Worker   Peripheral2::ConnectionOptions connection_options{
356*61c4878aSAndroid Build Coastguard Worker       .bondable_mode = false,
357*61c4878aSAndroid Build Coastguard Worker       .service_filter = std::nullopt,
358*61c4878aSAndroid Build Coastguard Worker       .parameters = std::nullopt,
359*61c4878aSAndroid Build Coastguard Worker       .att_mtu = std::nullopt};
360*61c4878aSAndroid Build Coastguard Worker   parameters.procedure = Peripheral2::ExtendedAdvertising{
361*61c4878aSAndroid Build Coastguard Worker       .configuration = connection_options,
362*61c4878aSAndroid Build Coastguard Worker       .tx_power = std::nullopt,
363*61c4878aSAndroid Build Coastguard Worker       .primary_phy = pw::bluetooth::low_energy::Phy::k1Megabit,
364*61c4878aSAndroid Build Coastguard Worker       .secondary_phy = pw::bluetooth::low_energy::Phy::k1Megabit};
365*61c4878aSAndroid Build Coastguard Worker 
366*61c4878aSAndroid Build Coastguard Worker   AdvertisedPeripheral2::Ptr advertised_peripheral =
367*61c4878aSAndroid Build Coastguard Worker       AdvertiseExpectSuccess(parameters);
368*61c4878aSAndroid Build Coastguard Worker 
369*61c4878aSAndroid Build Coastguard Worker   ASSERT_EQ(adapter().fake_le()->registered_advertisements().size(), 1u);
370*61c4878aSAndroid Build Coastguard Worker   auto& advertisement =
371*61c4878aSAndroid Build Coastguard Worker       adapter().fake_le()->registered_advertisements().begin()->second;
372*61c4878aSAndroid Build Coastguard Worker   ASSERT_TRUE(advertisement.connectable.has_value());
373*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(advertisement.connectable->bondable_mode,
374*61c4878aSAndroid Build Coastguard Worker             bt::sm::BondableMode::NonBondable);
375*61c4878aSAndroid Build Coastguard Worker }
376*61c4878aSAndroid Build Coastguard Worker 
TEST_F(PeripheralTest,StartAdvertisingWithExtendedProcedureWithConnectionOptionsBondable)377*61c4878aSAndroid Build Coastguard Worker TEST_F(PeripheralTest,
378*61c4878aSAndroid Build Coastguard Worker        StartAdvertisingWithExtendedProcedureWithConnectionOptionsBondable) {
379*61c4878aSAndroid Build Coastguard Worker   Peripheral2::AdvertisingParameters parameters;
380*61c4878aSAndroid Build Coastguard Worker   Peripheral2::ConnectionOptions connection_options{
381*61c4878aSAndroid Build Coastguard Worker       .bondable_mode = true,
382*61c4878aSAndroid Build Coastguard Worker       .service_filter = std::nullopt,
383*61c4878aSAndroid Build Coastguard Worker       .parameters = std::nullopt,
384*61c4878aSAndroid Build Coastguard Worker       .att_mtu = std::nullopt};
385*61c4878aSAndroid Build Coastguard Worker   parameters.procedure = Peripheral2::ExtendedAdvertising{
386*61c4878aSAndroid Build Coastguard Worker       .configuration = connection_options,
387*61c4878aSAndroid Build Coastguard Worker       .tx_power = std::nullopt,
388*61c4878aSAndroid Build Coastguard Worker       .primary_phy = pw::bluetooth::low_energy::Phy::k1Megabit,
389*61c4878aSAndroid Build Coastguard Worker       .secondary_phy = pw::bluetooth::low_energy::Phy::k1Megabit};
390*61c4878aSAndroid Build Coastguard Worker 
391*61c4878aSAndroid Build Coastguard Worker   AdvertisedPeripheral2::Ptr advertised_peripheral =
392*61c4878aSAndroid Build Coastguard Worker       AdvertiseExpectSuccess(parameters);
393*61c4878aSAndroid Build Coastguard Worker 
394*61c4878aSAndroid Build Coastguard Worker   ASSERT_EQ(adapter().fake_le()->registered_advertisements().size(), 1u);
395*61c4878aSAndroid Build Coastguard Worker   auto& advertisement =
396*61c4878aSAndroid Build Coastguard Worker       adapter().fake_le()->registered_advertisements().begin()->second;
397*61c4878aSAndroid Build Coastguard Worker   ASSERT_TRUE(advertisement.connectable.has_value());
398*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(advertisement.connectable->bondable_mode,
399*61c4878aSAndroid Build Coastguard Worker             bt::sm::BondableMode::Bondable);
400*61c4878aSAndroid Build Coastguard Worker }
401*61c4878aSAndroid Build Coastguard Worker 
TEST_F(PeripheralTest,StartAdvertisingFailureInternalError)402*61c4878aSAndroid Build Coastguard Worker TEST_F(PeripheralTest, StartAdvertisingFailureInternalError) {
403*61c4878aSAndroid Build Coastguard Worker   adapter().fake_le()->set_advertising_result(
404*61c4878aSAndroid Build Coastguard Worker       ToResult(bt::HostError::kScanResponseTooLong));
405*61c4878aSAndroid Build Coastguard Worker   Peripheral2::AdvertisingParameters parameters;
406*61c4878aSAndroid Build Coastguard Worker   std::optional<Peripheral2::AdvertiseResult> result = Advertise(parameters);
407*61c4878aSAndroid Build Coastguard Worker   ASSERT_TRUE(result.has_value());
408*61c4878aSAndroid Build Coastguard Worker   ASSERT_FALSE(result.value().has_value());
409*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(result.value().error(), AdvertiseError::kScanResponseDataTooLong);
410*61c4878aSAndroid Build Coastguard Worker }
411*61c4878aSAndroid Build Coastguard Worker 
TEST_F(PeripheralTest,StartAdvertisingAndCallAdvertisedPeripheralStopAdvertising)412*61c4878aSAndroid Build Coastguard Worker TEST_F(PeripheralTest,
413*61c4878aSAndroid Build Coastguard Worker        StartAdvertisingAndCallAdvertisedPeripheralStopAdvertising) {
414*61c4878aSAndroid Build Coastguard Worker   Peripheral2::AdvertisingParameters parameters;
415*61c4878aSAndroid Build Coastguard Worker 
416*61c4878aSAndroid Build Coastguard Worker   AdvertisedPeripheral2::Ptr advertised_peripheral =
417*61c4878aSAndroid Build Coastguard Worker       AdvertiseExpectSuccess(parameters);
418*61c4878aSAndroid Build Coastguard Worker   ASSERT_EQ(adapter().fake_le()->registered_advertisements().size(), 1u);
419*61c4878aSAndroid Build Coastguard Worker 
420*61c4878aSAndroid Build Coastguard Worker   advertised_peripheral->StopAdvertising();
421*61c4878aSAndroid Build Coastguard Worker 
422*61c4878aSAndroid Build Coastguard Worker   pw::async2::PendFuncTask stop_task(
423*61c4878aSAndroid Build Coastguard Worker       [&advertised_peripheral](pw::async2::Context& cx) -> pw::async2::Poll<> {
424*61c4878aSAndroid Build Coastguard Worker         pw::async2::Poll<pw::Status> pend = advertised_peripheral->PendStop(cx);
425*61c4878aSAndroid Build Coastguard Worker         if (pend.IsReady()) {
426*61c4878aSAndroid Build Coastguard Worker           EXPECT_TRUE(pend->ok());
427*61c4878aSAndroid Build Coastguard Worker           return pw::async2::Ready();
428*61c4878aSAndroid Build Coastguard Worker         }
429*61c4878aSAndroid Build Coastguard Worker         return pw::async2::Pending();
430*61c4878aSAndroid Build Coastguard Worker       });
431*61c4878aSAndroid Build Coastguard Worker   dispatcher2().Post(stop_task);
432*61c4878aSAndroid Build Coastguard Worker 
433*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(dispatcher2().RunUntilStalled(stop_task), pw::async2::Pending());
434*61c4878aSAndroid Build Coastguard Worker   ASSERT_EQ(adapter().fake_le()->registered_advertisements().size(), 1u);
435*61c4878aSAndroid Build Coastguard Worker 
436*61c4878aSAndroid Build Coastguard Worker   // Process the stop request.
437*61c4878aSAndroid Build Coastguard Worker   dispatcher().RunUntilIdle();
438*61c4878aSAndroid Build Coastguard Worker   // Process the waker wake.
439*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(dispatcher2().RunUntilStalled(stop_task), pw::async2::Ready());
440*61c4878aSAndroid Build Coastguard Worker   ASSERT_EQ(adapter().fake_le()->registered_advertisements().size(), 0u);
441*61c4878aSAndroid Build Coastguard Worker }
442