C++ conversion (#80)

Converted project to C++
This commit is contained in:
Ken Van Hoeylandt
2024-11-22 20:26:08 +01:00
committed by GitHub
parent 6d80144e12
commit 85e26636a3
488 changed files with 6017 additions and 39466 deletions
+9
View File
@@ -0,0 +1,9 @@
project(tests)
set(DOCTESTINC ${PROJECT_SOURCE_DIR}/Include)
enable_testing()
add_subdirectory(TactilityCore)
add_custom_target(build-tests)
add_dependencies(build-tests TactilityCoreTests)
File diff suppressed because it is too large Load Diff
+49
View File
@@ -0,0 +1,49 @@
#include "doctest.h"
#include "Bundle.h"
using namespace tt;
TEST_CASE("boolean can be stored and retrieved") {
Bundle bundle;
bundle.putBool("key", true);
CHECK(bundle.hasBool("key"));
CHECK(bundle.getBool("key"));
bool opt_result = false;
CHECK(bundle.optBool("key", opt_result));
CHECK_EQ(opt_result, true);
}
TEST_CASE("int32 can be stored and retrieved") {
Bundle bundle;
bundle.putInt32("key", true);
CHECK(bundle.hasInt32("key"));
CHECK(bundle.getInt32("key"));
int32_t opt_result = false;
CHECK(bundle.optInt32("key", opt_result));
CHECK_EQ(opt_result, true);
}
TEST_CASE("string can be stored and retrieved") {
Bundle bundle;
bundle.putString("key", "test");
CHECK(bundle.hasString("key"));
CHECK_EQ(bundle.getString("key"), "test");
std::string opt_result;
CHECK(bundle.optString("key", opt_result));
CHECK_EQ(opt_result, "test");
}
TEST_CASE("bundle copy makes an actual copy") {
auto* original_ptr = new Bundle();
Bundle& original = *original_ptr;
original.putBool("bool", true);
original.putInt32("int32", 123);
original.putString("string", "text");
Bundle copy = original;
delete original_ptr;
CHECK_EQ(copy.getBool("bool"), true);
CHECK_EQ(copy.getInt32("int32"), 123);
CHECK_EQ(copy.getString("string"), "text");
}
+21
View File
@@ -0,0 +1,21 @@
project(TactilityCoreTests)
enable_language(C CXX ASM)
set(CMAKE_CXX_COMPILER g++)
file(GLOB_RECURSE TEST_SOURCES ${PROJECT_SOURCE_DIR}/*.cpp)
add_executable(TactilityCoreTests EXCLUDE_FROM_ALL ${TEST_SOURCES})
target_include_directories(TactilityCoreTests PRIVATE
${DOCTESTINC}
)
add_test(NAME TactilityCoreTests
COMMAND TactilityCoreTests
)
target_link_libraries(TactilityCoreTests
PUBLIC TactilityCore
freertos_kernel
)
+36
View File
@@ -0,0 +1,36 @@
#include "doctest.h"
#include "TactilityCore.h"
#include "Dispatcher.h"
using namespace tt;
void increment_callback(void* context) {
auto* counter = (uint32_t*)context;
(*counter)++;
}
TEST_CASE("dispatcher should not call callback if consume isn't called") {
Dispatcher dispatcher;
uint32_t counter = 0;
dispatcher.dispatch(&increment_callback, &counter);
delay_tick(10);
CHECK_EQ(counter, 0);
}
TEST_CASE("dispatcher should be able to dealloc when message is not consumed") {
auto* dispatcher = new Dispatcher();
uint32_t counter = 0;
dispatcher->dispatch(increment_callback, &counter);
delete dispatcher;
}
TEST_CASE("dispatcher should call callback when consume is called") {
Dispatcher dispatcher;
uint32_t counter = 0;
dispatcher.dispatch(increment_callback, &counter);
dispatcher.consume(100);
CHECK_EQ(counter, 1);
}
+58
View File
@@ -0,0 +1,58 @@
#define DOCTEST_CONFIG_IMPLEMENT
#include "doctest.h"
#include <cassert>
#include "FreeRTOS.h"
#include "task.h"
typedef struct {
int argc;
char** argv;
int result;
} TestTaskData;
void test_task(void* parameter) {
auto* data = (TestTaskData*)parameter;
doctest::Context context;
context.applyCommandLine(data->argc, data->argv);
// overrides
context.setOption("no-breaks", true); // don't break in the debugger when assertions fail
data->result = context.run();
if (context.shouldExit()) { // important - query flags (and --exit) rely on the user doing this
vTaskEndScheduler();
}
vTaskDelete(nullptr);
}
int main(int argc, char** argv) {
TestTaskData data = {
.argc = argc,
.argv = argv,
.result = 0
};
BaseType_t task_result = xTaskCreate(
test_task,
"test_task",
8192,
&data,
1,
nullptr
);
assert(task_result == pdPASS);
vTaskStartScheduler();
}
extern "C" {
// Required for FreeRTOS
void vAssertCalled(unsigned long line, const char* const file) {
__assert_fail("assert failed", file, line, "");
}
}
+86
View File
@@ -0,0 +1,86 @@
#include "doctest.h"
#include "MessageQueue.h"
using namespace tt;
TEST_CASE("message queue capacity should be correct") {
MessageQueue queue(10, 1);
uint32_t capacity = queue.getCapacity();
CHECK_EQ(capacity, 10);
}
TEST_CASE("message queue initial count should be 0") {
MessageQueue queue(10, 1);
uint32_t count = queue.getCount();
CHECK_EQ(count, 0);
}
TEST_CASE("message queue message size should be correct") {
MessageQueue queue(1, 123);
uint32_t message_size = queue.getMessageSize();
CHECK_EQ(message_size, 123);
}
TEST_CASE("message queue count should increase when message is added") {
MessageQueue queue(10, sizeof(uint32_t));
uint32_t message = 123;
queue.put(&message, 100);
uint32_t count = queue.getCount();
CHECK_EQ(count, 1);
}
TEST_CASE("message queue count should be 0 when message is added and queue is reset") {
MessageQueue queue(10, sizeof(uint32_t));
uint32_t message = 123;
queue.put(&message, 100);
queue.reset();
uint32_t count = queue.getCount();
CHECK_EQ(count, 0);
}
TEST_CASE("message queue consumption should work") {
MessageQueue queue(10, sizeof(uint32_t));
uint32_t out_message = 123;
queue.put(&out_message, 100);
uint32_t in_message = 0;
queue.get(&in_message, 100);
CHECK_EQ(in_message, 123);
}
TEST_CASE("message queue count should decrease when message is consumed") {
MessageQueue queue(10, sizeof(uint32_t));
uint32_t out_message = 123;
queue.put(&out_message, 100);
uint32_t in_message = 0;
queue.get(&in_message, 100);
uint32_t count = queue.getCount();
CHECK_EQ(count, 0);
}
TEST_CASE("message queue should make copy of data") {
// Given a number that we can later delete
MessageQueue queue(1, sizeof(int32_t));
const int32_t test_value = 123;
auto* number = new int32_t();
*number = test_value;
// When we put the number in the queue and then delete it
queue.put(number, 100);
delete number;
// We want to verify that the value was copied into the queue and retrieved properly
int32_t queue_number = 0;
CHECK_EQ(queue.get(&queue_number, 100), TtStatusOk);
CHECK_EQ(queue_number, test_value);
}
+36
View File
@@ -0,0 +1,36 @@
#include "doctest.h"
#include "TactilityCore.h"
#include "Mutex.h"
using namespace tt;
static int thread_with_mutex_parameter(void* parameter) {
auto* mutex = (Mutex*)parameter;
tt_mutex_acquire(mutex, TtWaitForever);
return 0;
}
TEST_CASE("a mutex can block a thread") {
auto* mutex = tt_mutex_alloc(MutexTypeNormal);
tt_mutex_acquire(mutex, TtWaitForever);
Thread* thread = thread_alloc_ex(
"thread",
1024,
&thread_with_mutex_parameter,
mutex
);
thread_start(thread);
delay_ms(5);
CHECK_EQ(thread_get_state(thread), ThreadStateRunning);
tt_mutex_release(mutex);
delay_ms(5);
CHECK_EQ(thread_get_state(thread), ThreadStateStopped);
thread_join(thread);
thread_free(thread);
tt_mutex_free(mutex);
}
+103
View File
@@ -0,0 +1,103 @@
#include "doctest.h"
#include "TactilityCore.h"
#include "Thread.h"
using namespace tt;
static int interruptable_thread(void* parameter) {
bool* interrupted = (bool*)parameter;
while (!*interrupted) {
delay_ms(5);
}
return 0;
}
static int immediate_return_thread(void* parameter) {
bool* has_called = (bool*)parameter;
*has_called = true;
return 0;
}
static int thread_with_return_code(void* parameter) {
int* code = (int*)parameter;
return *code;
}
TEST_CASE("when a thread is started then its callback should be called") {
bool has_called = false;
auto* thread = thread_alloc_ex(
"immediate return task",
4096,
&immediate_return_thread,
&has_called
);
CHECK(!has_called);
thread_start(thread);
thread_join(thread);
thread_free(thread);
CHECK(has_called);
}
TEST_CASE("a thread can be started and stopped") {
bool interrupted = false;
auto* thread = thread_alloc_ex(
"interruptable thread",
4096,
&interruptable_thread,
&interrupted
);
CHECK(thread);
thread_start(thread);
interrupted = true;
thread_join(thread);
thread_free(thread);
}
TEST_CASE("thread id should only be set at when thread is started") {
bool interrupted = false;
auto* thread = thread_alloc_ex(
"interruptable thread",
4096,
&interruptable_thread,
&interrupted
);
CHECK_EQ(thread_get_id(thread), nullptr);
thread_start(thread);
CHECK_NE(thread_get_id(thread), nullptr);
interrupted = true;
thread_join(thread);
CHECK_EQ(thread_get_id(thread), nullptr);
thread_free(thread);
}
TEST_CASE("thread state should be correct") {
bool interrupted = false;
auto* thread = thread_alloc_ex(
"interruptable thread",
4096,
&interruptable_thread,
&interrupted
);
CHECK_EQ(thread_get_state(thread), ThreadStateStopped);
thread_start(thread);
ThreadState state = thread_get_state(thread);
CHECK((state == ThreadStateStarting || state == ThreadStateRunning));
interrupted = true;
thread_join(thread);
CHECK_EQ(thread_get_state(thread), ThreadStateStopped);
thread_free(thread);
}
TEST_CASE("thread id should only be set at when thread is started") {
int code = 123;
auto* thread = thread_alloc_ex(
"return code",
4096,
&thread_with_return_code,
&code
);
thread_start(thread);
thread_join(thread);
CHECK_EQ(thread_get_return_code(thread), code);
thread_free(thread);
}
+64
View File
@@ -0,0 +1,64 @@
#include "doctest.h"
#include "TactilityCore.h"
#include "Timer.h"
using namespace tt;
void* timer_callback_context = NULL;
static void timer_callback_with_context(void* context) {
timer_callback_context = context;
}
static void timer_callback_with_counter(void* context) {
int* int_ptr = (int*)context;
(*int_ptr)++;
}
TEST_CASE("a timer passes the context correctly") {
int foo = 1;
auto* timer = timer_alloc(&timer_callback_with_context, TimerTypeOnce, &foo);
timer_start(timer, 1);
delay_tick(10);
timer_stop(timer);
timer_free(timer);
CHECK_EQ(timer_callback_context, &foo);
}
TEST_CASE("TimerTypePeriodic timers can be stopped and restarted") {
int counter = 0;
auto* timer = timer_alloc(&timer_callback_with_counter, TimerTypePeriodic, &counter);
timer_start(timer, 1);
delay_tick(10);
timer_stop(timer);
delay_tick(10);
timer_stop(timer);
timer_free(timer);
CHECK_GE(counter, 2);
}
TEST_CASE("TimerTypePeriodic calls the callback periodically") {
int counter = 0;
int ticks_to_run = 10;
auto* timer = timer_alloc(&timer_callback_with_counter, TimerTypePeriodic, &counter);
timer_start(timer, 1);
delay_tick(ticks_to_run);
timer_stop(timer);
timer_free(timer);
CHECK_EQ(counter, ticks_to_run);
}
TEST_CASE("restarting TimerTypeOnce timers has no effect") {
int counter = 0;
auto* timer = timer_alloc(&timer_callback_with_counter, TimerTypeOnce, &counter);
timer_start(timer, 1);
delay_tick(10);
timer_stop(timer);
delay_tick(10);
timer_stop(timer);
timer_free(timer);
CHECK_EQ(counter, 1);
}