1 /*
2 * Copyright 2023 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 #include "test/fake/fake_osi.h"
17
18 #include <bluetooth/log.h>
19
20 #include "test/mock/mock_osi_alarm.h"
21 #include "test/mock/mock_osi_allocator.h"
22 #include "test/mock/mock_osi_fixed_queue.h"
23 #include "test/mock/mock_osi_list.h"
24
25 using namespace bluetooth;
26
27 // Must be global to resolve the symbol within the legacy stack
28 struct alarm_t {
29 alarm_callback_t cb;
30 void* data;
31
alarm_talarm_t32 alarm_t(const char* /* name */) {
33 cb = nullptr;
34 data = nullptr;
35 };
36 };
37
38 struct list_node_t {
39 void* data_;
40 list_node_t* next_;
41
list_node_tlist_node_t42 list_node_t(void* data, list_node_t* next) {
43 data_ = data;
44 next_ = next;
45 }
46 };
47
48 struct list_t {
49 list_node_t* head_;
50 list_node_t* tail_;
51 size_t length_;
52 list_free_cb free_cb_;
53
list_tlist_t54 list_t(list_free_cb free_cb) {
55 head_ = tail_ = nullptr;
56 free_cb_ = free_cb;
57 length_ = 0;
58 }
59 };
60
61 struct fixed_queue_t {
62 list_t* list_;
63 size_t capacity_;
64
fixed_queue_tfixed_queue_t65 fixed_queue_t(size_t capacity) {
66 list_ = test::mock::osi_list::list_new(nullptr);
67 capacity_ = capacity;
68 }
69 };
70
71 namespace test {
72 namespace fake {
73
list_free_node_(list_t * l,list_node_t * node)74 static list_node_t* list_free_node_(list_t* l, list_node_t* node) {
75 log::assert_that(l != nullptr, "assert failed: l != nullptr");
76 log::assert_that(node != nullptr, "assert failed: node != nullptr");
77
78 auto next = node->next_;
79
80 if (l->free_cb_) l->free_cb_(node->data_);
81 delete node;
82 --l->length_;
83 return next;
84 }
85
FakeOsi()86 FakeOsi::FakeOsi() {
87 test::mock::osi_alarm::alarm_free.body = [](alarm_t* alarm) {
88 if (alarm) {
89 delete alarm;
90 }
91 };
92
93 test::mock::osi_alarm::alarm_new.body = [](const char* name) {
94 return new alarm_t(name);
95 };
96
97 test::mock::osi_alarm::alarm_set_on_mloop.body =
98 [](alarm_t* alarm, uint64_t /* interval_ms */, alarm_callback_t cb,
99 void* data) {
100 alarm->cb = cb;
101 alarm->data = data;
102 };
103
104 test::mock::osi_alarm::alarm_cancel.body = [](alarm_t* alarm) {
105 if (alarm) {
106 alarm->cb = nullptr;
107 alarm->data = nullptr;
108 }
109 };
110
111 test::mock::osi_allocator::osi_calloc.body = [](size_t size) {
112 return calloc(1UL, size);
113 };
114 test::mock::osi_allocator::osi_free.body = [](void* ptr) { free(ptr); };
115 test::mock::osi_allocator::osi_free_and_reset.body = [](void** ptr) {
116 free(*ptr);
117 *ptr = nullptr;
118 };
119 test::mock::osi_allocator::osi_malloc.body = [](size_t size) {
120 return malloc(size);
121 };
122
123 test::mock::osi_list::list_new.body = [](list_free_cb callback) {
124 return new list_t(callback);
125 };
126
127 test::mock::osi_list::list_free.body = [](list_t* l) {
128 log::assert_that(l != nullptr, "assert failed: l != nullptr");
129 test::mock::osi_list::list_clear(l);
130 delete l;
131 };
132 test::mock::osi_list::list_is_empty.body = [](const list_t* l) {
133 return test::mock::osi_list::list_length(l) == 0;
134 };
135 test::mock::osi_list::list_foreach.body =
136 [](const list_t* l, list_iter_cb callback, void* context) {
137 log::assert_that(l != nullptr, "assert failed: l != nullptr");
138 for (auto node = l->head_; node;) {
139 auto next = node->next_;
140 if (!callback(node->data_, context)) return node;
141 node = next;
142 }
143 return (list_node_t*)nullptr;
144 };
145 test::mock::osi_list::list_contains.body = [](const list_t* l,
146 const void* data) {
147 auto node = test::mock::osi_list::list_foreach(
148 l, [](void* data, void* context) { return data != context; },
149 const_cast<void*>(data));
150 return node;
151 };
152 test::mock::osi_list::list_length.body = [](const list_t* l) {
153 log::assert_that(l != nullptr, "assert failed: l != nullptr");
154 return l->length_;
155 };
156 test::mock::osi_list::list_front.body = [](const list_t* l) {
157 log::assert_that(l != nullptr, "assert failed: l != nullptr");
158 log::assert_that(l->head_, "assert failed: l->head_");
159 return l->head_->data_;
160 };
161 test::mock::osi_list::list_back.body = [](const list_t* l) {
162 log::assert_that(l != nullptr, "assert failed: l != nullptr");
163 log::assert_that(l->tail_, "assert failed: l->tail_");
164 return l->tail_->data_;
165 };
166 test::mock::osi_list::list_back_node.body = [](const list_t* l) {
167 log::assert_that(l != nullptr, "assert failed: l != nullptr");
168 return l->tail_;
169 };
170
171 test::mock::osi_list::list_insert_after.body =
172 [](list_t* l, list_node_t* prev_node, void* data) {
173 log::assert_that(l != nullptr, "assert failed: l != nullptr");
174 log::assert_that(prev_node != nullptr,
175 "assert failed: prev_node != nullptr");
176 log::assert_that(data != nullptr, "assert failed: data != nullptr");
177 auto node = new list_node_t(data, prev_node->next_);
178 prev_node->next_ = node;
179 if (l->tail_ == prev_node) l->tail_ = node;
180 ++l->length_;
181 return true;
182 };
183 test::mock::osi_list::list_prepend.body = [](list_t* l, void* data) {
184 log::assert_that(l != nullptr, "assert failed: l != nullptr");
185 log::assert_that(data != nullptr, "assert failed: data != nullptr");
186
187 auto node = new list_node_t(data, l->head_);
188 l->head_ = node;
189 if (l->tail_ == NULL) l->tail_ = l->head_;
190 ++l->length_;
191 return true;
192 };
193 test::mock::osi_list::list_append.body = [](list_t* l, void* data) {
194 log::assert_that(l != nullptr, "assert failed: l != nullptr");
195 log::assert_that(data != nullptr, "assert failed: data != nullptr");
196
197 auto node = new list_node_t(data, nullptr);
198 if (l->tail_) {
199 l->tail_->next_ = node;
200 l->tail_ = node;
201 } else {
202 l->head_ = l->tail_ = node;
203 }
204 ++l->length_;
205 return true;
206 };
207 test::mock::osi_list::list_remove.body = [](list_t* l, void* data) {
208 log::assert_that(l != nullptr, "assert failed: l != nullptr");
209 log::assert_that(data != nullptr, "assert failed: data != nullptr");
210
211 if (test::mock::osi_list::list_is_empty(l)) return false;
212
213 if (l->head_->data_ == data) {
214 auto next = list_free_node_(l, l->head_);
215 if (l->tail_ == l->head_) l->tail_ = next;
216 l->head_ = next;
217 return true;
218 }
219
220 for (auto prev = l->head_, node = l->head_->next_; node;
221 prev = node, node = node->next_)
222 if (node->data_ == data) {
223 prev->next_ = list_free_node_(l, node);
224 if (l->tail_ == node) l->tail_ = prev;
225 return true;
226 }
227
228 return false;
229 };
230 test::mock::osi_list::list_clear.body = [](list_t* l) {
231 log::assert_that(l != nullptr, "assert failed: l != nullptr");
232 for (auto node = l->head_; node;) {
233 node = list_free_node_(l, node);
234 }
235 l->head_ = NULL;
236 l->tail_ = NULL;
237 l->length_ = 0;
238 return;
239 };
240
241 test::mock::osi_list::list_begin.body = [](const list_t* l) {
242 log::assert_that(l != nullptr, "assert failed: l != nullptr");
243 return l->head_;
244 };
245 test::mock::osi_list::list_end.body = [](const list_t* l) {
246 log::assert_that(l != nullptr, "assert failed: l != nullptr");
247 return l->tail_;
248 };
249 test::mock::osi_list::list_next.body = [](const list_node_t* node) {
250 log::assert_that(node != nullptr, "assert failed: node != nullptr");
251 return node->next_;
252 };
253 test::mock::osi_list::list_node.body = [](const list_node_t* node) {
254 log::assert_that(node != nullptr, "assert failed: node != nullptr");
255 return node->data_;
256 };
257
258 test::mock::osi_fixed_queue::fixed_queue_new.body = [](size_t capacity) {
259 return new fixed_queue_t(capacity);
260 };
261 test::mock::osi_fixed_queue::fixed_queue_flush.body =
262 [](fixed_queue_t* q, fixed_queue_free_cb cb) {
263 if (q) {
264 if (cb) {
265 test::mock::osi_list::list_foreach(
266 q->list_,
267 [](void* data, void* cb) {
268 reinterpret_cast<fixed_queue_free_cb>(cb)(data);
269 return true;
270 },
271 reinterpret_cast<void*>(cb));
272 }
273 test::mock::osi_list::list_clear(q->list_);
274 }
275 };
276 test::mock::osi_fixed_queue::fixed_queue_free.body =
277 [](fixed_queue_t* q, fixed_queue_free_cb free_cb) {
278 if (q) {
279 test::mock::osi_fixed_queue::fixed_queue_flush(q, free_cb);
280 delete q->list_;
281 delete q;
282 }
283 };
284 test::mock::osi_fixed_queue::fixed_queue_enqueue.body = [](fixed_queue_t* q,
285 void* data) {
286 if (q) test::mock::osi_list::list_append(q->list_, data);
287 };
288 test::mock::osi_fixed_queue::fixed_queue_dequeue.body = [](fixed_queue_t* q) {
289 void* ret = nullptr;
290 if (q) {
291 ret = test::mock::osi_list::list_front(q->list_);
292 test::mock::osi_list::list_remove(q->list_, ret);
293 }
294 return ret;
295 };
296
297 test::mock::osi_fixed_queue::fixed_queue_length.body = [](fixed_queue_t* q) {
298 return q ? test::mock::osi_list::list_length(q->list_) : 0;
299 };
300
301 test::mock::osi_fixed_queue::fixed_queue_is_empty.body =
302 [](fixed_queue_t* q) {
303 return test::mock::osi_fixed_queue::fixed_queue_length(q) == 0;
304 };
305
306 test::mock::osi_fixed_queue::fixed_queue_capacity.body =
307 [](fixed_queue_t* q) { return q ? q->capacity_ : 0; };
308
309 test::mock::osi_fixed_queue::fixed_queue_try_enqueue.body =
310 [](fixed_queue_t* q, void* data) {
311 test::mock::osi_fixed_queue::fixed_queue_enqueue(q, data);
312 return true;
313 };
314 test::mock::osi_fixed_queue::fixed_queue_try_dequeue.body =
315 [](fixed_queue_t* q) {
316 void* ret = nullptr;
317 if (q && !test::mock::osi_fixed_queue::fixed_queue_is_empty(q)) {
318 ret = test::mock::osi_fixed_queue::fixed_queue_dequeue(q);
319 }
320 return ret;
321 };
322 test::mock::osi_fixed_queue::fixed_queue_try_peek_first.body =
323 [](fixed_queue_t* q) {
324 return (q && !test::mock::osi_list::list_is_empty(q->list_))
325 ? test::mock::osi_list::list_front(q->list_)
326 : nullptr;
327 };
328
329 test::mock::osi_fixed_queue::fixed_queue_try_peek_last.body =
330 [](fixed_queue_t* q) {
331 return (q && !test::mock::osi_list::list_is_empty(q->list_))
332 ? test::mock::osi_list::list_back(q->list_)
333 : nullptr;
334 };
335
336 test::mock::osi_fixed_queue::fixed_queue_get_list.body =
337 [](fixed_queue_t* q) { return q ? q->list_ : nullptr; };
338
339 test::mock::osi_fixed_queue::fixed_queue_try_remove_from_queue.body =
340 [](fixed_queue_t* /* q */, void* /* data */) {
341 // not implemented
342 abort();
343 return nullptr;
344 };
345
346 test::mock::osi_fixed_queue::fixed_queue_get_enqueue_fd.body =
347 [](const fixed_queue_t* /* q */) {
348 // not implemented
349 abort();
350 return 0;
351 };
352
353 test::mock::osi_fixed_queue::fixed_queue_get_dequeue_fd.body =
354 [](const fixed_queue_t* /* q */) {
355 // not implemented
356 abort();
357 return 0;
358 };
359
360 test::mock::osi_fixed_queue::fixed_queue_register_dequeue.body =
361 [](fixed_queue_t* /* q */, reactor_t* /* reactor */,
362 fixed_queue_cb /* ready_cb */, void* /* context */) {
363 // not implemented
364 abort();
365 };
366 test::mock::osi_fixed_queue::fixed_queue_unregister_dequeue.body =
367 [](fixed_queue_t* /* q */) {
368 // not implemented
369 abort();
370 };
371 }
372
~FakeOsi()373 FakeOsi::~FakeOsi() {
374 test::mock::osi_alarm::alarm_free = {};
375 test::mock::osi_alarm::alarm_new = {};
376
377 test::mock::osi_allocator::osi_calloc = {};
378 test::mock::osi_allocator::osi_free = {};
379 test::mock::osi_allocator::osi_free_and_reset = {};
380 test::mock::osi_allocator::osi_malloc = {};
381
382 test::mock::osi_list::list_new = {};
383 test::mock::osi_list::list_free = {};
384 test::mock::osi_list::list_is_empty = {};
385 test::mock::osi_list::list_foreach = {};
386 test::mock::osi_list::list_contains = {};
387 test::mock::osi_list::list_length = {};
388 test::mock::osi_list::list_front = {};
389 test::mock::osi_list::list_back = {};
390 test::mock::osi_list::list_back_node = {};
391 test::mock::osi_list::list_insert_after = {};
392 test::mock::osi_list::list_prepend = {};
393 test::mock::osi_list::list_append = {};
394 test::mock::osi_list::list_remove = {};
395 test::mock::osi_list::list_clear = {};
396 test::mock::osi_list::list_begin = {};
397 test::mock::osi_list::list_end = {};
398 test::mock::osi_list::list_next = {};
399 test::mock::osi_list::list_node = {};
400
401 test::mock::osi_fixed_queue::fixed_queue_new = {};
402 test::mock::osi_fixed_queue::fixed_queue_flush = {};
403 test::mock::osi_fixed_queue::fixed_queue_free = {};
404 test::mock::osi_fixed_queue::fixed_queue_enqueue = {};
405 test::mock::osi_fixed_queue::fixed_queue_dequeue = {};
406 test::mock::osi_fixed_queue::fixed_queue_length = {};
407 test::mock::osi_fixed_queue::fixed_queue_is_empty = {};
408 test::mock::osi_fixed_queue::fixed_queue_capacity = {};
409 test::mock::osi_fixed_queue::fixed_queue_try_enqueue = {};
410 test::mock::osi_fixed_queue::fixed_queue_try_dequeue = {};
411 test::mock::osi_fixed_queue::fixed_queue_try_peek_first = {};
412 test::mock::osi_fixed_queue::fixed_queue_try_peek_last = {};
413 test::mock::osi_fixed_queue::fixed_queue_try_remove_from_queue = {};
414 test::mock::osi_fixed_queue::fixed_queue_get_list = {};
415 test::mock::osi_fixed_queue::fixed_queue_get_enqueue_fd = {};
416 test::mock::osi_fixed_queue::fixed_queue_get_dequeue_fd = {};
417 test::mock::osi_fixed_queue::fixed_queue_register_dequeue = {};
418 test::mock::osi_fixed_queue::fixed_queue_unregister_dequeue = {};
419 }
420
421 } // namespace fake
422 } // namespace test
423