1 /*
2  * Copyright 2020 HIMSA II K/S - www.himsa.dk.
3  * Represented by EHIMA - www.ehima.com
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  *      http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17 
18 #include <bluetooth/log.h>
19 #include <gmock/gmock.h>
20 #include <gtest/gtest.h>
21 
22 #include <vector>
23 
24 #include "bind_helpers.h"
25 #include "hci/controller_interface_mock.h"
26 #include "l2c_api.h"
27 #include "mock_btif_storage.h"
28 #include "mock_btm_api_layer.h"
29 #include "mock_eatt.h"
30 #include "mock_gatt_layer.h"
31 #include "mock_l2cap_layer.h"
32 #include "stack/include/bt_hdr.h"
33 #include "stack/include/bt_psm_types.h"
34 #include "stack/include/l2cdefs.h"
35 #include "test/mock/mock_main_shim_entry.h"
36 #include "types/raw_address.h"
37 
38 using testing::_;
39 using testing::DoAll;
40 using testing::MockFunction;
41 using testing::NiceMock;
42 using testing::NotNull;
43 using testing::Return;
44 using testing::SaveArg;
45 using testing::SaveArgPointee;
46 using testing::StrictMock;
47 
48 using bluetooth::eatt::EattChannel;
49 using bluetooth::eatt::EattChannelState;
50 using namespace bluetooth;
51 
52 #define BLE_GATT_SVR_SUP_FEAT_EATT_BITMASK 0x01
53 
54 /* Needed for testing context */
55 static tGATT_TCB test_tcb;
btif_storage_add_eatt_supported(const RawAddress & addr)56 void btif_storage_add_eatt_supported(const RawAddress& addr) { return; }
gatt_consolidate(const RawAddress & identity_addr,const RawAddress & rpa)57 void gatt_consolidate(const RawAddress& identity_addr, const RawAddress& rpa) {}
gatt_data_process(tGATT_TCB & tcb,uint16_t cid,BT_HDR * p_buf)58 void gatt_data_process(tGATT_TCB& tcb, uint16_t cid, BT_HDR* p_buf) { return; }
gatt_find_tcb_by_addr(const RawAddress & bda,tBT_TRANSPORT transport)59 tGATT_TCB* gatt_find_tcb_by_addr(const RawAddress& bda,
60                                  tBT_TRANSPORT transport) {
61   log::info("");
62   return &test_tcb;
63 }
64 
65 namespace {
66 const RawAddress test_address({0x11, 0x11, 0x11, 0x11, 0x11, 0x11});
67 
68 class EattTest : public testing::Test {
69  protected:
ConnectDeviceEattSupported(int num_of_accepted_connections,bool collision=false)70   void ConnectDeviceEattSupported(int num_of_accepted_connections,
71                                   bool collision = false) {
72     ON_CALL(gatt_interface_, ClientReadSupportedFeatures)
73         .WillByDefault(
74             [](const RawAddress& addr,
75                base::OnceCallback<void(const RawAddress&, uint8_t)> cb) {
76               std::move(cb).Run(addr, BLE_GATT_SVR_SUP_FEAT_EATT_BITMASK);
77               return true;
78             });
79     ON_CALL(gatt_interface_, GetEattSupport)
80         .WillByDefault([](const RawAddress& addr) { return true; });
81 
82     std::vector<uint16_t> test_local_cids{61, 62, 63, 64, 65};
83     EXPECT_CALL(l2cap_interface_,
84                 ConnectCreditBasedReq(BT_PSM_EATT, test_address, _))
85         .WillOnce(Return(test_local_cids));
86 
87     eatt_instance_->Connect(test_address);
88 
89     if (collision) {
90       /* Collision should be handled only if all channels has been rejected in
91        * first place.*/
92       if (num_of_accepted_connections == 0) {
93         EXPECT_CALL(l2cap_interface_,
94                     ConnectCreditBasedReq(BT_PSM_EATT, test_address, _))
95             .Times(1);
96       }
97 
98       l2cap_app_info_.pL2CA_CreditBasedCollisionInd_Cb(test_address);
99     }
100 
101     int i = 0;
102     for (uint16_t cid : test_local_cids) {
103       EattChannel* channel =
104           eatt_instance_->FindEattChannelByCid(test_address, cid);
105       ASSERT_TRUE(channel != nullptr);
106       ASSERT_TRUE(channel->state_ == EattChannelState::EATT_CHANNEL_PENDING);
107 
108       if (i < num_of_accepted_connections) {
109         l2cap_app_info_.pL2CA_CreditBasedConnectCfm_Cb(
110             test_address, cid, EATT_MIN_MTU_MPS, L2CAP_CONN_OK);
111         connected_cids_.push_back(cid);
112 
113         ASSERT_TRUE(channel->state_ == EattChannelState::EATT_CHANNEL_OPENED);
114         ASSERT_TRUE(channel->tx_mtu_ == EATT_MIN_MTU_MPS);
115       } else {
116         l2cap_app_info_.pL2CA_Error_Cb(cid, L2CAP_CONN_NO_RESOURCES);
117 
118         EattChannel* channel =
119             eatt_instance_->FindEattChannelByCid(test_address, cid);
120         ASSERT_TRUE(channel == nullptr);
121       }
122       i++;
123     }
124 
125     ASSERT_TRUE(test_tcb.eatt == num_of_accepted_connections);
126   }
127 
ConnectDeviceBothSides(int num_of_accepted_connections,std::vector<uint16_t> & incoming_cids)128   void ConnectDeviceBothSides(int num_of_accepted_connections,
129                               std::vector<uint16_t>& incoming_cids) {
130     base::OnceCallback<void(const RawAddress&, uint8_t)> eatt_supp_feat_cb;
131 
132     ON_CALL(gatt_interface_, ClientReadSupportedFeatures)
133         .WillByDefault(
134             [&eatt_supp_feat_cb](
135                 const RawAddress& addr,
136                 base::OnceCallback<void(const RawAddress&, uint8_t)> cb) {
137               eatt_supp_feat_cb = std::move(cb);
138               return true;
139             });
140 
141     // Return false to trigger supported features request
142     ON_CALL(gatt_interface_, GetEattSupport)
143         .WillByDefault([](const RawAddress& addr) { return false; });
144 
145     std::vector<uint16_t> test_local_cids{61, 62, 63, 64, 65};
146     EXPECT_CALL(l2cap_interface_,
147                 ConnectCreditBasedReq(BT_PSM_EATT, test_address, _))
148         .WillOnce(Return(test_local_cids));
149 
150     eatt_instance_->Connect(test_address);
151 
152     // Let the remote connect while we are trying to connect
153     EXPECT_CALL(
154         l2cap_interface_,
155         ConnectCreditBasedRsp(test_address, 1, incoming_cids, L2CAP_CONN_OK, _))
156         .WillOnce(Return(true));
157     l2cap_app_info_.pL2CA_CreditBasedConnectInd_Cb(
158         test_address, incoming_cids, BT_PSM_EATT, EATT_MIN_MTU_MPS, 1);
159 
160     // Respond to feature request scheduled by the connect request
161     ASSERT_TRUE(eatt_supp_feat_cb);
162     if (eatt_supp_feat_cb) {
163       std::move(eatt_supp_feat_cb)
164           .Run(test_address, BLE_GATT_SVR_SUP_FEAT_EATT_BITMASK);
165     }
166 
167     int i = 0;
168     for (uint16_t cid : test_local_cids) {
169       EattChannel* channel =
170           eatt_instance_->FindEattChannelByCid(test_address, cid);
171       ASSERT_TRUE(channel != nullptr);
172       ASSERT_TRUE(channel->state_ == EattChannelState::EATT_CHANNEL_PENDING);
173 
174       if (i < num_of_accepted_connections) {
175         l2cap_app_info_.pL2CA_CreditBasedConnectCfm_Cb(
176             test_address, cid, EATT_MIN_MTU_MPS, L2CAP_CONN_OK);
177         connected_cids_.push_back(cid);
178 
179         ASSERT_TRUE(channel->state_ == EattChannelState::EATT_CHANNEL_OPENED);
180         ASSERT_TRUE(channel->tx_mtu_ == EATT_MIN_MTU_MPS);
181       } else {
182         l2cap_app_info_.pL2CA_Error_Cb(cid, L2CAP_CONN_NO_RESOURCES);
183 
184         EattChannel* channel =
185             eatt_instance_->FindEattChannelByCid(test_address, cid);
186         ASSERT_TRUE(channel == nullptr);
187       }
188       i++;
189     }
190 
191     // Check the incoming CIDs as well
192     for (auto cid : incoming_cids) {
193       EattChannel* channel =
194           eatt_instance_->FindEattChannelByCid(test_address, cid);
195       ASSERT_NE(nullptr, channel);
196       ASSERT_EQ(channel->state_, EattChannelState::EATT_CHANNEL_OPENED);
197       ASSERT_TRUE(channel->tx_mtu_ == EATT_MIN_MTU_MPS);
198     }
199 
200     ASSERT_EQ(test_tcb.eatt,
201               num_of_accepted_connections + incoming_cids.size());
202   }
203 
DisconnectEattByPeer(void)204   void DisconnectEattByPeer(void) {
205     for (uint16_t cid : connected_cids_)
206       l2cap_app_info_.pL2CA_DisconnectInd_Cb(cid, true);
207     ASSERT_TRUE(test_tcb.eatt == 0);
208   }
209 
DisconnectEattDevice(std::vector<uint16_t> cids)210   void DisconnectEattDevice(std::vector<uint16_t> cids) {
211     EXPECT_CALL(l2cap_interface_, DisconnectRequest(_)).Times(cids.size());
212     eatt_instance_->Disconnect(test_address);
213 
214     ASSERT_TRUE(test_tcb.eatt == 0);
215   }
216 
SetUp()217   void SetUp() override {
218     le_buffer_size_.le_data_packet_length_ = 128;
219     le_buffer_size_.total_num_le_packets_ = 24;
220     ON_CALL(controller_, GetLeBufferSize)
221         .WillByDefault(Return(le_buffer_size_));
222     bluetooth::l2cap::SetMockInterface(&l2cap_interface_);
223     bluetooth::manager::SetMockBtmApiInterface(&btm_api_interface_);
224     bluetooth::manager::SetMockBtifStorageInterface(&btif_storage_interface_);
225     bluetooth::gatt::SetMockGattInterface(&gatt_interface_);
226     bluetooth::hci::testing::mock_controller_ = &controller_;
227 
228     // Clear the static memory for each test case
229     memset(&test_tcb, 0, sizeof(test_tcb));
230 
231     EXPECT_CALL(l2cap_interface_, RegisterLECoc(BT_PSM_EATT, _, _))
232         .WillOnce(DoAll(SaveArg<1>(&l2cap_app_info_), Return(BT_PSM_EATT)));
233 
234     ON_CALL(btif_storage_interface_, LoadBondedEatt).WillByDefault([]() {
235       return;
236     });
237 
238     hci_role_ = HCI_ROLE_CENTRAL;
239 
240     ON_CALL(l2cap_interface_, GetBleConnRole(_))
241         .WillByDefault(DoAll(Return(hci_role_)));
242 
243     eatt_instance_ = EattExtension::GetInstance();
244     eatt_instance_->Start();
245 
246     Test::SetUp();
247   }
248 
TearDown()249   void TearDown() override {
250     EXPECT_CALL(l2cap_interface_, DeregisterLECoc(BT_PSM_EATT)).Times(1);
251 
252     eatt_instance_->Stop();
253     eatt_instance_ = nullptr;
254     hci_role_ = 0;
255     connected_cids_.clear();
256 
257     bluetooth::gatt::SetMockGattInterface(nullptr);
258     bluetooth::l2cap::SetMockInterface(nullptr);
259     bluetooth::manager::SetMockBtifStorageInterface(nullptr);
260     bluetooth::manager::SetMockBtmApiInterface(nullptr);
261     bluetooth::hci::testing::mock_controller_ = nullptr;
262 
263     Test::TearDown();
264   }
265 
266   bluetooth::manager::MockBtifStorageInterface btif_storage_interface_;
267   bluetooth::manager::MockBtmApiInterface btm_api_interface_;
268   bluetooth::l2cap::MockL2capInterface l2cap_interface_;
269   bluetooth::gatt::MockGattInterface gatt_interface_;
270   bluetooth::hci::testing::MockControllerInterface controller_;
271   bluetooth::hci::LeBufferSize le_buffer_size_;
272 
273   tL2CAP_APPL_INFO l2cap_app_info_;
274   EattExtension* eatt_instance_;
275   std::vector<uint16_t> connected_cids_;
276   uint8_t hci_role_ = HCI_ROLE_CENTRAL;
277 };
278 
TEST_F(EattTest,ConnectSucceed)279 TEST_F(EattTest, ConnectSucceed) {
280   ConnectDeviceEattSupported(1);
281   DisconnectEattDevice(connected_cids_);
282 }
283 
TEST_F(EattTest,IncomingEattConnectionByUnknownDevice)284 TEST_F(EattTest, IncomingEattConnectionByUnknownDevice) {
285   std::vector<uint16_t> incoming_cids{71, 72, 73, 74, 75};
286 
287   ON_CALL(btm_api_interface_, IsEncrypted)
288       .WillByDefault(
289           [](const RawAddress& addr, tBT_TRANSPORT transport) { return true; });
290   EXPECT_CALL(
291       l2cap_interface_,
292       ConnectCreditBasedRsp(test_address, 1, incoming_cids, L2CAP_CONN_OK, _))
293       .WillOnce(Return(true));
294 
295   l2cap_app_info_.pL2CA_CreditBasedConnectInd_Cb(
296       test_address, incoming_cids, BT_PSM_EATT, EATT_MIN_MTU_MPS, 1);
297 
298   DisconnectEattDevice(incoming_cids);
299 }
300 
TEST_F(EattTest,IncomingEattConnectionByKnownDevice)301 TEST_F(EattTest, IncomingEattConnectionByKnownDevice) {
302   hci_role_ = HCI_ROLE_PERIPHERAL;
303   ON_CALL(btm_api_interface_, IsEncrypted)
304       .WillByDefault(
305           [](const RawAddress& addr, tBT_TRANSPORT transport) { return true; });
306   ON_CALL(gatt_interface_, ClientReadSupportedFeatures)
307       .WillByDefault(
308           [](const RawAddress& addr,
309              base::OnceCallback<void(const RawAddress&, uint8_t)> cb) {
310             std::move(cb).Run(addr, BLE_GATT_SVR_SUP_FEAT_EATT_BITMASK);
311             return true;
312           });
313   ON_CALL(gatt_interface_, GetEattSupport)
314       .WillByDefault([](const RawAddress& addr) { return true; });
315 
316   eatt_instance_->Connect(test_address);
317   std::vector<uint16_t> incoming_cids{71, 72, 73, 74, 75};
318 
319   EXPECT_CALL(
320       l2cap_interface_,
321       ConnectCreditBasedRsp(test_address, 1, incoming_cids, L2CAP_CONN_OK, _))
322       .WillOnce(Return(true));
323 
324   l2cap_app_info_.pL2CA_CreditBasedConnectInd_Cb(
325       test_address, incoming_cids, BT_PSM_EATT, EATT_MIN_MTU_MPS, 1);
326 
327   DisconnectEattDevice(incoming_cids);
328 
329   hci_role_ = HCI_ROLE_CENTRAL;
330 }
331 
TEST_F(EattTest,IncomingEattConnectionByKnownDeviceEncryptionOff)332 TEST_F(EattTest, IncomingEattConnectionByKnownDeviceEncryptionOff) {
333   hci_role_ = HCI_ROLE_PERIPHERAL;
334   ON_CALL(btm_api_interface_, IsEncrypted)
335       .WillByDefault([](const RawAddress& addr, tBT_TRANSPORT transport) {
336         return false;
337       });
338   ON_CALL(btm_api_interface_, IsLinkKeyKnown)
339       .WillByDefault(
340           [](const RawAddress& addr, tBT_TRANSPORT transport) { return true; });
341   ON_CALL(gatt_interface_, ClientReadSupportedFeatures)
342       .WillByDefault(
343           [](const RawAddress& addr,
344              base::OnceCallback<void(const RawAddress&, uint8_t)> cb) {
345             std::move(cb).Run(addr, BLE_GATT_SVR_SUP_FEAT_EATT_BITMASK);
346             return true;
347           });
348   ON_CALL(gatt_interface_, GetEattSupport)
349       .WillByDefault([](const RawAddress& addr) { return true; });
350 
351   eatt_instance_->Connect(test_address);
352   std::vector<uint16_t> incoming_cids{71, 72, 73, 74, 75};
353 
354   EXPECT_CALL(l2cap_interface_,
355               ConnectCreditBasedRsp(test_address, 1, _,
356                                     L2CAP_LE_RESULT_INSUFFICIENT_ENCRYP, _))
357       .WillOnce(Return(true));
358 
359   l2cap_app_info_.pL2CA_CreditBasedConnectInd_Cb(
360       test_address, incoming_cids, BT_PSM_EATT, EATT_MIN_MTU_MPS, 1);
361 
362   hci_role_ = HCI_ROLE_CENTRAL;
363 }
364 
TEST_F(EattTest,IncomingEattConnectionByUnknownDeviceEncryptionOff)365 TEST_F(EattTest, IncomingEattConnectionByUnknownDeviceEncryptionOff) {
366   std::vector<uint16_t> incoming_cids{71, 72, 73, 74, 75};
367 
368   ON_CALL(btm_api_interface_, IsEncrypted)
369       .WillByDefault([](const RawAddress& addr, tBT_TRANSPORT transport) {
370         return false;
371       });
372   ON_CALL(btm_api_interface_, IsLinkKeyKnown)
373       .WillByDefault([](const RawAddress& addr, tBT_TRANSPORT transport) {
374         return false;
375       });
376   EXPECT_CALL(
377       l2cap_interface_,
378       ConnectCreditBasedRsp(test_address, 1, _,
379                             L2CAP_LE_RESULT_INSUFFICIENT_AUTHENTICATION, _))
380       .WillOnce(Return(true));
381 
382   l2cap_app_info_.pL2CA_CreditBasedConnectInd_Cb(
383       test_address, incoming_cids, BT_PSM_EATT, EATT_MIN_MTU_MPS, 1);
384 }
385 
TEST_F(EattTest,ReconnectInitiatedByRemoteSucceed)386 TEST_F(EattTest, ReconnectInitiatedByRemoteSucceed) {
387   ConnectDeviceEattSupported(1);
388   DisconnectEattDevice(connected_cids_);
389   std::vector<uint16_t> incoming_cids{71, 72, 73, 74, 75};
390 
391   ON_CALL(btm_api_interface_, IsEncrypted)
392       .WillByDefault(
393           [](const RawAddress& addr, tBT_TRANSPORT transport) { return true; });
394 
395   EXPECT_CALL(
396       l2cap_interface_,
397       ConnectCreditBasedRsp(test_address, 1, incoming_cids, L2CAP_CONN_OK, _))
398       .WillOnce(Return(true));
399 
400   l2cap_app_info_.pL2CA_CreditBasedConnectInd_Cb(
401       test_address, incoming_cids, BT_PSM_EATT, EATT_MIN_MTU_MPS, 1);
402 
403   DisconnectEattDevice(incoming_cids);
404 }
405 
TEST_F(EattTest,ConnectInitiatedWhenRemoteConnects)406 TEST_F(EattTest, ConnectInitiatedWhenRemoteConnects) {
407   ON_CALL(btm_api_interface_, IsEncrypted)
408       .WillByDefault(
409           [](const RawAddress& addr, tBT_TRANSPORT transport) { return true; });
410 
411   std::vector<uint16_t> incoming_cids{71, 72, 73, 74};
412   ConnectDeviceBothSides(1, incoming_cids);
413 
414   std::vector<uint16_t> disconnecting_cids;
415   disconnecting_cids.insert(disconnecting_cids.end(), incoming_cids.begin(),
416                             incoming_cids.end());
417   disconnecting_cids.insert(disconnecting_cids.end(), connected_cids_.begin(),
418                             connected_cids_.end());
419   DisconnectEattDevice(disconnecting_cids);
420 }
421 
TEST_F(EattTest,ConnectSucceedMultipleChannels)422 TEST_F(EattTest, ConnectSucceedMultipleChannels) {
423   ConnectDeviceEattSupported(5);
424   DisconnectEattDevice(connected_cids_);
425 }
426 
TEST_F(EattTest,ConnectFailedEattNotSupported)427 TEST_F(EattTest, ConnectFailedEattNotSupported) {
428   ON_CALL(gatt_interface_, ClientReadSupportedFeatures)
429       .WillByDefault(
430           [](const RawAddress& addr,
431              base::OnceCallback<void(const RawAddress&, uint8_t)> cb) {
432             std::move(cb).Run(addr, 0);
433             return true;
434           });
435   ON_CALL(gatt_interface_, GetEattSupport)
436       .WillByDefault([](const RawAddress& addr) { return false; });
437 
438   EXPECT_CALL(l2cap_interface_,
439               ConnectCreditBasedReq(BT_PSM_EATT, test_address, _))
440       .Times(0);
441   eatt_instance_->Connect(test_address);
442   ASSERT_TRUE(eatt_instance_->IsEattSupportedByPeer(test_address) == false);
443 }
444 
TEST_F(EattTest,ConnectFailedSlaveOnTheLink)445 TEST_F(EattTest, ConnectFailedSlaveOnTheLink) {
446   EXPECT_CALL(l2cap_interface_,
447               ConnectCreditBasedReq(BT_PSM_EATT, test_address, _))
448       .Times(0);
449 
450   hci_role_ = HCI_ROLE_PERIPHERAL;
451   eatt_instance_->Connect(test_address);
452 
453   /* Back to default btm role */
454   hci_role_ = HCI_ROLE_CENTRAL;
455 }
456 
TEST_F(EattTest,DisonnectByPeerSucceed)457 TEST_F(EattTest, DisonnectByPeerSucceed) {
458   ConnectDeviceEattSupported(2);
459 
460   uint16_t cid = connected_cids_[0];
461   EattChannel* channel =
462       eatt_instance_->FindEattChannelByCid(test_address, cid);
463   ASSERT_TRUE(channel->state_ == EattChannelState::EATT_CHANNEL_OPENED);
464 
465   DisconnectEattByPeer();
466 
467   channel = eatt_instance_->FindEattChannelByCid(test_address, cid);
468   ASSERT_TRUE(channel == nullptr);
469 }
470 
TEST_F(EattTest,ReconfigAllSucceed)471 TEST_F(EattTest, ReconfigAllSucceed) {
472   ConnectDeviceEattSupported(3);
473 
474   std::vector<uint16_t> cids;
475   EXPECT_CALL(l2cap_interface_, ReconfigCreditBasedConnsReq(_, _, _))
476       .WillOnce(DoAll(SaveArg<1>(&cids), Return(true)));
477 
478   uint16_t new_mtu = 300;
479   eatt_instance_->ReconfigureAll(test_address, new_mtu);
480 
481   ASSERT_TRUE(cids.size() == connected_cids_.size());
482 
483   tL2CAP_LE_CFG_INFO cfg = {.result = L2CAP_CFG_OK, .mtu = new_mtu};
484 
485   for (uint16_t cid : cids) {
486     l2cap_app_info_.pL2CA_CreditBasedReconfigCompleted_Cb(test_address, cid,
487                                                           true, &cfg);
488 
489     EattChannel* channel =
490         eatt_instance_->FindEattChannelByCid(test_address, cid);
491     ASSERT_TRUE(channel->state_ == EattChannelState::EATT_CHANNEL_OPENED);
492     ASSERT_TRUE(channel->rx_mtu_ == new_mtu);
493   }
494 
495   DisconnectEattDevice(connected_cids_);
496 }
497 
TEST_F(EattTest,ReconfigAllFailed)498 TEST_F(EattTest, ReconfigAllFailed) {
499   ConnectDeviceEattSupported(4);
500 
501   std::vector<uint16_t> cids;
502   EXPECT_CALL(l2cap_interface_, ReconfigCreditBasedConnsReq(_, _, _))
503       .WillOnce(DoAll(SaveArg<1>(&cids), Return(true)));
504 
505   uint16_t new_mtu = 300;
506   eatt_instance_->ReconfigureAll(test_address, new_mtu);
507 
508   ASSERT_TRUE(cids.size() == connected_cids_.size());
509 
510   tL2CAP_LE_CFG_INFO cfg = {.result = L2CAP_CFG_FAILED_NO_REASON,
511                             .mtu = new_mtu};
512 
513   for (uint16_t cid : cids) {
514     l2cap_app_info_.pL2CA_CreditBasedReconfigCompleted_Cb(test_address, cid,
515                                                           true, &cfg);
516 
517     EattChannel* channel =
518         eatt_instance_->FindEattChannelByCid(test_address, cid);
519     ASSERT_TRUE(channel->state_ == EattChannelState::EATT_CHANNEL_OPENED);
520     ASSERT_TRUE(channel->rx_mtu_ != new_mtu);
521   }
522 
523   DisconnectEattDevice(connected_cids_);
524 }
525 
TEST_F(EattTest,ReconfigSingleSucceed)526 TEST_F(EattTest, ReconfigSingleSucceed) {
527   ConnectDeviceEattSupported(2);
528 
529   std::vector<uint16_t> cids;
530   EXPECT_CALL(l2cap_interface_, ReconfigCreditBasedConnsReq(_, _, _))
531       .WillOnce(DoAll(SaveArg<1>(&cids), Return(true)));
532 
533   uint16_t new_mtu = 300;
534   eatt_instance_->Reconfigure(test_address, connected_cids_[1], new_mtu);
535 
536   ASSERT_TRUE(cids.size() == 1);
537 
538   tL2CAP_LE_CFG_INFO cfg = {.result = L2CAP_CFG_OK, .mtu = new_mtu};
539 
540   auto it = std::find(connected_cids_.begin(), connected_cids_.end(), cids[0]);
541   ASSERT_TRUE(it != connected_cids_.end());
542 
543   l2cap_app_info_.pL2CA_CreditBasedReconfigCompleted_Cb(test_address, cids[0],
544                                                         true, &cfg);
545   EattChannel* channel =
546       eatt_instance_->FindEattChannelByCid(test_address, cids[0]);
547   ASSERT_TRUE(channel->state_ == EattChannelState::EATT_CHANNEL_OPENED);
548   ASSERT_TRUE(channel->rx_mtu_ == new_mtu);
549 
550   DisconnectEattDevice(connected_cids_);
551 }
552 
TEST_F(EattTest,ReconfigSingleFailed)553 TEST_F(EattTest, ReconfigSingleFailed) {
554   ConnectDeviceEattSupported(2);
555 
556   std::vector<uint16_t> cids;
557   EXPECT_CALL(l2cap_interface_, ReconfigCreditBasedConnsReq(_, _, _))
558       .WillOnce(DoAll(SaveArg<1>(&cids), Return(true)));
559 
560   uint16_t new_mtu = 300;
561   eatt_instance_->ReconfigureAll(test_address, new_mtu);
562 
563   ASSERT_TRUE(cids.size() == connected_cids_.size());
564 
565   tL2CAP_LE_CFG_INFO cfg = {.result = L2CAP_CFG_FAILED_NO_REASON,
566                             .mtu = new_mtu};
567 
568   auto it = std::find(connected_cids_.begin(), connected_cids_.end(), cids[0]);
569   ASSERT_TRUE(it != connected_cids_.end());
570 
571   l2cap_app_info_.pL2CA_CreditBasedReconfigCompleted_Cb(test_address, cids[0],
572                                                         true, &cfg);
573   EattChannel* channel =
574       eatt_instance_->FindEattChannelByCid(test_address, cids[0]);
575   ASSERT_TRUE(channel->state_ == EattChannelState::EATT_CHANNEL_OPENED);
576   ASSERT_TRUE(channel->rx_mtu_ != new_mtu);
577 
578   DisconnectEattDevice(connected_cids_);
579 }
580 
TEST_F(EattTest,ReconfigPeerSucceed)581 TEST_F(EattTest, ReconfigPeerSucceed) {
582   ConnectDeviceEattSupported(3);
583 
584   uint16_t new_mtu = 300;
585   tL2CAP_LE_CFG_INFO cfg = {.result = L2CAP_CFG_OK, .mtu = new_mtu};
586 
587   for (uint16_t cid : connected_cids_) {
588     l2cap_app_info_.pL2CA_CreditBasedReconfigCompleted_Cb(test_address, cid,
589                                                           false, &cfg);
590 
591     EattChannel* channel =
592         eatt_instance_->FindEattChannelByCid(test_address, cid);
593     ASSERT_TRUE(channel->state_ == EattChannelState::EATT_CHANNEL_OPENED);
594     ASSERT_TRUE(channel->tx_mtu_ == new_mtu);
595   }
596 
597   DisconnectEattDevice(connected_cids_);
598 }
599 
TEST_F(EattTest,ReconfigPeerFailed)600 TEST_F(EattTest, ReconfigPeerFailed) {
601   ConnectDeviceEattSupported(2);
602 
603   uint16_t new_mtu = 300;
604   tL2CAP_LE_CFG_INFO cfg = {.result = L2CAP_CFG_FAILED_NO_REASON,
605                             .mtu = new_mtu};
606 
607   for (uint16_t cid : connected_cids_) {
608     l2cap_app_info_.pL2CA_CreditBasedReconfigCompleted_Cb(test_address, cid,
609                                                           false, &cfg);
610 
611     EattChannel* channel =
612         eatt_instance_->FindEattChannelByCid(test_address, cid);
613     ASSERT_TRUE(channel->state_ == EattChannelState::EATT_CHANNEL_OPENED);
614     ASSERT_TRUE(channel->tx_mtu_ != new_mtu);
615   }
616 
617   DisconnectEattDevice(connected_cids_);
618 }
619 
TEST_F(EattTest,DoubleDisconnect)620 TEST_F(EattTest, DoubleDisconnect) {
621   ConnectDeviceEattSupported(1);
622   DisconnectEattDevice(connected_cids_);
623 
624   /* Force second disconnect */
625   eatt_instance_->Disconnect(test_address);
626 }
627 
TEST_F(EattTest,TestCollisionHandling)628 TEST_F(EattTest, TestCollisionHandling) {
629   ConnectDeviceEattSupported(0, true /* collision*/);
630   ConnectDeviceEattSupported(5, true /* collision*/);
631 }
632 
TEST_F(EattTest,ChannelUnavailableWhileOpening)633 TEST_F(EattTest, ChannelUnavailableWhileOpening) {
634   // arrange
635   ON_CALL(gatt_interface_, ClientReadSupportedFeatures)
636       .WillByDefault(
637           [](const RawAddress& addr,
638              base::OnceCallback<void(const RawAddress&, uint8_t)> cb) {
639             std::move(cb).Run(addr, BLE_GATT_SVR_SUP_FEAT_EATT_BITMASK);
640             return true;
641           });
642   ON_CALL(gatt_interface_, GetEattSupport).WillByDefault(Return(true));
643 
644   // expect
645   EXPECT_CALL(l2cap_interface_,
646               ConnectCreditBasedReq(BT_PSM_EATT, test_address, _))
647       .WillOnce(Return(std::vector<uint16_t>{61}));
648 
649   // act: start
650   eatt_instance_->Connect(test_address);
651   auto available_channel_for_request =
652       eatt_instance_->GetChannelAvailableForClientRequest(test_address);
653   auto available_channel_for_indication =
654       eatt_instance_->GetChannelAvailableForIndication(test_address);
655 
656   // assert
657   ASSERT_EQ(available_channel_for_request, nullptr);
658   ASSERT_EQ(available_channel_for_indication, nullptr);
659 }
660 
TEST_F(EattTest,ChannelUnavailableWhileReconfiguring)661 TEST_F(EattTest, ChannelUnavailableWhileReconfiguring) {
662   // arrange
663   ON_CALL(l2cap_interface_, ReconfigCreditBasedConnsReq(_, _, _))
664       .WillByDefault(Return(true));
665   ConnectDeviceEattSupported(/* num_of_accepted_connections = */ 1);
666 
667   // act: reconfigure, then get available channels
668   eatt_instance_->Reconfigure(test_address, connected_cids_[0], 300);
669   auto available_channel_for_request =
670       eatt_instance_->GetChannelAvailableForClientRequest(test_address);
671   auto available_channel_for_indication =
672       eatt_instance_->GetChannelAvailableForIndication(test_address);
673 
674   // assert
675   ASSERT_EQ(available_channel_for_request, nullptr);
676   ASSERT_EQ(available_channel_for_indication, nullptr);
677 }
678 
679 }  // namespace
680