Files
trail-mate/tests/hostlink/test_hostlink_tx_memory.cpp

105 lines
3.3 KiB
C++

#include "hostlink/hostlink_codec.h"
#include "hostlink/sensitive_memory.h"
#include <cassert>
#include <cstdarg>
#include <cstdlib>
#include <cstring>
#include <map>
namespace hostlink
{
constexpr uint32_t MALLOC_CAP_SPIRAM = 1, MALLOC_CAP_INTERNAL = 2, MALLOC_CAP_8BIT = 4;
constexpr int pdPASS = 1;
struct TxItem
{
uint8_t* data = nullptr;
size_t len = 0;
};
TxItem queued;
void* s_tx_queue = &queued;
using QueueHandle_t = void*;
std::map<void*, size_t> allocation_sizes;
bool full = false, ready = true, fail_allocation = false;
unsigned allocations = 0, frees = 0;
int s_session;
bool is_ready(int) { return ready; }
uint16_t next_seq() { return 17; }
void* heap_caps_malloc_prefer(size_t size, size_t count, ...)
{
assert(count == 2);
va_list args;
va_start(args, count);
assert(va_arg(args, uint32_t) == (MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT));
assert(va_arg(args, uint32_t) == (MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT));
va_end(args);
if (fail_allocation) return nullptr;
++allocations;
auto* value = std::malloc(size);
allocation_sizes[value] = size;
return value;
}
void test_free(void* value)
{
if (value)
{
const auto size = allocation_sizes.at(value);
for (size_t i = 0; i < size; ++i) assert(static_cast<uint8_t*>(value)[i] == 0);
allocation_sizes.erase(value);
++frees;
}
std::free(value);
}
int xQueueSend(void*, const TxItem* item, unsigned)
{
if (full) return 0;
queued = *item;
full = true;
return pdPASS;
}
int xQueueReceive(void*, TxItem* item, unsigned)
{
if (!full) return 0;
*item = queued;
full = false;
return pdPASS;
}
#define free test_free
#include "hostlink_tx_actual.inc"
#undef free
} // namespace hostlink
int main()
{
using namespace hostlink;
uint8_t source[kMaxFrameLen];
std::memset(source, 42, sizeof(source));
assert(enqueue_event(0x21, source, sizeof(source), false, 123));
assert(full && allocations == 1 && !frees && queued.len == kMaxFrameLen + kHeaderSize + kCrcSize);
Decoder decoder;
decoder.push(queued.data, queued.len);
Frame frame;
assert(decoder.next(frame) && frame.type == 0x21 && frame.seq == 123 && frame.payload.size() == sizeof(source) && !std::memcmp(frame.payload.data(), source, sizeof(source)));
const auto* original = queued.data;
assert(!enqueue_event(0x82, source, 1, false, 0));
assert(queued.data == original && frees == 1);
assert(enqueue_event(0x21, source, 1, true, 124));
assert(queued.data != original && frees == 2);
fail_allocation = true;
assert(!enqueue_event(0x21, source, 1, true, 0) && frees == 2);
fail_allocation = false;
ready = false;
assert(!enqueue_event(0x21, source, 1, false, 0) && allocations == 3);
ready = true;
assert(!enqueue_event(0x21, nullptr, 1, false, 0) && allocations == 3);
assert(!enqueue_event(0x21, source, kMaxFrameLen + 1, false, 0) && allocations == 3);
TxItem final;
assert(xQueueReceive(s_tx_queue, &final, 0) == pdPASS);
release_tx_item(final);
assert(!final.data && !final.len);
assert(enqueue_event(0x21, source, 96, false, 125));
ready = false;
drain_tx_queue(s_tx_queue);
assert(!full && allocations == frees);
drain_tx_queue(s_tx_queue);
drain_tx_queue(nullptr);
assert(allocations == frees);
}