From 33411bb47171d824368d543d68a2c9088431af09 Mon Sep 17 00:00:00 2001 From: NValsted Date: Mon, 1 Apr 2024 03:43:44 +0200 Subject: [PATCH] Add test environment and init CI --- .github/workflows/run-tests.yml | 43 +++++++++++++++++++++++++++++++++ Dockerfile | 37 ++++++++++++++++++++++++++++ README.md | 14 +++++++++-- meson.build | 20 ++++++++++++++- tests/test_proc_pack.c | 31 ++++++++++++++++++++++++ 5 files changed, 142 insertions(+), 3 deletions(-) create mode 100644 .github/workflows/run-tests.yml create mode 100644 Dockerfile create mode 100644 tests/test_proc_pack.c diff --git a/.github/workflows/run-tests.yml b/.github/workflows/run-tests.yml new file mode 100644 index 0000000..05c6ef6 --- /dev/null +++ b/.github/workflows/run-tests.yml @@ -0,0 +1,43 @@ +name: Tests + +on: + push: + branches: [ main ] + pull_request: + branches: [ main ] + +jobs: + build: + runs-on: ubuntu-latest + + steps: + - name: Checkout code + uses: actions/checkout@v2 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v1 + + - name: Cache Docker layers + uses: actions/cache@v2 + with: + path: /tmp/.buildx-cache + key: ${{ runner.os }}-buildx-${{ github.sha }} + restore-keys: | + ${{ runner.os }}-buildx- + + - name: Build Docker image + uses: docker/build-push-action@v2 + with: + context: . + load: true + push: false + tags: csp_proc:latest + cache-from: type=local,src=/tmp/.buildx-cache + cache-to: type=local,dest=/tmp/.buildx-cache + + - name: Check code formatting + run: | + docker run --rm -v "$(pwd):/csp_proc" -v "$(pwd)/.git:/csp_proc/.git" csp_proc:latest bash -c "find . -name '*.cpp' -or -name '*.hpp' -or -name '*.c' -or -name '*.c' -or -name '*.h' | xargs clang-format -style=file -i && git diff --exit-code" + + - name: Run tests + run: docker run --rm csp_proc:latest meson test -C builddir diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..915a902 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,37 @@ +# Stage 1: clang-format 17.x +FROM ubuntu:22.04 AS clang-format-builder + +RUN apt-get update && apt-get install -y \ + wget \ + xz-utils + +RUN wget -O clang-format.tar.xz https://github.com/llvm/llvm-project/releases/download/llvmorg-17.0.6/clang+llvm-17.0.6-x86_64-linux-gnu-ubuntu-22.04.tar.xz +RUN tar -xf clang-format.tar.xz clang+llvm-17.0.6-x86_64-linux-gnu-ubuntu-22.04/bin/clang-format && \ + mv clang+llvm-17.0.6-x86_64-linux-gnu-ubuntu-22.04/bin/clang-format ./clang-format && \ + chmod +x clang-format + +# Stage 2: Build csp_proc and dependencies (including test dependencies) +FROM ubuntu:22.04 + +RUN apt-get update && apt-get install -y \ + python3 \ + python3-pip \ + ninja-build \ + gcc \ + g++ \ + git \ + meson \ + libcriterion-dev + +COPY --from=clang-format-builder /clang-format /usr/bin/ + +WORKDIR /csp_proc/ +RUN git clone https://github.com/spaceinventor/libcsp.git lib/csp +RUN git clone https://github.com/spaceinventor/libparam.git lib/param +RUN git clone https://github.com/spaceinventor/slash.git lib/slash +RUN git clone https://github.com/FreeRTOS/FreeRTOS-Kernel.git lib/freertos + +COPY . /csp_proc/ + +RUN meson setup builddir \ + && meson compile -C builddir diff --git a/README.md b/README.md index 5e50d4b..7f2054f 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,14 @@ # csp_proc -Lightweight, programmable procedures with a libcsp- and libparam-native runtime. This library has a relatively small footprint suitable for microcontrollers, requiring no external libraries other than libcsp and libparam themselves. +![Tests](https://github.com/discosat/csp_proc/actions/workflows/run-tests.yml/badge.svg) -This provides remote control over coordination between nodes in a CSP network, essentially exposing the network as single programmable unit. +Lightweight, programmable procedures with a libcsp- and libparam-native runtime. This provides remote control over coordination between nodes in a CSP network, essentially exposing the network as single programmable unit. + +The library has a relatively small footprint suitable for microcontrollers, requiring no external libraries other than libcsp and libparam themselves for the core of the library. However, currently, the only runtime implementation relies on FreeRTOS. + +# Build environment +Refer to the Dockerfile for a reference build environment, including code formatter. It can be brought up like so: + +```bash +docker build -t csp_proc . +docker run --rm -v "$(pwd):/csp_proc" -t csp_proc +``` diff --git a/meson.build b/meson.build index 15cc404..0330ff6 100644 --- a/meson.build +++ b/meson.build @@ -1,4 +1,8 @@ -project('csp_proc', 'c') +project('csp_proc', 'c', subproject_dir: 'lib', default_options: [ + 'c_std=gnu11', + 'b_lto=false', + 'default_library=static', +]) csp_dep = dependency('csp', fallback : ['csp', 'csp_dep']) param_dep = dependency('param', fallback : ['param', 'param_dep']) @@ -76,3 +80,17 @@ csp_proc_lib = static_library('csp_proc', ) csp_proc_dep = declare_dependency(include_directories : csp_proc_inc, link_with : csp_proc_lib) + + +# Tests +criterion_dep = dependency('criterion', required : false) +if not criterion_dep.found() + error('Criterion not found (required for tests)') +endif + +test_src = files([ + 'tests/test_proc_pack.c', +]) + +run_tests_executable = executable('run_tests', test_src, dependencies : [criterion_dep, csp_proc_dep, csp_dep, param_dep, slash_dep, freertos_dep]) +test('run_tests', run_tests_executable) diff --git a/tests/test_proc_pack.c b/tests/test_proc_pack.c new file mode 100644 index 0000000..ca3489b --- /dev/null +++ b/tests/test_proc_pack.c @@ -0,0 +1,31 @@ +#include + +#include +#include +#include + +Test(proc_pack_unpack, test_pack_unpack) { + proc_t original_proc; + csp_packet_t packet; + + original_proc.instruction_count = 1; + original_proc.instructions[0].node = 1; + original_proc.instructions[0].type = PROC_BLOCK; + original_proc.instructions[0].instruction.block.param_a = "param_a"; + original_proc.instructions[0].instruction.block.op = OP_EQ; + original_proc.instructions[0].instruction.block.param_b = "param_b"; + + int pack_result = pack_proc_into_csp_packet(&original_proc, &packet); + cr_assert(pack_result == 0, "Packing failed"); + + proc_t new_proc; + int unpack_result = unpack_proc_from_csp_packet(&new_proc, &packet); + cr_assert(unpack_result == 0, "Unpacking failed"); + + cr_assert(original_proc.instruction_count == new_proc.instruction_count, "Instruction counts do not match"); + cr_assert(original_proc.instructions[0].node == new_proc.instructions[0].node, "Nodes do not match"); + cr_assert(original_proc.instructions[0].type == new_proc.instructions[0].type, "Types do not match"); + cr_assert(strcmp(original_proc.instructions[0].instruction.block.param_a, new_proc.instructions[0].instruction.block.param_a) == 0, "param_a does not match"); + cr_assert(original_proc.instructions[0].instruction.block.op == new_proc.instructions[0].instruction.block.op, "op does not match"); + cr_assert(strcmp(original_proc.instructions[0].instruction.block.param_b, new_proc.instructions[0].instruction.block.param_b) == 0, "param_b does not match"); +}