418 lines
12 KiB
C++
418 lines
12 KiB
C++
/*
|
|
* Copyright 2023 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 "test/fake/fake_osi.h"
|
|
|
|
#include "test/mock/mock_osi_alarm.h"
|
|
#include "test/mock/mock_osi_allocator.h"
|
|
#include "test/mock/mock_osi_fixed_queue.h"
|
|
#include "test/mock/mock_osi_list.h"
|
|
|
|
// Must be global to resolve the symbol within the legacy stack
|
|
struct alarm_t {
|
|
alarm_callback_t cb;
|
|
void* data;
|
|
|
|
alarm_t(const char* name) {
|
|
cb = nullptr;
|
|
data = nullptr;
|
|
};
|
|
};
|
|
|
|
struct list_node_t {
|
|
void* data_;
|
|
list_node_t* next_;
|
|
|
|
list_node_t(void* data, list_node_t* next) {
|
|
data_ = data;
|
|
next_ = next;
|
|
}
|
|
};
|
|
|
|
struct list_t {
|
|
list_node_t* head_;
|
|
list_node_t* tail_;
|
|
size_t length_;
|
|
list_free_cb free_cb_;
|
|
|
|
list_t(list_free_cb free_cb) {
|
|
head_ = tail_ = nullptr;
|
|
free_cb_ = free_cb;
|
|
length_ = 0;
|
|
}
|
|
};
|
|
|
|
struct fixed_queue_t {
|
|
list_t* list_;
|
|
size_t capacity_;
|
|
|
|
fixed_queue_t(size_t capacity) {
|
|
list_ = test::mock::osi_list::list_new(nullptr);
|
|
capacity_ = capacity;
|
|
}
|
|
};
|
|
|
|
namespace test {
|
|
namespace fake {
|
|
|
|
static list_node_t* list_free_node_(list_t* l, list_node_t* node) {
|
|
CHECK(l);
|
|
CHECK(node);
|
|
|
|
auto next = node->next_;
|
|
|
|
if (l->free_cb_) l->free_cb_(node->data_);
|
|
delete node;
|
|
--l->length_;
|
|
return next;
|
|
}
|
|
|
|
FakeOsi::FakeOsi() {
|
|
test::mock::osi_alarm::alarm_free.body = [](alarm_t* alarm) {
|
|
if (alarm) {
|
|
delete alarm;
|
|
}
|
|
};
|
|
|
|
test::mock::osi_alarm::alarm_new.body = [](const char* name) {
|
|
return new alarm_t(name);
|
|
};
|
|
|
|
test::mock::osi_alarm::alarm_set_on_mloop.body =
|
|
[](alarm_t* alarm, uint64_t interval_ms, alarm_callback_t cb,
|
|
void* data) {
|
|
alarm->cb = cb;
|
|
alarm->data = data;
|
|
};
|
|
|
|
test::mock::osi_alarm::alarm_cancel.body = [](alarm_t* alarm) {
|
|
if (alarm) {
|
|
alarm->cb = nullptr;
|
|
alarm->data = nullptr;
|
|
}
|
|
};
|
|
|
|
test::mock::osi_allocator::osi_calloc.body = [](size_t size) {
|
|
return calloc(1UL, size);
|
|
};
|
|
test::mock::osi_allocator::osi_free.body = [](void* ptr) { free(ptr); };
|
|
test::mock::osi_allocator::osi_free_and_reset.body = [](void** ptr) {
|
|
free(*ptr);
|
|
*ptr = nullptr;
|
|
};
|
|
test::mock::osi_allocator::osi_malloc.body = [](size_t size) {
|
|
return malloc(size);
|
|
};
|
|
|
|
test::mock::osi_list::list_new.body = [](list_free_cb callback) {
|
|
return new list_t(callback);
|
|
};
|
|
|
|
test::mock::osi_list::list_free.body = [](list_t* l) {
|
|
CHECK(l);
|
|
test::mock::osi_list::list_clear(l);
|
|
delete l;
|
|
};
|
|
test::mock::osi_list::list_is_empty.body = [](const list_t* l) {
|
|
return test::mock::osi_list::list_length(l) == 0;
|
|
};
|
|
test::mock::osi_list::list_foreach.body =
|
|
[](const list_t* l, list_iter_cb callback, void* context) {
|
|
CHECK(l);
|
|
for (auto node = l->head_; node;) {
|
|
auto next = node->next_;
|
|
if (!callback(node->data_, context)) return node;
|
|
node = next;
|
|
}
|
|
return (list_node_t*)nullptr;
|
|
};
|
|
test::mock::osi_list::list_contains.body = [](const list_t* l,
|
|
const void* data) {
|
|
auto node = test::mock::osi_list::list_foreach(
|
|
l, [](void* data, void* context) { return data != context; },
|
|
const_cast<void*>(data));
|
|
return node;
|
|
};
|
|
test::mock::osi_list::list_length.body = [](const list_t* l) {
|
|
CHECK(l);
|
|
return l->length_;
|
|
};
|
|
test::mock::osi_list::list_front.body = [](const list_t* l) {
|
|
CHECK(l);
|
|
CHECK(l->head_);
|
|
return l->head_->data_;
|
|
};
|
|
test::mock::osi_list::list_back.body = [](const list_t* l) {
|
|
CHECK(l);
|
|
CHECK(l->tail_);
|
|
return l->tail_->data_;
|
|
};
|
|
test::mock::osi_list::list_back_node.body = [](const list_t* l) {
|
|
CHECK(l);
|
|
return l->tail_;
|
|
};
|
|
|
|
test::mock::osi_list::list_insert_after.body =
|
|
[](list_t* l, list_node_t* prev_node, void* data) {
|
|
CHECK(l);
|
|
CHECK(prev_node);
|
|
CHECK(data);
|
|
auto node = new list_node_t(data, prev_node->next_);
|
|
prev_node->next_ = node;
|
|
if (l->tail_ == prev_node) l->tail_ = node;
|
|
++l->length_;
|
|
return true;
|
|
};
|
|
test::mock::osi_list::list_prepend.body = [](list_t* l, void* data) {
|
|
CHECK(l);
|
|
CHECK(data);
|
|
|
|
auto node = new list_node_t(data, l->head_);
|
|
l->head_ = node;
|
|
if (l->tail_ == NULL) l->tail_ = l->head_;
|
|
++l->length_;
|
|
return true;
|
|
};
|
|
test::mock::osi_list::list_append.body = [](list_t* l, void* data) {
|
|
CHECK(l);
|
|
CHECK(data);
|
|
|
|
auto node = new list_node_t(data, nullptr);
|
|
if (l->tail_) {
|
|
l->tail_->next_ = node;
|
|
l->tail_ = node;
|
|
} else {
|
|
l->head_ = l->tail_ = node;
|
|
}
|
|
++l->length_;
|
|
return true;
|
|
};
|
|
test::mock::osi_list::list_remove.body = [](list_t* l, void* data) {
|
|
CHECK(l);
|
|
CHECK(data);
|
|
|
|
if (test::mock::osi_list::list_is_empty(l)) return false;
|
|
|
|
if (l->head_->data_ == data) {
|
|
auto next = list_free_node_(l, l->head_);
|
|
if (l->tail_ == l->head_) l->tail_ = next;
|
|
l->head_ = next;
|
|
return true;
|
|
}
|
|
|
|
for (auto prev = l->head_, node = l->head_->next_; node;
|
|
prev = node, node = node->next_)
|
|
if (node->data_ == data) {
|
|
prev->next_ = list_free_node_(l, node);
|
|
if (l->tail_ == node) l->tail_ = prev;
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
};
|
|
test::mock::osi_list::list_clear.body = [](list_t* l) {
|
|
CHECK(l);
|
|
for (auto node = l->head_; node;) {
|
|
node = list_free_node_(l, node);
|
|
}
|
|
l->head_ = NULL;
|
|
l->tail_ = NULL;
|
|
l->length_ = 0;
|
|
return;
|
|
};
|
|
|
|
test::mock::osi_list::list_begin.body = [](const list_t* l) {
|
|
CHECK(l);
|
|
return l->head_;
|
|
};
|
|
test::mock::osi_list::list_end.body = [](const list_t* l) {
|
|
CHECK(l);
|
|
return l->tail_;
|
|
};
|
|
test::mock::osi_list::list_next.body = [](const list_node_t* node) {
|
|
CHECK(node);
|
|
return node->next_;
|
|
};
|
|
test::mock::osi_list::list_node.body = [](const list_node_t* node) {
|
|
CHECK(node);
|
|
return node->data_;
|
|
};
|
|
|
|
test::mock::osi_fixed_queue::fixed_queue_new.body = [](size_t capacity) {
|
|
return new fixed_queue_t(capacity);
|
|
};
|
|
test::mock::osi_fixed_queue::fixed_queue_flush.body =
|
|
[](fixed_queue_t* q, fixed_queue_free_cb cb) {
|
|
if (q) {
|
|
if (cb) {
|
|
test::mock::osi_list::list_foreach(
|
|
q->list_,
|
|
[](void* data, void* cb) {
|
|
reinterpret_cast<fixed_queue_free_cb>(cb)(data);
|
|
return true;
|
|
},
|
|
reinterpret_cast<void*>(cb));
|
|
}
|
|
test::mock::osi_list::list_clear(q->list_);
|
|
}
|
|
};
|
|
test::mock::osi_fixed_queue::fixed_queue_free.body =
|
|
[](fixed_queue_t* q, fixed_queue_free_cb free_cb) {
|
|
if (q) {
|
|
test::mock::osi_fixed_queue::fixed_queue_flush(q, free_cb);
|
|
delete q->list_;
|
|
delete q;
|
|
}
|
|
};
|
|
test::mock::osi_fixed_queue::fixed_queue_enqueue.body = [](fixed_queue_t* q,
|
|
void* data) {
|
|
if (q) test::mock::osi_list::list_append(q->list_, data);
|
|
};
|
|
test::mock::osi_fixed_queue::fixed_queue_dequeue.body = [](fixed_queue_t* q) {
|
|
void* ret = nullptr;
|
|
if (q) {
|
|
ret = test::mock::osi_list::list_front(q->list_);
|
|
test::mock::osi_list::list_remove(q->list_, ret);
|
|
}
|
|
return ret;
|
|
};
|
|
|
|
test::mock::osi_fixed_queue::fixed_queue_length.body = [](fixed_queue_t* q) {
|
|
return q ? test::mock::osi_list::list_length(q->list_) : 0;
|
|
};
|
|
|
|
test::mock::osi_fixed_queue::fixed_queue_is_empty.body =
|
|
[](fixed_queue_t* q) {
|
|
return test::mock::osi_fixed_queue::fixed_queue_length(q) == 0;
|
|
};
|
|
|
|
test::mock::osi_fixed_queue::fixed_queue_capacity.body =
|
|
[](fixed_queue_t* q) { return q ? q->capacity_ : 0; };
|
|
|
|
test::mock::osi_fixed_queue::fixed_queue_try_enqueue.body =
|
|
[](fixed_queue_t* q, void* data) {
|
|
test::mock::osi_fixed_queue::fixed_queue_enqueue(q, data);
|
|
return true;
|
|
};
|
|
test::mock::osi_fixed_queue::fixed_queue_try_dequeue.body =
|
|
[](fixed_queue_t* q) {
|
|
void* ret = nullptr;
|
|
if (q && !test::mock::osi_fixed_queue::fixed_queue_is_empty(q)) {
|
|
ret = test::mock::osi_fixed_queue::fixed_queue_dequeue(q);
|
|
}
|
|
return ret;
|
|
};
|
|
test::mock::osi_fixed_queue::fixed_queue_try_peek_first.body =
|
|
[](fixed_queue_t* q) {
|
|
return (q && !test::mock::osi_list::list_is_empty(q->list_))
|
|
? test::mock::osi_list::list_front(q->list_)
|
|
: nullptr;
|
|
};
|
|
|
|
test::mock::osi_fixed_queue::fixed_queue_try_peek_last.body =
|
|
[](fixed_queue_t* q) {
|
|
return (q && !test::mock::osi_list::list_is_empty(q->list_))
|
|
? test::mock::osi_list::list_back(q->list_)
|
|
: nullptr;
|
|
};
|
|
|
|
test::mock::osi_fixed_queue::fixed_queue_get_list.body =
|
|
[](fixed_queue_t* q) { return q ? q->list_ : nullptr; };
|
|
|
|
test::mock::osi_fixed_queue::fixed_queue_try_remove_from_queue.body =
|
|
[](fixed_queue_t* q, void* data) {
|
|
// not implemented
|
|
abort();
|
|
return nullptr;
|
|
};
|
|
|
|
test::mock::osi_fixed_queue::fixed_queue_get_enqueue_fd.body =
|
|
[](const fixed_queue_t* q) {
|
|
// not implemented
|
|
abort();
|
|
return 0;
|
|
};
|
|
|
|
test::mock::osi_fixed_queue::fixed_queue_get_dequeue_fd.body =
|
|
[](const fixed_queue_t* q) {
|
|
// not implemented
|
|
abort();
|
|
return 0;
|
|
};
|
|
|
|
test::mock::osi_fixed_queue::fixed_queue_register_dequeue.body =
|
|
[](fixed_queue_t* q, reactor_t* reactor, fixed_queue_cb ready_cb,
|
|
void* context) {
|
|
// not implemented
|
|
abort();
|
|
};
|
|
test::mock::osi_fixed_queue::fixed_queue_unregister_dequeue.body =
|
|
[](fixed_queue_t* q) {
|
|
// not implemented
|
|
abort();
|
|
};
|
|
}
|
|
|
|
FakeOsi::~FakeOsi() {
|
|
test::mock::osi_alarm::alarm_free = {};
|
|
test::mock::osi_alarm::alarm_new = {};
|
|
|
|
test::mock::osi_allocator::osi_calloc = {};
|
|
test::mock::osi_allocator::osi_free = {};
|
|
test::mock::osi_allocator::osi_free_and_reset = {};
|
|
test::mock::osi_allocator::osi_malloc = {};
|
|
|
|
test::mock::osi_list::list_new = {};
|
|
test::mock::osi_list::list_free = {};
|
|
test::mock::osi_list::list_is_empty = {};
|
|
test::mock::osi_list::list_foreach = {};
|
|
test::mock::osi_list::list_contains = {};
|
|
test::mock::osi_list::list_length = {};
|
|
test::mock::osi_list::list_front = {};
|
|
test::mock::osi_list::list_back = {};
|
|
test::mock::osi_list::list_back_node = {};
|
|
test::mock::osi_list::list_insert_after = {};
|
|
test::mock::osi_list::list_prepend = {};
|
|
test::mock::osi_list::list_append = {};
|
|
test::mock::osi_list::list_remove = {};
|
|
test::mock::osi_list::list_clear = {};
|
|
test::mock::osi_list::list_begin = {};
|
|
test::mock::osi_list::list_end = {};
|
|
test::mock::osi_list::list_next = {};
|
|
test::mock::osi_list::list_node = {};
|
|
|
|
test::mock::osi_fixed_queue::fixed_queue_new = {};
|
|
test::mock::osi_fixed_queue::fixed_queue_flush = {};
|
|
test::mock::osi_fixed_queue::fixed_queue_free = {};
|
|
test::mock::osi_fixed_queue::fixed_queue_enqueue = {};
|
|
test::mock::osi_fixed_queue::fixed_queue_dequeue = {};
|
|
test::mock::osi_fixed_queue::fixed_queue_length = {};
|
|
test::mock::osi_fixed_queue::fixed_queue_is_empty = {};
|
|
test::mock::osi_fixed_queue::fixed_queue_capacity = {};
|
|
test::mock::osi_fixed_queue::fixed_queue_try_enqueue = {};
|
|
test::mock::osi_fixed_queue::fixed_queue_try_dequeue = {};
|
|
test::mock::osi_fixed_queue::fixed_queue_try_peek_first = {};
|
|
test::mock::osi_fixed_queue::fixed_queue_try_peek_last = {};
|
|
test::mock::osi_fixed_queue::fixed_queue_try_remove_from_queue = {};
|
|
test::mock::osi_fixed_queue::fixed_queue_get_list = {};
|
|
test::mock::osi_fixed_queue::fixed_queue_get_enqueue_fd = {};
|
|
test::mock::osi_fixed_queue::fixed_queue_get_dequeue_fd = {};
|
|
test::mock::osi_fixed_queue::fixed_queue_register_dequeue = {};
|
|
test::mock::osi_fixed_queue::fixed_queue_unregister_dequeue = {};
|
|
}
|
|
|
|
} // namespace fake
|
|
} // namespace test
|