1 /*
2 * Copyright 2021 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 <gtest/gtest.h>
18 #include <string.h>
19
20 #include <cstdint>
21 #include <map>
22 #include <memory>
23 #include <string>
24
25 #include "common/message_loop_thread.h"
26 #include "common/strings.h"
27 #include "stack/gatt/gatt_int.h"
28 #include "stack/include/gatt_api.h"
29
30 std::map<std::string, int> mock_function_count_map;
31
LogMsg(uint32_t trace_set_mask,const char * fmt_str,...)32 void LogMsg(uint32_t trace_set_mask, const char* fmt_str, ...) {}
33
get_main_thread()34 bluetooth::common::MessageLoopThread* get_main_thread() { return nullptr; }
35
36 class StackGattTest : public ::testing::Test {};
37
38 namespace {
39
40 // Actual size of structure without compiler padding
actual_sizeof_tGATT_REG()41 size_t actual_sizeof_tGATT_REG() {
42 return sizeof(bluetooth::Uuid) + sizeof(tGATT_CBACK) + sizeof(tGATT_IF) +
43 sizeof(bool) + sizeof(uint8_t) + sizeof(bool);
44 }
45
tGATT_DISC_RES_CB(uint16_t conn_id,tGATT_DISC_TYPE disc_type,tGATT_DISC_RES * p_data)46 void tGATT_DISC_RES_CB(uint16_t conn_id, tGATT_DISC_TYPE disc_type,
47 tGATT_DISC_RES* p_data) {}
tGATT_DISC_CMPL_CB(uint16_t conn_id,tGATT_DISC_TYPE disc_type,tGATT_STATUS status)48 void tGATT_DISC_CMPL_CB(uint16_t conn_id, tGATT_DISC_TYPE disc_type,
49 tGATT_STATUS status) {}
tGATT_CMPL_CBACK(uint16_t conn_id,tGATTC_OPTYPE op,tGATT_STATUS status,tGATT_CL_COMPLETE * p_data)50 void tGATT_CMPL_CBACK(uint16_t conn_id, tGATTC_OPTYPE op, tGATT_STATUS status,
51 tGATT_CL_COMPLETE* p_data) {}
tGATT_CONN_CBACK(tGATT_IF gatt_if,const RawAddress & bda,uint16_t conn_id,bool connected,tGATT_DISCONN_REASON reason,tBT_TRANSPORT transport)52 void tGATT_CONN_CBACK(tGATT_IF gatt_if, const RawAddress& bda, uint16_t conn_id,
53 bool connected, tGATT_DISCONN_REASON reason,
54 tBT_TRANSPORT transport) {}
tGATT_REQ_CBACK(uint16_t conn_id,uint32_t trans_id,tGATTS_REQ_TYPE type,tGATTS_DATA * p_data)55 void tGATT_REQ_CBACK(uint16_t conn_id, uint32_t trans_id, tGATTS_REQ_TYPE type,
56 tGATTS_DATA* p_data) {}
tGATT_CONGESTION_CBACK(uint16_t conn_id,bool congested)57 void tGATT_CONGESTION_CBACK(uint16_t conn_id, bool congested) {}
tGATT_ENC_CMPL_CB(tGATT_IF gatt_if,const RawAddress & bda)58 void tGATT_ENC_CMPL_CB(tGATT_IF gatt_if, const RawAddress& bda) {}
tGATT_PHY_UPDATE_CB(tGATT_IF gatt_if,uint16_t conn_id,uint8_t tx_phy,uint8_t rx_phy,tGATT_STATUS status)59 void tGATT_PHY_UPDATE_CB(tGATT_IF gatt_if, uint16_t conn_id, uint8_t tx_phy,
60 uint8_t rx_phy, tGATT_STATUS status) {}
tGATT_CONN_UPDATE_CB(tGATT_IF gatt_if,uint16_t conn_id,uint16_t interval,uint16_t latency,uint16_t timeout,tGATT_STATUS status)61 void tGATT_CONN_UPDATE_CB(tGATT_IF gatt_if, uint16_t conn_id, uint16_t interval,
62 uint16_t latency, uint16_t timeout,
63 tGATT_STATUS status) {}
64
65 tGATT_CBACK gatt_callbacks = {
66 .p_conn_cb = tGATT_CONN_CBACK,
67 .p_cmpl_cb = tGATT_CMPL_CBACK,
68 .p_disc_res_cb = tGATT_DISC_RES_CB,
69 .p_disc_cmpl_cb = tGATT_DISC_CMPL_CB,
70 .p_req_cb = tGATT_REQ_CBACK,
71 .p_enc_cmpl_cb = tGATT_ENC_CMPL_CB,
72 .p_congestion_cb = tGATT_CONGESTION_CBACK,
73 .p_phy_update_cb = tGATT_PHY_UPDATE_CB,
74 .p_conn_update_cb = tGATT_CONN_UPDATE_CB,
75 };
76
77 } // namespace
78
TEST_F(StackGattTest,lifecycle_tGATT_REG)79 TEST_F(StackGattTest, lifecycle_tGATT_REG) {
80 {
81 std::unique_ptr<tGATT_REG> reg0 = std::make_unique<tGATT_REG>();
82 std::unique_ptr<tGATT_REG> reg1 = std::make_unique<tGATT_REG>();
83 memset(reg0.get(), 0xff, sizeof(tGATT_REG));
84 memset(reg1.get(), 0xff, sizeof(tGATT_REG));
85 ASSERT_EQ(0, memcmp(reg0.get(), reg1.get(), sizeof(tGATT_REG)));
86
87 memset(reg0.get(), 0x0, sizeof(tGATT_REG));
88 memset(reg1.get(), 0x0, sizeof(tGATT_REG));
89 ASSERT_EQ(0, memcmp(reg0.get(), reg1.get(), sizeof(tGATT_REG)));
90 }
91
92 {
93 std::unique_ptr<tGATT_REG> reg0 = std::make_unique<tGATT_REG>();
94 memset(reg0.get(), 0xff, sizeof(tGATT_REG));
95
96 tGATT_REG reg1;
97 memset(®1, 0xff, sizeof(tGATT_REG));
98
99 // Clear the structures
100 memset(reg0.get(), 0, sizeof(tGATT_REG));
101 // Restore the complex structure after memset
102 memset(®1.name, 0, sizeof(std::string));
103 reg1 = {};
104 ASSERT_EQ(0, memcmp(reg0.get(), ®1, actual_sizeof_tGATT_REG()));
105 }
106
107 {
108 tGATT_REG* reg0 = new tGATT_REG();
109 tGATT_REG* reg1 = new tGATT_REG();
110 memset(reg0, 0, sizeof(tGATT_REG));
111 *reg1 = {};
112 reg0->in_use = true;
113 ASSERT_NE(0, memcmp(reg0, reg1, sizeof(tGATT_REG)));
114 delete reg1;
115 delete reg0;
116 }
117 }
118
TEST_F(StackGattTest,gatt_init_free)119 TEST_F(StackGattTest, gatt_init_free) {
120 gatt_init();
121 gatt_free();
122 }
123
TEST_F(StackGattTest,GATT_Register_Deregister)124 TEST_F(StackGattTest, GATT_Register_Deregister) {
125 gatt_init();
126
127 // Gatt db profile always takes the first slot
128 tGATT_IF apps[GATT_MAX_APPS - 1];
129
130 for (int i = 0; i < GATT_MAX_APPS - 1; i++) {
131 std::string name = bluetooth::common::StringFormat("name%02d", i);
132 apps[i] = GATT_Register(bluetooth::Uuid::GetRandom(), name, &gatt_callbacks,
133 false);
134 }
135
136 for (int i = 0; i < GATT_MAX_APPS - 1; i++) {
137 GATT_Deregister(apps[i]);
138 }
139
140 gatt_free();
141 }
142