/* * Copyright 2022 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "hci/remote_name_request.h" #include #include #include #include #include #include #include #include #include #include "hci/address.h" #include "hci/hci_layer_fake.h" #include "os/thread.h" namespace bluetooth { namespace hci { namespace { using ::testing::Eq; const auto address1 = Address::FromString("A1:A2:A3:A4:A5:A6").value(); const auto address2 = Address::FromString("B1:B2:B3:B4:B5:B6").value(); const auto address3 = Address::FromString("C1:C2:C3:C4:C5:C6").value(); const auto remote_name1 = std::array{1, 2, 3}; const auto timeout = std::chrono::milliseconds(100); MATCHER(IsSet, "Future is not set") { if (arg.wait_for(timeout) != std::future_status::ready) { return false; } const_cast&>(arg).get(); return true; } MATCHER_P(IsSetWithValue, matcher, "Future is not set with value") { if (arg.wait_for(timeout) != std::future_status::ready) { return false; } EXPECT_THAT(const_cast&>(arg).get(), matcher); return true; } class RemoteNameRequestModuleTest : public ::testing::Test { protected: void SetUp() override { test_hci_layer_ = new HciLayerFake; fake_registry_.InjectTestModule(&HciLayer::Factory, test_hci_layer_); fake_registry_.Start(&thread_); ASSERT_TRUE(fake_registry_.IsStarted()); client_handler_ = fake_registry_.GetTestModuleHandler(&RemoteNameRequestModule::Factory); ASSERT_NE(client_handler_, nullptr); remote_name_request_module_ = static_cast( fake_registry_.GetModuleUnderTest(&RemoteNameRequestModule::Factory)); ::testing::FLAGS_gtest_death_test_style = "threadsafe"; } void TearDown() override { fake_registry_.SynchronizeModuleHandler(&RemoteNameRequestModule::Factory, timeout); fake_registry_.StopAll(); } template common::ContextualOnceCallback impossibleCallback() { return client_handler_->BindOnce([](T... /* args */) { ADD_FAILURE(); }); } template common::ContextualOnceCallback emptyCallback() { return client_handler_->BindOnce([](T... /* args */) {}); } template common::ContextualOnceCallback promiseCallback(std::promise promise) { return client_handler_->BindOnce( [](std::promise promise, T... /* args */) { promise.set_value(); }, std::move(promise)); } template common::ContextualOnceCallback capturingPromiseCallback( std::promise> promise) { return client_handler_->BindOnce( [](std::promise> promise, T... args) { promise.set_value(std::make_tuple(args...)); }, std::move(promise)); } template common::ContextualOnceCallback capturingPromiseCallback(std::promise promise) { return client_handler_->BindOnce( [](std::promise promise, T arg) { promise.set_value(arg); }, std::move(promise)); } TestModuleRegistry fake_registry_; os::Thread& thread_ = fake_registry_.GetTestThread(); HciLayerFake* test_hci_layer_ = nullptr; RemoteNameRequestModule* remote_name_request_module_ = nullptr; os::Handler* client_handler_ = nullptr; }; TEST_F(RemoteNameRequestModuleTest, CorrectCommandSent) { // start a remote name request remote_name_request_module_->StartRemoteNameRequest( address1, RemoteNameRequestBuilder::Create( address1, PageScanRepetitionMode::R0, 3, ClockOffsetValid::INVALID), impossibleCallback(), impossibleCallback(), impossibleCallback>()); // verify that the correct HCI command was sent auto command = test_hci_layer_->GetCommand(); auto discovery_command = DiscoveryCommandView::Create(command); ASSERT_TRUE(discovery_command.IsValid()); auto rnr_command = RemoteNameRequestView::Create(DiscoveryCommandView::Create(discovery_command)); ASSERT_TRUE(rnr_command.IsValid()); EXPECT_EQ(rnr_command.GetBdAddr(), address1); EXPECT_EQ(rnr_command.GetPageScanRepetitionMode(), PageScanRepetitionMode::R0); EXPECT_EQ(rnr_command.GetClockOffset(), 3); EXPECT_EQ(rnr_command.GetClockOffsetValid(), ClockOffsetValid::INVALID); } TEST_F(RemoteNameRequestModuleTest, FailToSendCommand) { auto promise = std::promise{}; auto future = promise.get_future(); // start a remote name request remote_name_request_module_->StartRemoteNameRequest( address1, RemoteNameRequestBuilder::Create( address1, PageScanRepetitionMode::R0, 3, ClockOffsetValid::INVALID), capturingPromiseCallback(std::move(promise)), impossibleCallback(), impossibleCallback>()); // on the command, return a failure HCI status test_hci_layer_->GetCommand(); test_hci_layer_->IncomingEvent( RemoteNameRequestStatusBuilder::Create(ErrorCode::STATUS_UNKNOWN, 1)); // the completion callback should be immediately invoked with the failing status EXPECT_THAT(future, IsSetWithValue(Eq(ErrorCode::STATUS_UNKNOWN))); } TEST_F(RemoteNameRequestModuleTest, SendCommandSuccessfully) { auto promise = std::promise{}; auto future = promise.get_future(); // start a remote name request remote_name_request_module_->StartRemoteNameRequest( address1, RemoteNameRequestBuilder::Create( address1, PageScanRepetitionMode::R0, 3, ClockOffsetValid::INVALID), capturingPromiseCallback(std::move(promise)), impossibleCallback(), impossibleCallback>()); // the command receives a successful reply, so it successfully starts test_hci_layer_->GetCommand(); test_hci_layer_->IncomingEvent(RemoteNameRequestStatusBuilder::Create(ErrorCode::SUCCESS, 1)); // the completion callback should be invoked with the failing status EXPECT_THAT(future, IsSetWithValue(Eq(ErrorCode::SUCCESS))); } TEST_F(RemoteNameRequestModuleTest, SendCommandThenCancelIt) { auto promise = std::promise{}; auto future = promise.get_future(); // start a remote name request remote_name_request_module_->StartRemoteNameRequest( address1, RemoteNameRequestBuilder::Create( address1, PageScanRepetitionMode::R0, 3, ClockOffsetValid::INVALID), emptyCallback(), impossibleCallback(), impossibleCallback>()); // we successfully start test_hci_layer_->GetCommand(); test_hci_layer_->IncomingEvent(RemoteNameRequestStatusBuilder::Create(ErrorCode::SUCCESS, 1)); // but then the request is cancelled remote_name_request_module_->CancelRemoteNameRequest(address1); // get the cancel command and check it is correct auto command = test_hci_layer_->GetCommand(); auto discovery_command = DiscoveryCommandView::Create(command); ASSERT_TRUE(discovery_command.IsValid()); auto cancel_command = RemoteNameRequestCancelView::Create(DiscoveryCommandView::Create(discovery_command)); ASSERT_TRUE(cancel_command.IsValid()); EXPECT_EQ(cancel_command.GetBdAddr(), address1); } TEST_F(RemoteNameRequestModuleTest, SendCommandThenCancelItCallback) { auto promise = std::promise>>{}; auto future = promise.get_future(); // start a remote name request remote_name_request_module_->StartRemoteNameRequest( address1, RemoteNameRequestBuilder::Create( address1, PageScanRepetitionMode::R0, 3, ClockOffsetValid::INVALID), emptyCallback(), impossibleCallback(), capturingPromiseCallback>(std::move(promise))); // we successfully start test_hci_layer_->GetCommand(); test_hci_layer_->IncomingEvent(RemoteNameRequestStatusBuilder::Create(ErrorCode::SUCCESS, 1)); // but then the request is cancelled successfully (the status doesn't matter) remote_name_request_module_->CancelRemoteNameRequest(address1); test_hci_layer_->GetCommand(); test_hci_layer_->IncomingEvent( RemoteNameRequestCancelCompleteBuilder::Create(1, ErrorCode::SUCCESS, address1)); // verify that the completion has NOT yet been invoked (we need to wait for the RNR itself to // complete) EXPECT_THAT(future.wait_for(timeout), std::future_status::timeout); // let the RNR complete with a failure test_hci_layer_->IncomingEvent(RemoteNameRequestCompleteBuilder::Create( ErrorCode::UNKNOWN_CONNECTION, address1, remote_name1)); // only now should the name callback be invoked EXPECT_THAT( future, IsSetWithValue(Eq(std::make_tuple(ErrorCode::UNKNOWN_CONNECTION, remote_name1)))); } // TODO(aryarahul) - unify HciLayerFake so this test can be run TEST_F(RemoteNameRequestModuleTest, DISABLED_SendCommandThenCancelItCallbackInteropWorkaround) { // Some controllers INCORRECTLY give us an ACL Connection Complete event, rather than a Remote // Name Request Complete event, if we issue a cancellation. We should nonetheless handle this // properly. auto promise = std::promise>>{}; auto future = promise.get_future(); // start a remote name request remote_name_request_module_->StartRemoteNameRequest( address1, RemoteNameRequestBuilder::Create( address1, PageScanRepetitionMode::R0, 3, ClockOffsetValid::INVALID), emptyCallback(), impossibleCallback(), capturingPromiseCallback>(std::move(promise))); // we successfully start test_hci_layer_->GetCommand(); test_hci_layer_->IncomingEvent(RemoteNameRequestStatusBuilder::Create(ErrorCode::SUCCESS, 1)); // but then the request is cancelled successfully (the status doesn't matter) remote_name_request_module_->CancelRemoteNameRequest(address1); test_hci_layer_->GetCommand(); test_hci_layer_->IncomingEvent( RemoteNameRequestCancelCompleteBuilder::Create(1, ErrorCode::SUCCESS, address1)); // get the INCORRECT ACL connection complete event test_hci_layer_->IncomingEvent(ConnectionCompleteBuilder::Create( ErrorCode::UNKNOWN_CONNECTION, 0, address1, LinkType::ACL, Enable::DISABLED)); // we expect the name callback to be invoked nonetheless EXPECT_THAT( future, IsSetWithValue( Eq(std::make_tuple(ErrorCode::UNKNOWN_CONNECTION, std::array{})))); } // This test should be replaced with the above one, so we test the integration of AclManager and // RnrModule TEST_F(RemoteNameRequestModuleTest, SendCommandThenCancelItCallbackInteropWorkaround) { auto promise = std::promise>>{}; auto future = promise.get_future(); // start a remote name request remote_name_request_module_->StartRemoteNameRequest( address1, RemoteNameRequestBuilder::Create( address1, PageScanRepetitionMode::R0, 3, ClockOffsetValid::INVALID), emptyCallback(), impossibleCallback(), capturingPromiseCallback>(std::move(promise))); // we successfully start test_hci_layer_->GetCommand(); test_hci_layer_->IncomingEvent(RemoteNameRequestStatusBuilder::Create(ErrorCode::SUCCESS, 1)); // but then the request is cancelled successfully (the status doesn't matter) remote_name_request_module_->CancelRemoteNameRequest(address1); test_hci_layer_->GetCommand(); test_hci_layer_->IncomingEvent( RemoteNameRequestCancelCompleteBuilder::Create(1, ErrorCode::SUCCESS, address1)); // the INCORRECT ACL connection complete event will, from ACLManager, trigger this event remote_name_request_module_->ReportRemoteNameRequestCancellation(address1); // we expect the name callback to be invoked nonetheless EXPECT_THAT( future, IsSetWithValue( Eq(std::make_tuple(ErrorCode::UNKNOWN_CONNECTION, std::array{})))); } TEST_F(RemoteNameRequestModuleTest, SendCommandThenCancelItCancelFails) { auto promise = std::promise>>{}; auto future = promise.get_future(); // start a remote name request remote_name_request_module_->StartRemoteNameRequest( address1, RemoteNameRequestBuilder::Create( address1, PageScanRepetitionMode::R0, 3, ClockOffsetValid::INVALID), emptyCallback(), impossibleCallback(), capturingPromiseCallback>(std::move(promise))); // we successfully start test_hci_layer_->GetCommand(); test_hci_layer_->IncomingEvent(RemoteNameRequestStatusBuilder::Create(ErrorCode::SUCCESS, 1)); // but then the request is cancelled successfully (the status doesn't matter) remote_name_request_module_->CancelRemoteNameRequest(address1); test_hci_layer_->GetCommand(); test_hci_layer_->IncomingEvent(RemoteNameRequestCancelCompleteBuilder::Create( 1, ErrorCode::INVALID_HCI_COMMAND_PARAMETERS, address1)); // we expect the name callback to be invoked nonetheless EXPECT_THAT( future, IsSetWithValue(Eq( std::make_tuple(ErrorCode::INVALID_HCI_COMMAND_PARAMETERS, std::array{})))); } TEST_F(RemoteNameRequestModuleTest, HostSupportedEvents) { auto promise = std::promise{}; auto future = promise.get_future(); // start a remote name request remote_name_request_module_->StartRemoteNameRequest( address1, RemoteNameRequestBuilder::Create( address1, PageScanRepetitionMode::R0, 3, ClockOffsetValid::INVALID), emptyCallback(), capturingPromiseCallback(std::move(promise)), impossibleCallback>()); test_hci_layer_->GetCommand(); test_hci_layer_->IncomingEvent(RemoteNameRequestStatusBuilder::Create(ErrorCode::SUCCESS, 1)); // verify that the completion has NOT yet been invoked (we need to wait for the RNR itself to // complete) EXPECT_THAT(future.wait_for(timeout), std::future_status::timeout); // report host supported events test_hci_layer_->IncomingEvent( RemoteHostSupportedFeaturesNotificationBuilder::Create(address1, 1234)); // verify that we got the features EXPECT_THAT(future, IsSetWithValue(Eq((uint64_t)1234))); } TEST_F(RemoteNameRequestModuleTest, CompletedRemoteNameRequest) { auto promise = std::promise>>{}; auto future = promise.get_future(); // start a remote name request remote_name_request_module_->StartRemoteNameRequest( address1, RemoteNameRequestBuilder::Create( address1, PageScanRepetitionMode::R0, 3, ClockOffsetValid::INVALID), emptyCallback(), impossibleCallback(), capturingPromiseCallback>(std::move(promise))); test_hci_layer_->GetCommand(); test_hci_layer_->IncomingEvent(RemoteNameRequestStatusBuilder::Create(ErrorCode::SUCCESS, 1)); // verify that the completion has NOT yet been invoked (we need to wait for the RNR itself to // complete) EXPECT_THAT(future.wait_for(timeout), std::future_status::timeout); // report remote name (with some random status that should be passed through) test_hci_layer_->IncomingEvent( RemoteNameRequestCompleteBuilder::Create(ErrorCode::STATUS_UNKNOWN, address1, remote_name1)); // verify that the callback was invoked with the same status EXPECT_THAT(future, IsSetWithValue(Eq(std::make_tuple(ErrorCode::STATUS_UNKNOWN, remote_name1)))); } TEST_F(RemoteNameRequestModuleTest, QueuingRemoteNameRequestsSecondOneStarts) { auto promise1 = std::promise{}; auto future1 = promise1.get_future(); auto promise2 = std::promise>>{}; auto future2 = promise2.get_future(); // start a remote name request remote_name_request_module_->StartRemoteNameRequest( address1, RemoteNameRequestBuilder::Create( address1, PageScanRepetitionMode::R0, 3, ClockOffsetValid::INVALID), emptyCallback(), impossibleCallback(), promiseCallback>(std::move(promise1))); // enqueue a second one remote_name_request_module_->StartRemoteNameRequest( address2, RemoteNameRequestBuilder::Create( address2, PageScanRepetitionMode::R1, 4, ClockOffsetValid::VALID), emptyCallback(), impossibleCallback(), capturingPromiseCallback>(std::move(promise2))); // acknowledge that the first one has started test_hci_layer_->GetCommand(); test_hci_layer_->IncomingEvent(RemoteNameRequestStatusBuilder::Create(ErrorCode::SUCCESS, 1)); // report remote name for the first one test_hci_layer_->IncomingEvent( RemoteNameRequestCompleteBuilder::Create(ErrorCode::STATUS_UNKNOWN, address1, remote_name1)); // verify that the first callback was invoked EXPECT_THAT(future1, IsSet()); // verify that the second request has now started (so we are participating in the ACL scheduling // process) auto command = test_hci_layer_->GetCommand(); auto discovery_command = DiscoveryCommandView::Create(command); ASSERT_TRUE(discovery_command.IsValid()); auto rnr_command = RemoteNameRequestView::Create(DiscoveryCommandView::Create(discovery_command)); ASSERT_TRUE(rnr_command.IsValid()); EXPECT_EQ(rnr_command.GetBdAddr(), address2); EXPECT_EQ(rnr_command.GetPageScanRepetitionMode(), PageScanRepetitionMode::R1); EXPECT_EQ(rnr_command.GetClockOffset(), 4); EXPECT_EQ(rnr_command.GetClockOffsetValid(), ClockOffsetValid::VALID); } TEST_F(RemoteNameRequestModuleTest, QueuingRemoteNameRequestsSecondOneCancelledWhileQueued) { auto promise = std::promise>>{}; auto future = promise.get_future(); // start a remote name request remote_name_request_module_->StartRemoteNameRequest( address1, RemoteNameRequestBuilder::Create( address1, PageScanRepetitionMode::R0, 3, ClockOffsetValid::INVALID), emptyCallback(), impossibleCallback(), emptyCallback>()); // enqueue a second one remote_name_request_module_->StartRemoteNameRequest( address2, RemoteNameRequestBuilder::Create( address2, PageScanRepetitionMode::R1, 4, ClockOffsetValid::VALID), emptyCallback(), impossibleCallback(), capturingPromiseCallback>(std::move(promise))); // acknowledge that the first one has started test_hci_layer_->GetCommand(); test_hci_layer_->IncomingEvent(RemoteNameRequestStatusBuilder::Create(ErrorCode::SUCCESS, 1)); // cancel the second one remote_name_request_module_->CancelRemoteNameRequest(address2); // verify that the cancellation callback was properly invoked immediately EXPECT_THAT( future, IsSetWithValue(Eq(std::make_tuple(ErrorCode::PAGE_TIMEOUT, std::array{})))); } TEST_F(RemoteNameRequestModuleTest, QueuingRemoteNameRequestsCancelFirst) { auto promise1 = std::promise{}; auto future1 = promise1.get_future(); auto promise2 = std::promise>>{}; auto future2 = promise2.get_future(); // start a remote name request remote_name_request_module_->StartRemoteNameRequest( address1, RemoteNameRequestBuilder::Create( address1, PageScanRepetitionMode::R0, 3, ClockOffsetValid::INVALID), emptyCallback(), impossibleCallback(), promiseCallback>(std::move(promise1))); // enqueue a second one remote_name_request_module_->StartRemoteNameRequest( address2, RemoteNameRequestBuilder::Create( address2, PageScanRepetitionMode::R1, 4, ClockOffsetValid::VALID), emptyCallback(), impossibleCallback(), capturingPromiseCallback>(std::move(promise2))); // acknowledge that the first one has started test_hci_layer_->GetCommand(); test_hci_layer_->IncomingEvent(RemoteNameRequestStatusBuilder::Create(ErrorCode::SUCCESS, 1)); // cancel the first one remote_name_request_module_->CancelRemoteNameRequest(address1); // let the cancel complete test_hci_layer_->GetCommand(); test_hci_layer_->IncomingEvent( RemoteNameRequestCancelCompleteBuilder::Create(1, ErrorCode::SUCCESS, address1)); test_hci_layer_->IncomingEvent(RemoteNameRequestCompleteBuilder::Create( ErrorCode::UNKNOWN_CONNECTION, address1, remote_name1)); // verify that the second request has now started auto command = test_hci_layer_->GetCommand(); auto discovery_command = DiscoveryCommandView::Create(command); ASSERT_TRUE(discovery_command.IsValid()); auto rnr_command = RemoteNameRequestView::Create(DiscoveryCommandView::Create(discovery_command)); ASSERT_TRUE(rnr_command.IsValid()); EXPECT_EQ(rnr_command.GetBdAddr(), address2); } TEST_F(RemoteNameRequestModuleTest, QueuingRemoteNameRequestsCancelFirstWithBuggyController) { auto promise1 = std::promise{}; auto future1 = promise1.get_future(); auto promise2 = std::promise>>{}; auto future2 = promise2.get_future(); // start a remote name request remote_name_request_module_->StartRemoteNameRequest( address1, RemoteNameRequestBuilder::Create( address1, PageScanRepetitionMode::R0, 3, ClockOffsetValid::INVALID), emptyCallback(), impossibleCallback(), promiseCallback>(std::move(promise1))); // enqueue a second one remote_name_request_module_->StartRemoteNameRequest( address2, RemoteNameRequestBuilder::Create( address2, PageScanRepetitionMode::R1, 4, ClockOffsetValid::VALID), emptyCallback(), impossibleCallback(), capturingPromiseCallback>(std::move(promise2))); // acknowledge that the first one has started test_hci_layer_->GetCommand(); test_hci_layer_->IncomingEvent(RemoteNameRequestStatusBuilder::Create(ErrorCode::SUCCESS, 1)); // cancel the first one remote_name_request_module_->CancelRemoteNameRequest(address1); // let the cancel complete test_hci_layer_->GetCommand(); test_hci_layer_->IncomingEvent( RemoteNameRequestCancelCompleteBuilder::Create(1, ErrorCode::SUCCESS, address1)); // send the INCORRECT response that we tolerate for interop reasons remote_name_request_module_->ReportRemoteNameRequestCancellation(address1); // verify that the second request has now started auto command = test_hci_layer_->GetCommand(); auto discovery_command = DiscoveryCommandView::Create(command); ASSERT_TRUE(discovery_command.IsValid()); auto rnr_command = RemoteNameRequestView::Create(DiscoveryCommandView::Create(discovery_command)); ASSERT_TRUE(rnr_command.IsValid()); EXPECT_EQ(rnr_command.GetBdAddr(), address2); } TEST_F(RemoteNameRequestModuleTest, FailToSendCommandThenSendNext) { auto promise = std::promise{}; auto future = promise.get_future(); // start a remote name request remote_name_request_module_->StartRemoteNameRequest( address1, RemoteNameRequestBuilder::Create( address1, PageScanRepetitionMode::R0, 3, ClockOffsetValid::INVALID), capturingPromiseCallback(std::move(promise)), impossibleCallback(), impossibleCallback>()); // on the command, return a failure HCI status test_hci_layer_->GetCommand(); test_hci_layer_->IncomingEvent( RemoteNameRequestStatusBuilder::Create(ErrorCode::STATUS_UNKNOWN, 1)); // start a second request remote_name_request_module_->StartRemoteNameRequest( address2, RemoteNameRequestBuilder::Create( address2, PageScanRepetitionMode::R1, 4, ClockOffsetValid::VALID), emptyCallback(), impossibleCallback(), impossibleCallback>()); // verify that it started auto command = test_hci_layer_->GetCommand(); auto discovery_command = DiscoveryCommandView::Create(command); ASSERT_TRUE(discovery_command.IsValid()); auto rnr_command = RemoteNameRequestView::Create(DiscoveryCommandView::Create(discovery_command)); ASSERT_TRUE(rnr_command.IsValid()); EXPECT_EQ(rnr_command.GetBdAddr(), address2); } TEST_F(RemoteNameRequestModuleTest, FailToSendCommandThenDequeueNext) { auto promise = std::promise{}; auto future = promise.get_future(); // start a remote name request remote_name_request_module_->StartRemoteNameRequest( address1, RemoteNameRequestBuilder::Create( address1, PageScanRepetitionMode::R0, 3, ClockOffsetValid::INVALID), emptyCallback(), impossibleCallback(), impossibleCallback>()); // enqueue a second one remote_name_request_module_->StartRemoteNameRequest( address2, RemoteNameRequestBuilder::Create( address2, PageScanRepetitionMode::R1, 4, ClockOffsetValid::VALID), impossibleCallback(), impossibleCallback(), impossibleCallback>()); // for the first, return a failure HCI status test_hci_layer_->GetCommand(); test_hci_layer_->IncomingEvent( RemoteNameRequestStatusBuilder::Create(ErrorCode::STATUS_UNKNOWN, 1)); // verify that the second one started auto command = test_hci_layer_->GetCommand(); auto discovery_command = DiscoveryCommandView::Create(command); ASSERT_TRUE(discovery_command.IsValid()); auto rnr_command = RemoteNameRequestView::Create(DiscoveryCommandView::Create(discovery_command)); ASSERT_TRUE(rnr_command.IsValid()); EXPECT_EQ(rnr_command.GetBdAddr(), address2); } TEST_F(RemoteNameRequestModuleTest, CancelJustWhenRNREventReturns) { auto promise = std::promise>>{}; auto future = promise.get_future(); // start a remote name request remote_name_request_module_->StartRemoteNameRequest( address1, RemoteNameRequestBuilder::Create( address1, PageScanRepetitionMode::R0, 3, ClockOffsetValid::INVALID), emptyCallback(), impossibleCallback(), capturingPromiseCallback>(std::move(promise))); // we successfully start test_hci_layer_->GetCommand(); auto promise2 = std::promise(); auto future2 = promise2.get_future(); client_handler_->Post(base::BindOnce( [](RemoteNameRequestModule* remote_name_request_module, HciLayerFake* test_hci_layer, std::promise promise2) { // but then the request is cancelled successfully (the status doesn't matter) remote_name_request_module->CancelRemoteNameRequest(address1); // Send an rnr event completed with page timeout status test_hci_layer->IncomingEvent( RemoteNameRequestStatusBuilder::Create(ErrorCode::PAGE_TIMEOUT, 1)); promise2.set_value(); }, remote_name_request_module_, test_hci_layer_, std::move(promise2))); future2.wait(); } } // namespace } // namespace hci } // namespace bluetooth