1 /*
2  * Copyright 2022 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "hci/acl_manager/acl_scheduler.h"
18 
19 #include <gmock/gmock.h>
20 #include <gtest/gtest.h>
21 
22 #include <chrono>
23 #include <future>
24 
25 #include "hci/address.h"
26 #include "os/thread.h"
27 
28 namespace bluetooth {
29 namespace hci {
30 namespace acl_manager {
31 namespace {
32 
33 const auto address1 = Address::FromString("A1:A2:A3:A4:A5:A6").value();
34 const auto address2 = Address::FromString("B1:B2:B3:B4:B5:B6").value();
35 const auto address3 = Address::FromString("C1:C2:C3:C4:C5:C6").value();
36 
37 const auto timeout = std::chrono::milliseconds(100);
38 
39 MATCHER(IsSet, "Future is set") {
40   if (arg.wait_for(timeout) != std::future_status::ready) {
41     return false;
42   }
43   const_cast<std::future<void>&>(arg).get();
44   return true;
45 }
46 
47 class AclSchedulerTest : public ::testing::Test {
48  protected:
SetUp()49   void SetUp() override {
50     fake_registry_.Start<AclScheduler>(&thread_);
51     ASSERT_TRUE(fake_registry_.IsStarted<AclScheduler>());
52 
53     client_handler_ = fake_registry_.GetTestModuleHandler(&AclScheduler::Factory);
54     ASSERT_NE(client_handler_, nullptr);
55 
56     acl_scheduler_ = static_cast<AclScheduler*>(fake_registry_.GetModuleUnderTest(&AclScheduler::Factory));
57 
58     ::testing::FLAGS_gtest_death_test_style = "threadsafe";
59   }
60 
TearDown()61   void TearDown() override {
62     fake_registry_.SynchronizeModuleHandler(&AclScheduler::Factory, timeout);
63     fake_registry_.StopAll();
64   }
65 
impossibleCallbackTakingString()66   common::ContextualOnceCallback<void(std::string)> impossibleCallbackTakingString() {
67     return client_handler_->BindOnce([](std::string /* _ */) { ADD_FAILURE(); });
68   }
69 
emptyCallbackTakingString()70   common::ContextualOnceCallback<void(std::string)> emptyCallbackTakingString() {
71     return client_handler_->BindOnce([](std::string /* _ */) {});
72   }
73 
promiseCallbackTakingString(std::promise<void> promise)74   common::ContextualOnceCallback<void(std::string)> promiseCallbackTakingString(std::promise<void> promise) {
75     return client_handler_->BindOnce(
76         [](std::promise<void> promise, std::string /* _ */) { promise.set_value(); },
77         std::move(promise));
78   }
79 
impossibleCallback()80   common::ContextualOnceCallback<void()> impossibleCallback() {
81     return client_handler_->BindOnce([] { ADD_FAILURE(); });
82   }
83 
emptyCallback()84   common::ContextualOnceCallback<void()> emptyCallback() {
85     return client_handler_->BindOnce([] {});
86   }
87 
promiseCallback(std::promise<void> promise)88   common::ContextualOnceCallback<void()> promiseCallback(std::promise<void> promise) {
89     return client_handler_->BindOnce([](std::promise<void> promise) { promise.set_value(); }, std::move(promise));
90   }
91 
92   TestModuleRegistry fake_registry_;
93   os::Thread& thread_ = fake_registry_.GetTestThread();
94   AclScheduler* acl_scheduler_ = nullptr;
95   os::Handler* client_handler_ = nullptr;
96 };
97 
TEST_F(AclSchedulerTest,SingleConnectionImmediatelyExecuted)98 TEST_F(AclSchedulerTest, SingleConnectionImmediatelyExecuted) {
99   auto promise = std::promise<void>{};
100   auto future = promise.get_future();
101 
102   // start connection, which should immediately execute
103   acl_scheduler_->EnqueueOutgoingAclConnection(address1, promiseCallback(std::move(promise)));
104 
105   // it has started
106   EXPECT_THAT(future, IsSet());
107 }
108 
TEST_F(AclSchedulerTest,ThreeConnectionsQueue)109 TEST_F(AclSchedulerTest, ThreeConnectionsQueue) {
110   auto promise1 = std::promise<void>{};
111   auto future1 = promise1.get_future();
112   auto promise2 = std::promise<void>{};
113   auto future2 = promise2.get_future();
114 
115   // start first connection, which immediately runs
116   acl_scheduler_->EnqueueOutgoingAclConnection(address1, emptyCallback());
117   // start second connection
118   acl_scheduler_->EnqueueOutgoingAclConnection(address2, (promiseCallback(std::move(promise1))));
119   // start third connection
120   acl_scheduler_->EnqueueOutgoingAclConnection(address3, (promiseCallback(std::move(promise2))));
121 
122   // the second and third connections are currently queued
123   EXPECT_THAT(future1.wait_for(timeout), std::future_status::timeout);
124 
125   // first connection fails, so next one should start
126   acl_scheduler_->ReportOutgoingAclConnectionFailure();
127 
128   // the second connection has started, the third one is queued
129   EXPECT_THAT(future1, IsSet());
130   EXPECT_THAT(future2.wait_for(timeout), std::future_status::timeout);
131 
132   // second connection fails, so third one should start
133   acl_scheduler_->ReportOutgoingAclConnectionFailure();
134 
135   // the third connection has started
136   EXPECT_THAT(future2, IsSet());
137 }
138 
TEST_F(AclSchedulerTest,SingleConnectionCompletionCallback)139 TEST_F(AclSchedulerTest, SingleConnectionCompletionCallback) {
140   auto promise = std::promise<void>{};
141   auto future = promise.get_future();
142 
143   // start connection, which immediately runs
144   acl_scheduler_->EnqueueOutgoingAclConnection(address1, emptyCallback());
145 
146   // the outgoing connection completes
147   acl_scheduler_->ReportAclConnectionCompletion(
148       address1, promiseCallback(std::move(promise)), impossibleCallback(), impossibleCallbackTakingString());
149 
150   // the outgoing_connection callback should have executed
151   EXPECT_THAT(future, IsSet());
152 }
153 
TEST_F(AclSchedulerTest,SingleConnectionCompletionDequeueNext)154 TEST_F(AclSchedulerTest, SingleConnectionCompletionDequeueNext) {
155   auto promise = std::promise<void>{};
156   auto future = promise.get_future();
157 
158   // start connection, which immediately runs
159   acl_scheduler_->EnqueueOutgoingAclConnection(address1, emptyCallback());
160   // start second connection which should queue
161   acl_scheduler_->EnqueueOutgoingAclConnection(address2, promiseCallback(std::move(promise)));
162 
163   // complete the first connection
164   acl_scheduler_->ReportAclConnectionCompletion(
165       address1, emptyCallback(), impossibleCallback(), impossibleCallbackTakingString());
166 
167   // the next connection should dequeue now
168   EXPECT_THAT(future, IsSet());
169 }
170 
TEST_F(AclSchedulerTest,IncomingConnectionCallback)171 TEST_F(AclSchedulerTest, IncomingConnectionCallback) {
172   auto promise = std::promise<void>{};
173   auto future = promise.get_future();
174 
175   // an incoming connection arrives
176   acl_scheduler_->RegisterPendingIncomingConnection(address1);
177 
178   // and completes
179   acl_scheduler_->ReportAclConnectionCompletion(
180       address1, impossibleCallback(), promiseCallback(std::move(promise)), impossibleCallbackTakingString());
181 
182   // the incoming_connection callback should have executed
183   EXPECT_THAT(future, IsSet());
184 }
185 
TEST_F(AclSchedulerTest,UnknownConnectionCallback)186 TEST_F(AclSchedulerTest, UnknownConnectionCallback) {
187   auto promise = std::promise<void>{};
188   auto future = promise.get_future();
189 
190   // start outgoing connection
191   acl_scheduler_->EnqueueOutgoingAclConnection(address1, emptyCallback());
192 
193   // an incoming connection arrives
194   acl_scheduler_->RegisterPendingIncomingConnection(address2);
195 
196   // then an unknown connection completes
197   acl_scheduler_->ReportAclConnectionCompletion(
198       address3, impossibleCallback(), impossibleCallback(), (promiseCallbackTakingString(std::move(promise))));
199 
200   // the unknown_connection callback should have executed
201   EXPECT_THAT(future, IsSet());
202 }
203 
TEST_F(AclSchedulerTest,TiebreakForOutgoingConnection)204 TEST_F(AclSchedulerTest, TiebreakForOutgoingConnection) {
205   auto promise = std::promise<void>{};
206   auto future = promise.get_future();
207 
208   // start outgoing connection
209   acl_scheduler_->EnqueueOutgoingAclConnection(address1, emptyCallback());
210 
211   // an incoming connection arrives *from the same address*
212   acl_scheduler_->RegisterPendingIncomingConnection(address1);
213 
214   // then the connection to that address completes
215   acl_scheduler_->ReportAclConnectionCompletion(
216       address1, promiseCallback(std::move(promise)), impossibleCallback(), impossibleCallbackTakingString());
217 
218   // the outgoing_connection callback should have executed, NOT the incoming_connection one
219   // this preserves working behavior, it is not based on any principled decision (so if you need to break this test,
220   // go for it)
221   EXPECT_THAT(future, IsSet());
222 }
223 
TEST_F(AclSchedulerTest,QueueWhileIncomingConnectionsPending)224 TEST_F(AclSchedulerTest, QueueWhileIncomingConnectionsPending) {
225   auto promise = std::promise<void>{};
226   auto future = promise.get_future();
227 
228   // start outgoing connection
229   acl_scheduler_->EnqueueOutgoingAclConnection(address1, emptyCallback());
230   // queue a second outgoing connection
231   acl_scheduler_->EnqueueOutgoingAclConnection(address2, promiseCallback(std::move(promise)));
232 
233   // an incoming connection arrives
234   acl_scheduler_->RegisterPendingIncomingConnection(address3);
235 
236   // then the first outgoing connection completes
237   acl_scheduler_->ReportAclConnectionCompletion(
238       address1, emptyCallback(), impossibleCallback(), impossibleCallbackTakingString());
239 
240   // the outgoing_connection callback should not have executed yet
241   EXPECT_THAT(future.wait_for(timeout), std::future_status::timeout);
242 
243   // now the incoming connection completes
244   acl_scheduler_->ReportAclConnectionCompletion(
245       address3, impossibleCallback(), emptyCallback(), impossibleCallbackTakingString());
246 
247   // only now does the next outgoing connection start
248   EXPECT_THAT(future, IsSet());
249 }
250 
TEST_F(AclSchedulerTest,DoNothingWhileIncomingConnectionsExist)251 TEST_F(AclSchedulerTest, DoNothingWhileIncomingConnectionsExist) {
252   auto promise = std::promise<void>{};
253   auto future = promise.get_future();
254 
255   // an incoming connection arrives
256   acl_scheduler_->RegisterPendingIncomingConnection(address1);
257 
258   // try to start an outgoing connection
259   acl_scheduler_->EnqueueOutgoingAclConnection(address2, promiseCallback(std::move(promise)));
260 
261   // the outgoing_connection callback should not have executed yet
262   EXPECT_THAT(future.wait_for(timeout), std::future_status::timeout);
263 
264   // a second incoming connection arrives
265   acl_scheduler_->RegisterPendingIncomingConnection(address3);
266 
267   // the first incoming connection completes
268   acl_scheduler_->ReportAclConnectionCompletion(
269       address1, impossibleCallback(), emptyCallback(), impossibleCallbackTakingString());
270 
271   // the outgoing_connection callback should *still* not have executed yet
272   EXPECT_THAT(future.wait_for(timeout), std::future_status::timeout);
273 
274   // the second incoming connection completes, so none are left
275   acl_scheduler_->ReportAclConnectionCompletion(
276       address3, impossibleCallback(), emptyCallback(), impossibleCallbackTakingString());
277 
278   // only now does the outgoing connection start
279   EXPECT_THAT(future, IsSet());
280 }
281 
TEST_F(AclSchedulerTest,CancelOutgoingConnection)282 TEST_F(AclSchedulerTest, CancelOutgoingConnection) {
283   auto promise = std::promise<void>{};
284   auto future = promise.get_future();
285 
286   // start an outgoing connection
287   acl_scheduler_->EnqueueOutgoingAclConnection(address1, emptyCallback());
288   // enqueue a second connection
289   acl_scheduler_->EnqueueOutgoingAclConnection(address2, promiseCallback(std::move(promise)));
290 
291   // cancel the outgoing connection
292   acl_scheduler_->CancelAclConnection(address1, emptyCallback(), impossibleCallback());
293 
294   // we expect the second connection to stay queued until the cancel completes
295   EXPECT_THAT(future.wait_for(timeout), std::future_status::timeout);
296 
297   // now the cancel completes (with a failed status, in reality, but the scheduler doesn't care)
298   acl_scheduler_->ReportAclConnectionCompletion(
299       address1, emptyCallback(), impossibleCallback(), impossibleCallbackTakingString());
300 
301   // so only now do we advance the queue
302   EXPECT_THAT(future, IsSet());
303 }
304 
TEST_F(AclSchedulerTest,CancelOutgoingConnectionCallback)305 TEST_F(AclSchedulerTest, CancelOutgoingConnectionCallback) {
306   auto promise = std::promise<void>{};
307   auto future = promise.get_future();
308 
309   // start an outgoing connection
310   acl_scheduler_->EnqueueOutgoingAclConnection(address1, emptyCallback());
311 
312   // cancel the outgoing connection
313   acl_scheduler_->CancelAclConnection(address1, promiseCallback(std::move(promise)), impossibleCallback());
314 
315   // we expect the cancel_connection callback to be invoked since we are cancelling an actually active connection
316   EXPECT_THAT(future, IsSet());
317 }
318 
TEST_F(AclSchedulerTest,CancelQueuedConnectionRemoveFromQueue)319 TEST_F(AclSchedulerTest, CancelQueuedConnectionRemoveFromQueue) {
320   auto promise = std::promise<void>{};
321   auto future = promise.get_future();
322 
323   // start an outgoing connection
324   acl_scheduler_->EnqueueOutgoingAclConnection(address1, emptyCallback());
325   // start another connection that will queue
326   acl_scheduler_->EnqueueOutgoingAclConnection(address2, impossibleCallback());
327   // start a third connection that will queue
328   acl_scheduler_->EnqueueOutgoingAclConnection(address3, promiseCallback(std::move(promise)));
329 
330   // cancel the first queued connection
331   acl_scheduler_->CancelAclConnection(address2, impossibleCallback(), emptyCallback());
332 
333   // the second queued connection should remain enqueued, since another connection is in progress
334   EXPECT_THAT(future.wait_for(timeout), std::future_status::timeout);
335 
336   // complete the outgoing connection
337   acl_scheduler_->ReportOutgoingAclConnectionFailure();
338 
339   // only now can we dequeue the second queued connection
340   EXPECT_THAT(future, IsSet());
341 }
342 
TEST_F(AclSchedulerTest,CancelQueuedConnectionCallback)343 TEST_F(AclSchedulerTest, CancelQueuedConnectionCallback) {
344   auto promise = std::promise<void>{};
345   auto future = promise.get_future();
346 
347   // start an outgoing connection
348   acl_scheduler_->EnqueueOutgoingAclConnection(address1, emptyCallback());
349   // start another connection that will queue
350   acl_scheduler_->EnqueueOutgoingAclConnection(address2, emptyCallback());
351 
352   // cancel the queued connection
353   acl_scheduler_->CancelAclConnection(address2, impossibleCallback(), promiseCallback(std::move(promise)));
354 
355   // we expect the cancel_connection_completed callback to be invoked since we are cancelling a connection in the queue
356   EXPECT_THAT(future, IsSet());
357 }
358 
TEST_F(AclSchedulerTest,RemoteNameRequestImmediatelyExecuted)359 TEST_F(AclSchedulerTest, RemoteNameRequestImmediatelyExecuted) {
360   auto promise = std::promise<void>{};
361   auto future = promise.get_future();
362 
363   // start an outgoing request
364   acl_scheduler_->EnqueueRemoteNameRequest(address1, promiseCallback(std::move(promise)), emptyCallback());
365 
366   // we expect the start callback to be invoked immediately
367   EXPECT_THAT(future, IsSet());
368 }
369 
TEST_F(AclSchedulerTest,RemoteNameRequestQueuing)370 TEST_F(AclSchedulerTest, RemoteNameRequestQueuing) {
371   auto promise = std::promise<void>{};
372   auto future = promise.get_future();
373 
374   // start an outgoing request
375   acl_scheduler_->EnqueueRemoteNameRequest(address1, emptyCallback(), impossibleCallback());
376   // enqueue a second one
377   acl_scheduler_->EnqueueRemoteNameRequest(address2, promiseCallback(std::move(promise)), impossibleCallback());
378 
379   // we should still be queued
380   EXPECT_THAT(future.wait_for(timeout), std::future_status::timeout);
381 
382   // the first request completes
383   acl_scheduler_->ReportRemoteNameRequestCompletion(address1);
384 
385   // so the second request should now have started
386   EXPECT_THAT(future, IsSet());
387 }
388 
TEST_F(AclSchedulerTest,RemoteNameRequestCancellationCallback)389 TEST_F(AclSchedulerTest, RemoteNameRequestCancellationCallback) {
390   auto promise = std::promise<void>{};
391   auto future = promise.get_future();
392 
393   // start an outgoing request
394   acl_scheduler_->EnqueueRemoteNameRequest(address1, emptyCallback(), impossibleCallback());
395 
396   // cancel it
397   acl_scheduler_->CancelRemoteNameRequest(address1, promiseCallback(std::move(promise)));
398 
399   // the cancel callback should be invoked
400   EXPECT_THAT(future, IsSet());
401 }
402 
TEST_F(AclSchedulerTest,RemoteNameRequestCancellationWhileQueuedCallback)403 TEST_F(AclSchedulerTest, RemoteNameRequestCancellationWhileQueuedCallback) {
404   auto promise = std::promise<void>{};
405   auto future = promise.get_future();
406 
407   // start an outgoing request
408   acl_scheduler_->EnqueueRemoteNameRequest(address1, emptyCallback(), impossibleCallback());
409   // enqueue a second one
410   acl_scheduler_->EnqueueRemoteNameRequest(address2, impossibleCallback(), promiseCallback(std::move(promise)));
411 
412   // cancel the second one
413   acl_scheduler_->CancelRemoteNameRequest(address2, impossibleCallback());
414 
415   // the cancel_request_completed calback should be invoked
416   EXPECT_THAT(future, IsSet());
417 
418   // the first request completes
419   acl_scheduler_->ReportRemoteNameRequestCompletion(address1);
420 
421   // we don't dequeue the second one, since it was cancelled
422   // implicitly assert that its callback was never invoked
423 }
424 
TEST_F(AclSchedulerTest,CancelQueuedRemoteNameRequestRemoveFromQueue)425 TEST_F(AclSchedulerTest, CancelQueuedRemoteNameRequestRemoveFromQueue) {
426   auto promise = std::promise<void>{};
427   auto future = promise.get_future();
428 
429   // start an outgoing connection
430   acl_scheduler_->EnqueueOutgoingAclConnection(address1, emptyCallback());
431   // start another connection that will queue
432   acl_scheduler_->EnqueueRemoteNameRequest(address2, impossibleCallback(), emptyCallback());
433   // start a third connection that will queue
434   acl_scheduler_->EnqueueRemoteNameRequest(address3, promiseCallback(std::move(promise)), impossibleCallback());
435 
436   // cancel the first queued connection
437   acl_scheduler_->CancelRemoteNameRequest(address2, impossibleCallback());
438 
439   // the second queued connection should remain enqueued, since another connection is in progress
440   EXPECT_THAT(future.wait_for(timeout), std::future_status::timeout);
441 
442   // complete the outgoing connection
443   acl_scheduler_->ReportOutgoingAclConnectionFailure();
444 
445   // only now can we dequeue the second queued connection
446   EXPECT_THAT(future, IsSet());
447 }
448 
TEST_F(AclSchedulerTest,RemoteNameRequestCancellationShouldDequeueNext)449 TEST_F(AclSchedulerTest, RemoteNameRequestCancellationShouldDequeueNext) {
450   auto promise = std::promise<void>{};
451   auto future = promise.get_future();
452 
453   // start an outgoing request
454   acl_scheduler_->EnqueueRemoteNameRequest(address1, emptyCallback(), impossibleCallback());
455   // enqueue a second one
456   acl_scheduler_->EnqueueRemoteNameRequest(address2, promiseCallback(std::move(promise)), impossibleCallback());
457 
458   // we should still be queued
459   EXPECT_THAT(future.wait_for(timeout), std::future_status::timeout);
460 
461   // the first request is cancelled
462   acl_scheduler_->CancelRemoteNameRequest(address1, emptyCallback());
463 
464   // we should still remain queued while we wait for the cancel to complete
465   EXPECT_THAT(future.wait_for(timeout), std::future_status::timeout);
466 
467   // the cancel completes
468   acl_scheduler_->ReportRemoteNameRequestCompletion(address1);
469 
470   // so the second request should now have started
471   EXPECT_THAT(future, IsSet());
472 }
473 
474 }  // namespace
475 }  // namespace acl_manager
476 }  // namespace hci
477 }  // namespace bluetooth
478