From d418241f95d249cdacf2ee01567fee267be9d701 Mon Sep 17 00:00:00 2001 From: falsycat Date: Thu, 31 Dec 2020 00:00:00 +0000 Subject: [PATCH] Adds a test and CMake function. --- .gitignore | 1 - CMakeLists.txt | 22 +++++++++ TODO.TXT | 2 +- test/CMakeLists.txt | 18 ++++++++ test/main.c | 109 ++++++++++++++++++++++++++++++++++++++++++++ test/user.biner | 49 ++++++++++++++++++++ 6 files changed, 199 insertions(+), 2 deletions(-) create mode 100644 test/CMakeLists.txt create mode 100644 test/main.c create mode 100644 test/user.biner diff --git a/.gitignore b/.gitignore index 87f2b0a..056d00e 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,2 @@ *.swp /.build -/test diff --git a/CMakeLists.txt b/CMakeLists.txt index 9c7d49a..e7a45cb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -34,3 +34,25 @@ target_sources(biner c/zone.h ) target_include_directories(biner PRIVATE . ${CMAKE_CURRENT_BINARY_DIR}) + +function(target_biner_sources target) + cmake_parse_arguments("FUNC" "" "OUTPUT" "SOURCES" ${ARGN}) + file(MAKE_DIRECTORY "${FUNC_OUTPUT}") + + foreach(path ${FUNC_SOURCES}) + get_filename_component(basename "${path}" NAME) + set(in "${CMAKE_CURRENT_SOURCE_DIR}/${path}") + set(out "${FUNC_OUTPUT}/${basename}.h") + add_custom_command( + OUTPUT "${out}" + COMMAND $ < "${in}" > "${out}" + DEPENDS "${in}" biner + COMMENT "transpiling ${in} to C" + VERBATIM) + target_sources(${target} PRIVATE "${out}") + endforeach() +endfunction() + +if (BUILD_TESTING) + add_subdirectory(test) +endif() diff --git a/TODO.TXT b/TODO.TXT index 2a8e904..8d4108e 100644 --- a/TODO.TXT +++ b/TODO.TXT @@ -10,7 +10,7 @@ X conditional switching support X union support X C transpiler for unpacking X C transpiler for packing - setup tests +X setup tests handling of overflown or negative expression add bitmanip operators release 1.0.0 diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt new file mode 100644 index 0000000..baedefc --- /dev/null +++ b/test/CMakeLists.txt @@ -0,0 +1,18 @@ +add_executable(biner-test) +target_sources(biner-test + PRIVATE + main.c +) +target_biner_sources(biner-test + OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/generated + SOURCES + user.biner +) +target_include_directories(biner-test + PRIVATE + ${CMAKE_CURRENT_BINARY_DIR} +) +add_test( + NAME biner-test + COMMAND $ +) diff --git a/test/main.c b/test/main.c new file mode 100644 index 0000000..0fea754 --- /dev/null +++ b/test/main.c @@ -0,0 +1,109 @@ +#undef NDEBUG + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../c/pack.h" +#include "../c/unpack.h" +#include "../c/zone.h" + +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wpedantic" +#include "generated/user.biner.h" +#pragma GCC diagnostic pop + +static inline void print_user_(const user_t* u) { + assert(u != NULL); + + const char* sex = + u->sex == SEX_MALE? "male": + u->sex == SEX_FEMALE? "female": + u->sex == SEX_CAT? "cat": + "unknown"; + const char* role = + u->role == ROLE_TEACHER? "teacher": + u->role == ROLE_STUDENT? "student": + "unknown"; + + printf("name: %.*s\n", (int) u->name.len, u->name.ptr); + printf("age: %" PRIu8 "\n", u->age); + printf("sex: %s\n", sex); + printf("role: %s\n", role); + + printf("properties:\n"); + for (size_t i = 0; i < u->property_count; ++i) { + printf(" %.*s: %.*s\n", + (int) u->properties[i].key.len, u->properties[i].key.ptr, + (int) u->properties[i].value.len, u->properties[i].value.ptr); + } + + switch (u->role) { + case ROLE_TEACHER: + printf("salary: %" PRIu32 "\n", u->teacher.salary); + printf("payday: %" PRIu8 "/%" PRIu8 "\n", + u->teacher.payday.mon, u->teacher.payday.day); + break; + case ROLE_STUDENT: + printf("scores:\n"); + for (size_t i = 0; i < 10; ++i) { + printf(" - %" PRIu8 "\n", u->student.scores[i]); + } + printf("absents: %" PRIu8 "\n", u->student.absents); + break; + } +} + +int main(void) { +# define str_(v) { .ptr = (uint8_t*) (v), .len = strlen(v), } + user_t src = { + .name = str_("neko"), + .age = 4, + .sex = SEX_CAT, + .role = ROLE_STUDENT, + + .property_count = 2, + .properties = (strpair_t[]) { + { .key = str_("like"), .value = str_("rat"), }, + { .key = str_("hate"), .value = str_("dog"), }, + }, + + .student = { + .scores = { 100, 90, 80, 70, 60, 50, 40, 30, 20, 10, }, + .absents = 1, + }, + }; +# undef str_ + + user_pack_context_t pack_ctx = {0}; + user_pack_context_t unpack_ctx = {0}; + user_t dst = {0}; + + size_t b = 0; + bool completed = false; + while (!completed) { + uint8_t c; + completed = user_pack(&pack_ctx, &src, &c); + if (user_unpack(&unpack_ctx, &dst, c) != completed) { + fprintf(stderr, "fail at the %zu byte: ", b); + if (completed) { + fprintf(stderr, "pack function finsihed but unpack not\n"); + } else { + fprintf(stderr, "unpack function finsihed but pack not\n"); + } + return EXIT_FAILURE; + } + ++b; + } + + printf("[src]\n"); + print_user_(&src); + printf("[dst]\n"); + print_user_(&dst); + return EXIT_SUCCESS; +} diff --git a/test/user.biner b/test/user.biner new file mode 100644 index 0000000..dd8e9d8 --- /dev/null +++ b/test/user.biner @@ -0,0 +1,49 @@ +struct string_t { + lu64 len; + lu8[len] ptr; +}; +struct strpair_t { + string_t key; + string_t value; +}; + +enum sex_t { + SEX_MALE = 0x0, + SEX_FEMALE = 0x1, + SEX_CAT = 0x2, +}; + +enum role_t { + ROLE_TEACHER = 0x0, + ROLE_STUDENT = 0x1, +}; + +struct date_t { + lu8 mon; + lu8 day; +}; + +struct teacher_t { + lu32 salary; + date_t payday; +}; + +struct student_t { + lu8[10] scores; + lu8 absents; +}; + +struct user_t { + string_t name; + lu8 age; + lu8 sex; /* sex_t */ + lu8 role; /* role_t */ + + lu16 property_count; + strpair_t[property_count] properties; + + union { + (role == ROLE_TEACHER) teacher_t teacher; + (role == ROLE_STUDENT) student_t student; + }; +};