From 11f253f4196d7352c2c9a9bf90badfd7c272cc94 Mon Sep 17 00:00:00 2001 From: Paul Nykiel Date: Mon, 30 Jan 2023 19:50:18 +0100 Subject: [PATCH 01/11] Added Message decoding requirements --- MessageDecoding.c | 71 ++++++++++++++++-------------- MessageDecoding.h | 110 +++++++++++++++++++++++++++++++++++++++------- 2 files changed, 132 insertions(+), 49 deletions(-) diff --git a/MessageDecoding.c b/MessageDecoding.c index d728f98..3039f8d 100644 --- a/MessageDecoding.c +++ b/MessageDecoding.c @@ -9,59 +9,62 @@ #include "MessageDefs.h" -void message_decoding_init(message_decoding_data_t *decoding_data, uint8_t message_id) { - decoding_data->decodingState = DECODING_INITIAL; - decoding_data->len = 0; - decoding_data->id = message_id; +void message_decoding_init(message_decoding_data_t *decoding_data, uint8_t message_id, const pb_msgdesc_t *fields) { + decoding_data->_decodingState = DECODING_INITIAL; + decoding_data->_len = 0; + decoding_data->_id = message_id; + decoding_data->_fields = fields; } -bool message_decoding_decode(message_decoding_data_t *decoding_data, uint8_t data, const pb_msgdesc_t *fields, - void *message) { - switch (decoding_data->decodingState) { +bool message_decoding_decode(message_decoding_data_t *decoding_data, uint8_t data, void *message) { + switch (decoding_data->_decodingState) { case DECODING_INITIAL: if (data == END_BYTE) { - decoding_data->decodingState = DECODING_END_FOUND; + decoding_data->_decodingState = DECODING_INITIAL_END_FOUND; } break; - case DECODING_END_FOUND: + case DECODING_INITIAL_END_FOUND: if (data == START_BYTE) { - decoding_data->decodingState = DECODING_FIRST_FOUND; - if (decoding_data->len > 0) { - decoding_data->len -= 1; - - pb_istream_t istream = pb_istream_from_buffer(decoding_data->buf, decoding_data->len); - pb_decode(&istream, fields, message); - - decoding_data->len = 0; - return true; - } + decoding_data->_decodingState = DECODING_START_FOUND; } else { - if (decoding_data->len == 0) { - decoding_data->decodingState = DECODING_INITIAL; - } else { - decoding_data->decodingState = DECODING_IN_DATA; - decoding_data->buf[decoding_data->len] = data; - decoding_data->len += 1; - } + decoding_data->_decodingState = DECODING_INITIAL; } break; - case DECODING_FIRST_FOUND: - if (data == decoding_data->id) { - decoding_data->decodingState = DECODING_IN_DATA; + case DECODING_START_FOUND: + if (data == decoding_data->_id) { + decoding_data->_decodingState = DECODING_IN_DATA; + decoding_data->_len = 0; } else { - decoding_data->decodingState = DECODING_IN_WRONG_DATA; + decoding_data->_decodingState = DECODING_IN_WRONG_DATA; } break; case DECODING_IN_DATA: if (data == END_BYTE) { - decoding_data->decodingState = DECODING_END_FOUND; + decoding_data->_decodingState = DECODING_IN_DATA_END_FOUND; + } + decoding_data->_buf[decoding_data->_len] = data; + decoding_data->_len += 1; + break; + case DECODING_IN_DATA_END_FOUND: + if (data == START_BYTE) { + decoding_data->_decodingState = DECODING_START_FOUND; + pb_istream_t istream = pb_istream_from_buffer(decoding_data->_buf, decoding_data->_len - 1); + pb_decode(&istream, decoding_data->_fields, message); + return true; + } else { + decoding_data->_decodingState = DECODING_IN_DATA; } - decoding_data->buf[decoding_data->len] = data; - decoding_data->len += 1; break; case DECODING_IN_WRONG_DATA: if (data == END_BYTE) { - decoding_data->decodingState = DECODING_END_FOUND; + decoding_data->_decodingState = DECODING_IN_WRONG_DATA_END_FOUND; + } + break; + case DECODING_IN_WRONG_DATA_END_FOUND: + if (data == START_BYTE) { + decoding_data->_decodingState = DECODING_START_FOUND; + } else { + decoding_data->_decodingState = DECODING_IN_WRONG_DATA; } break; } diff --git a/MessageDecoding.h b/MessageDecoding.h index 284c595..35f0dc5 100644 --- a/MessageDecoding.h +++ b/MessageDecoding.h @@ -24,21 +24,24 @@ * Internal state of the decoder, */ typedef enum { - DECODING_INITIAL, ///< Initial state, no data received - DECODING_END_FOUND, ///< End byte found, waiting for start byte - DECODING_FIRST_FOUND, ///< Start byte received, waiting for ID - DECODING_IN_DATA, ///< Matching ID byte received, waiting for data or end byte - DECODING_IN_WRONG_DATA ///< Other ID byte received, waiting for data or end byte + DECODING_INITIAL, ///< Initial state, no data received + DECODING_INITIAL_END_FOUND, ///< End found but, no data received + DECODING_START_FOUND, ///< Start byte received, waiting for ID + DECODING_IN_DATA, ///< Matching ID byte received, waiting for data or end byte + DECODING_IN_WRONG_DATA, ///< Other ID byte received, waiting for data or end byte + DECODING_IN_DATA_END_FOUND, ///< End byte found, currently in correct package + DECODING_IN_WRONG_DATA_END_FOUND, ///< End byte found, currently in wrong package } message_decoding_state_t; /** * All internal data of the decoder. */ typedef struct { - uint8_t id; ///< The ID of the message to be received. - message_decoding_state_t decodingState; ///< The state of the decoder - uint8_t len; ///< The length of the received data (excluding start and ID) - uint8_t buf[DECODING_BUF_SIZE]; ///< The buffer for the data + uint8_t _id; ///< The ID of the message to be received. + const pb_msgdesc_t *_fields; ///< Protobuf message description + message_decoding_state_t _decodingState; ///< The state of the decoder + uint8_t _len; ///< The length of the received data (excluding start and ID) + uint8_t _buf[DECODING_BUF_SIZE]; ///< The buffer for the data } message_decoding_data_t; #ifdef __cplusplus @@ -46,23 +49,100 @@ extern "C" { #endif /** - * Initialize the internal state of the decoder. + * @brief Initialize the internal state of the decoder. + * + * This function performs the following tasks: + * * Set the internal variable "ID" to the argument message_id + * * Set the internal variable "fields" to the argument "fields" + * * Initialize decoding data such that the internal state machine is in the init state + * * @param decoding_data the state to initialize * @param message_id id of the message to be received + * @param fields the description of the protobuf-message */ -void message_decoding_init(message_decoding_data_t *decoding_data, uint8_t message_id); +void message_decoding_init(message_decoding_data_t *decoding_data, uint8_t message_id, const pb_msgdesc_t *fields); /** - * Decode a message from a datastream. + * @brief Decode a message from a datastream. + * + * The function performs the following tasks: + * * Transition the internal state machine with the input "data" in accordance to the following state machine: + * \dot + * digraph { + * INITIAL -> INITIAL_END_FOUND [ + * label = "data=0xF0"; + * ] + * + * INITIAL -> INITIAL [ + * label = "otherwise"; + * ] + * + * INITIAL_END_FOUND -> INITIAL [ + * label = "otherwise"; + * ] + * + * INITIAL_END_FOUND -> START_FOUND [ + * label = "data=0x0F"; + * ] + * + * IN_DATA_END_FOUND -> IN_DATA [ + * label = "otherwise"; + * ] + * + * IN_DATA_END_FOUND -> START_FOUND [ + * label = "data=0x0F/\nPublish data"; + * ] + * + * START_FOUND -> IN_DATA [ + * label = "data=ID/\nInit buffer"; + * ] + * + * IN_DATA -> IN_DATA [ + * label = "otherwise/\nFill buffer"; + * ] + * + * IN_DATA -> IN_DATA_END_FOUND [ + * label = "data=0xF0/\nFill buffer"; + * ] + * + * START_FOUND -> IN_WRONG_DATA [ + * label = "otherwise"; + * ] + * + * IN_WRONG_DATA_END_FOUND -> IN_WRONG_DATA [ + * label = "otherwise"; + * ] + * + * IN_WRONG_DATA_END_FOUND -> START_FOUND [ + * label = "data=0x0F"; + * ] + * + * IN_WRONG_DATA -> IN_WRONG_DATA [ + * label = "otherwise"; + * ] + * + * IN_WRONG_DATA -> IN_WRONG_DATA_END_FOUND [ + * label = "data=0xF0"; + * ] + * } + * \enddot + * * with the following actions: + * * **Init buffer**: Clear the internal buffer to contain no items + * * **Fill buffer**: Append "data" to the internal buffer + * * **Publish data**: Performs the following operations: + * * Remove the last (latest) element (which is the end byte) from the buffer + * * Prepare the buffer for protobuf (::pb_istream_from_buffer) + * * Set "message" to the decoded message (::pb_decode) + * * Return true + * * if the **Publish data** was not taken, return false + * * @param decoding_data the internal state of the decoder * @param data the new byte used for decoding - * @param fields the description of the protobuf-message * @param message out-parameter: set to the message if a complete message was received * @return true if a complete message was received, otherwise false * @return */ -bool message_decoding_decode(message_decoding_data_t *decoding_data, uint8_t data, const pb_msgdesc_t *fields, - void *message); +bool message_decoding_decode(message_decoding_data_t *decoding_data, uint8_t data, void *message); #ifdef __cplusplus } From 8e77636813a1683f9723a3792f0636dfd1a38f0e Mon Sep 17 00:00:00 2001 From: Paul Nykiel Date: Wed, 1 Feb 2023 16:38:19 +0100 Subject: [PATCH 02/11] Cleanup of requirements and decoding state machine --- MessageDecoding.c | 18 +++--------------- MessageDecoding.h | 37 ++++++++++--------------------------- MessageEncoding.c | 4 ++-- MessageEncoding.h | 19 ++++++++++++++++--- 4 files changed, 31 insertions(+), 47 deletions(-) diff --git a/MessageDecoding.c b/MessageDecoding.c index 3039f8d..146ee00 100644 --- a/MessageDecoding.c +++ b/MessageDecoding.c @@ -20,10 +20,10 @@ bool message_decoding_decode(message_decoding_data_t *decoding_data, uint8_t dat switch (decoding_data->_decodingState) { case DECODING_INITIAL: if (data == END_BYTE) { - decoding_data->_decodingState = DECODING_INITIAL_END_FOUND; + decoding_data->_decodingState = DECODING_END_FOUND; } break; - case DECODING_INITIAL_END_FOUND: + case DECODING_END_FOUND: if (data == START_BYTE) { decoding_data->_decodingState = DECODING_START_FOUND; } else { @@ -35,7 +35,7 @@ bool message_decoding_decode(message_decoding_data_t *decoding_data, uint8_t dat decoding_data->_decodingState = DECODING_IN_DATA; decoding_data->_len = 0; } else { - decoding_data->_decodingState = DECODING_IN_WRONG_DATA; + decoding_data->_decodingState = DECODING_INITIAL; } break; case DECODING_IN_DATA: @@ -55,18 +55,6 @@ bool message_decoding_decode(message_decoding_data_t *decoding_data, uint8_t dat decoding_data->_decodingState = DECODING_IN_DATA; } break; - case DECODING_IN_WRONG_DATA: - if (data == END_BYTE) { - decoding_data->_decodingState = DECODING_IN_WRONG_DATA_END_FOUND; - } - break; - case DECODING_IN_WRONG_DATA_END_FOUND: - if (data == START_BYTE) { - decoding_data->_decodingState = DECODING_START_FOUND; - } else { - decoding_data->_decodingState = DECODING_IN_WRONG_DATA; - } - break; } return false; } diff --git a/MessageDecoding.h b/MessageDecoding.h index 35f0dc5..cf9385c 100644 --- a/MessageDecoding.h +++ b/MessageDecoding.h @@ -24,13 +24,11 @@ * Internal state of the decoder, */ typedef enum { - DECODING_INITIAL, ///< Initial state, no data received - DECODING_INITIAL_END_FOUND, ///< End found but, no data received - DECODING_START_FOUND, ///< Start byte received, waiting for ID - DECODING_IN_DATA, ///< Matching ID byte received, waiting for data or end byte - DECODING_IN_WRONG_DATA, ///< Other ID byte received, waiting for data or end byte - DECODING_IN_DATA_END_FOUND, ///< End byte found, currently in correct package - DECODING_IN_WRONG_DATA_END_FOUND, ///< End byte found, currently in wrong package + DECODING_INITIAL, ///< Initial state, no data received + DECODING_END_FOUND, ///< End found, not in package + DECODING_START_FOUND, ///< Start byte received, waiting for ID + DECODING_IN_DATA, ///< Matching ID byte received, waiting for data or end byte + DECODING_IN_DATA_END_FOUND, ///< End byte found, currently in correct package } message_decoding_state_t; /** @@ -69,7 +67,8 @@ void message_decoding_init(message_decoding_data_t *decoding_data, uint8_t messa * * Transition the internal state machine with the input "data" in accordance to the following state machine: * \dot * digraph { - * INITIAL -> INITIAL_END_FOUND [ + * rankdir = "LR"; + * INITIAL -> END_FOUND [ * label = "data=0xF0"; * ] * @@ -77,11 +76,11 @@ void message_decoding_init(message_decoding_data_t *decoding_data, uint8_t messa * label = "otherwise"; * ] * - * INITIAL_END_FOUND -> INITIAL [ + * END_FOUND -> INITIAL [ * label = "otherwise"; * ] * - * INITIAL_END_FOUND -> START_FOUND [ + * END_FOUND -> START_FOUND [ * label = "data=0x0F"; * ] * @@ -105,25 +104,9 @@ void message_decoding_init(message_decoding_data_t *decoding_data, uint8_t messa * label = "data=0xF0/\nFill buffer"; * ] * - * START_FOUND -> IN_WRONG_DATA [ + * START_FOUND -> INITIAL [ * label = "otherwise"; * ] - * - * IN_WRONG_DATA_END_FOUND -> IN_WRONG_DATA [ - * label = "otherwise"; - * ] - * - * IN_WRONG_DATA_END_FOUND -> START_FOUND [ - * label = "data=0x0F"; - * ] - * - * IN_WRONG_DATA -> IN_WRONG_DATA [ - * label = "otherwise"; - * ] - * - * IN_WRONG_DATA -> IN_WRONG_DATA_END_FOUND [ - * label = "data=0xF0"; - * ] * } * \enddot * * with the following actions: diff --git a/MessageEncoding.c b/MessageEncoding.c index d959e1f..2fefe46 100644 --- a/MessageEncoding.c +++ b/MessageEncoding.c @@ -9,11 +9,11 @@ #include "MessageDefs.h" -uint16_t message_encode(uint8_t *buf, uint16_t size, const pb_msgdesc_t *fields, const void *message, uint8_t id) { +uint16_t message_encode(uint8_t *buf, uint16_t size, const pb_msgdesc_t *fields, const void *message, uint8_t message_id) { pb_ostream_t ostream = pb_ostream_from_buffer(buf + 2, size - 3); pb_encode(&ostream, fields, message); buf[0] = START_BYTE; - buf[1] = id; + buf[1] = message_id; buf[ostream.bytes_written + 2] = END_BYTE; return ostream.bytes_written + 3; } diff --git a/MessageEncoding.h b/MessageEncoding.h index c311bce..9fe5919 100644 --- a/MessageEncoding.h +++ b/MessageEncoding.h @@ -16,15 +16,28 @@ extern "C" { #endif /** - * Encode a message + * @brief Encode a message. + * + * This function encodes the data into buf according to the following frame format: + * | Byte | Description | Value | + * | --- | --- | --- | + * | 1 | Start byte | 0x0F | + * | 2 | ID byte | Value of the argument "message_id" | + * | 3..3+N | Protobuf-Payload | Result of pb_encode with the provided fields and message | + * | 4+N | End byte | 0xF0 | + * + * And returns the length of the encoded frame (4+N). + * + * @warning Buffer sizes are not checked * @param buf the buffer to write to needs to be at least the size of the message + 3 * @param size the size of the buffer * @param fields the protobuf field description * @param message a pointer to the message to encode - * @param id the message if of the message + * @param message_id the message if of the message * @return the size of the encoded message */ -uint16_t message_encode(uint8_t *buf, uint16_t size, const pb_msgdesc_t *fields, const void *message, uint8_t id); +uint16_t message_encode(uint8_t *buf, uint16_t size, const pb_msgdesc_t *fields, const void *message, + uint8_t message_id); #ifdef __cplusplus } From 11e9a8cb9fb9b08a91da279063869b6433ec02ca Mon Sep 17 00:00:00 2001 From: Paul Nykiel Date: Thu, 2 Feb 2023 18:46:08 +0100 Subject: [PATCH 03/11] Added nanopb tests --- .github/workflows/low_level_tests.yml | 50 +++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) create mode 100644 .github/workflows/low_level_tests.yml diff --git a/.github/workflows/low_level_tests.yml b/.github/workflows/low_level_tests.yml new file mode 100644 index 0000000..cf103af --- /dev/null +++ b/.github/workflows/low_level_tests.yml @@ -0,0 +1,50 @@ +name: LowLevelTests +on: [ push ] + +jobs: + Run-Tests: + name: Run Tests + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + compiler: [ { cc: gcc-10, cxx: g++-10 }, + { cc: gcc-11, cxx: g++-11 }, + { cc: clang-11, cxx: clang++-11 }, + { cc: clang-12, cxx: clang++-12 }, + { cc: clang-13, cxx: clang++-13 }, + { cc: clang-14, cxx: clang++-14 }, + #{ cc: clang-15, cxx: clang++-15 }, + { cc: clang-16, cxx: clang++-16 } ] + build: [ Release, Debug ] + env: + CC: ${{ matrix.compiler.cc }} + CXX: ${{ matrix.compiler.cxx }} + steps: + - uses: actions/checkout@v2 + with: + submodules: recursive + repository: https://github.com/nanopb/nanopb.git + - name: Install dependencies + run: | + # Taken from https://apt.llvm.org/ + wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | sudo apt-key add - + sudo add-apt-repository "deb http://apt.llvm.org/jammy/ llvm-toolchain-jammy main" + sudo add-apt-repository "deb-src http://apt.llvm.org/jammy/ llvm-toolchain-jammy main" + sudo apt-get update + sudo apt-get install -y g++-9 g++-10 g++-11 protobuf-compiler valgrind python3-protobuf clang-* scons lcov + - name: Run tests + run: | + scons + mkdir build/coverage + lcov --base-directory . --directory build/ -c -o build/coverage/nanopb.info + lcov -r build/coverage/nanopb.info '*tests*' -o build/coverage/nanopb.info + genhtml -o build/coverage build/coverage/nanopb.info + - uses: actions/upload-artifact@v3 + with: + name: RunResults + path: build/Tests/LowLevel + - uses: actions/upload-artifact@v3 + with: + name: ${{ matrix.compiler.cc }} + path: build/Tests/LowLevel From 7e4c9a84d5b8d31d9f5c52906d8973184a98a403 Mon Sep 17 00:00:00 2001 From: Paul Nykiel Date: Thu, 2 Feb 2023 18:47:35 +0100 Subject: [PATCH 04/11] Maybe fixed CI --- .github/workflows/low_level_tests.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/low_level_tests.yml b/.github/workflows/low_level_tests.yml index cf103af..e832a5b 100644 --- a/.github/workflows/low_level_tests.yml +++ b/.github/workflows/low_level_tests.yml @@ -3,7 +3,7 @@ on: [ push ] jobs: Run-Tests: - name: Run Tests + name: NanoPB Tests runs-on: ubuntu-latest strategy: fail-fast: false @@ -24,7 +24,7 @@ jobs: - uses: actions/checkout@v2 with: submodules: recursive - repository: https://github.com/nanopb/nanopb.git + repository: nanopb/nanopb - name: Install dependencies run: | # Taken from https://apt.llvm.org/ From 08ddff4965c6cde468f126758419aebfd43dc5c5 Mon Sep 17 00:00:00 2001 From: Paul Nykiel Date: Thu, 2 Feb 2023 18:49:42 +0100 Subject: [PATCH 05/11] Fixed path --- .github/workflows/low_level_tests.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/low_level_tests.yml b/.github/workflows/low_level_tests.yml index e832a5b..876013a 100644 --- a/.github/workflows/low_level_tests.yml +++ b/.github/workflows/low_level_tests.yml @@ -35,6 +35,7 @@ jobs: sudo apt-get install -y g++-9 g++-10 g++-11 protobuf-compiler valgrind python3-protobuf clang-* scons lcov - name: Run tests run: | + cd tests scons mkdir build/coverage lcov --base-directory . --directory build/ -c -o build/coverage/nanopb.info From 0585574816b19ac5cb00bfb5c961d19cee8ca3ce Mon Sep 17 00:00:00 2001 From: Paul Nykiel Date: Fri, 3 Feb 2023 19:19:41 +0100 Subject: [PATCH 06/11] Added nanopb as submodule --- .github/workflows/low_level_tests.yml | 11 +---------- .gitmodules | 3 +++ CMakeLists.txt | 12 ++---------- nanopb | 1 + 4 files changed, 7 insertions(+), 20 deletions(-) create mode 160000 nanopb diff --git a/.github/workflows/low_level_tests.yml b/.github/workflows/low_level_tests.yml index 876013a..0b17713 100644 --- a/.github/workflows/low_level_tests.yml +++ b/.github/workflows/low_level_tests.yml @@ -24,7 +24,6 @@ jobs: - uses: actions/checkout@v2 with: submodules: recursive - repository: nanopb/nanopb - name: Install dependencies run: | # Taken from https://apt.llvm.org/ @@ -35,17 +34,9 @@ jobs: sudo apt-get install -y g++-9 g++-10 g++-11 protobuf-compiler valgrind python3-protobuf clang-* scons lcov - name: Run tests run: | - cd tests + cd nanopb/tests scons mkdir build/coverage lcov --base-directory . --directory build/ -c -o build/coverage/nanopb.info lcov -r build/coverage/nanopb.info '*tests*' -o build/coverage/nanopb.info genhtml -o build/coverage build/coverage/nanopb.info - - uses: actions/upload-artifact@v3 - with: - name: RunResults - path: build/Tests/LowLevel - - uses: actions/upload-artifact@v3 - with: - name: ${{ matrix.compiler.cc }} - path: build/Tests/LowLevel diff --git a/.gitmodules b/.gitmodules index 0ffe77a..fe3b9b9 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,6 @@ [submodule "SI"] path = SI url = https://github.com/teamspatzenhirn/SI.git +[submodule "nanopb"] + path = nanopb + url = https://github.com/nanopb/nanopb.git diff --git a/CMakeLists.txt b/CMakeLists.txt index 7180cea..d92bd0e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,14 +1,8 @@ project(ToolboxPlaneMessages) -include(FetchContent) +add_subdirectory(SI) -FetchContent_Declare( - nanopb - GIT_REPOSITORY "https://github.com/nanopb/nanopb.git" - GIT_TAG "master" -) -FetchContent_Populate(nanopb) -set(CMAKE_MODULE_PATH ${nanopb_SOURCE_DIR}/extra) +set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/nanopb/extra) find_package(Nanopb REQUIRED) set(TOOLBOX_PLANE_MESSAGES @@ -28,5 +22,3 @@ target_include_directories(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/.. add_library(ToolboxPlaneMessageConversion INTERFACE) target_link_libraries(ToolboxPlaneMessageConversion INTERFACE ${PROJECT_NAME} SI) - -add_subdirectory(SI) diff --git a/nanopb b/nanopb new file mode 160000 index 0000000..c16c239 --- /dev/null +++ b/nanopb @@ -0,0 +1 @@ +Subproject commit c16c2399d1d1ba1e4a8d0f288cf9c158fdc85a0d From 6ed757415bf070f4da5720fd3a0d442fbe34cee8 Mon Sep 17 00:00:00 2001 From: Paul Nykiel Date: Fri, 3 Feb 2023 19:34:38 +0100 Subject: [PATCH 07/11] Moved external modules to external --- .gitmodules | 4 ++-- CMakeLists.txt | 4 ++-- SI => External/SI | 0 nanopb => External/nanopb | 0 4 files changed, 4 insertions(+), 4 deletions(-) rename SI => External/SI (100%) rename nanopb => External/nanopb (100%) diff --git a/.gitmodules b/.gitmodules index fe3b9b9..46ab20b 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,6 +1,6 @@ [submodule "SI"] - path = SI + path = External/SI url = https://github.com/teamspatzenhirn/SI.git [submodule "nanopb"] - path = nanopb + path = External/nanopb url = https://github.com/nanopb/nanopb.git diff --git a/CMakeLists.txt b/CMakeLists.txt index d92bd0e..623e899 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,8 +1,8 @@ project(ToolboxPlaneMessages) -add_subdirectory(SI) +add_subdirectory(External/SI) -set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/nanopb/extra) +set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/External/nanopb/extra) find_package(Nanopb REQUIRED) set(TOOLBOX_PLANE_MESSAGES diff --git a/SI b/External/SI similarity index 100% rename from SI rename to External/SI diff --git a/nanopb b/External/nanopb similarity index 100% rename from nanopb rename to External/nanopb From 43d3f11adff06637f1bc64a457230839ebe356a8 Mon Sep 17 00:00:00 2001 From: Paul Nykiel Date: Mon, 6 Feb 2023 19:54:20 +0100 Subject: [PATCH 08/11] Added mock tools and tests --- .github/workflows/low_level_tests.yml | 42 --- .gitmodules | 3 + CMakeLists.txt | 3 + External/MockTools | 1 + Tests/CMakeLists.txt | 14 + Tests/MessageDecoding.cpp | 436 ++++++++++++++++++++++++++ Tests/MessageEncoding.cpp | 80 +++++ Tests/generate_tests.sh | 62 ++++ Tests/main.cpp | 9 + 9 files changed, 608 insertions(+), 42 deletions(-) delete mode 100644 .github/workflows/low_level_tests.yml create mode 160000 External/MockTools create mode 100644 Tests/CMakeLists.txt create mode 100644 Tests/MessageDecoding.cpp create mode 100644 Tests/MessageEncoding.cpp create mode 100755 Tests/generate_tests.sh create mode 100644 Tests/main.cpp diff --git a/.github/workflows/low_level_tests.yml b/.github/workflows/low_level_tests.yml deleted file mode 100644 index 0b17713..0000000 --- a/.github/workflows/low_level_tests.yml +++ /dev/null @@ -1,42 +0,0 @@ -name: LowLevelTests -on: [ push ] - -jobs: - Run-Tests: - name: NanoPB Tests - runs-on: ubuntu-latest - strategy: - fail-fast: false - matrix: - compiler: [ { cc: gcc-10, cxx: g++-10 }, - { cc: gcc-11, cxx: g++-11 }, - { cc: clang-11, cxx: clang++-11 }, - { cc: clang-12, cxx: clang++-12 }, - { cc: clang-13, cxx: clang++-13 }, - { cc: clang-14, cxx: clang++-14 }, - #{ cc: clang-15, cxx: clang++-15 }, - { cc: clang-16, cxx: clang++-16 } ] - build: [ Release, Debug ] - env: - CC: ${{ matrix.compiler.cc }} - CXX: ${{ matrix.compiler.cxx }} - steps: - - uses: actions/checkout@v2 - with: - submodules: recursive - - name: Install dependencies - run: | - # Taken from https://apt.llvm.org/ - wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | sudo apt-key add - - sudo add-apt-repository "deb http://apt.llvm.org/jammy/ llvm-toolchain-jammy main" - sudo add-apt-repository "deb-src http://apt.llvm.org/jammy/ llvm-toolchain-jammy main" - sudo apt-get update - sudo apt-get install -y g++-9 g++-10 g++-11 protobuf-compiler valgrind python3-protobuf clang-* scons lcov - - name: Run tests - run: | - cd nanopb/tests - scons - mkdir build/coverage - lcov --base-directory . --directory build/ -c -o build/coverage/nanopb.info - lcov -r build/coverage/nanopb.info '*tests*' -o build/coverage/nanopb.info - genhtml -o build/coverage build/coverage/nanopb.info diff --git a/.gitmodules b/.gitmodules index 46ab20b..f76101b 100644 --- a/.gitmodules +++ b/.gitmodules @@ -4,3 +4,6 @@ [submodule "nanopb"] path = External/nanopb url = https://github.com/nanopb/nanopb.git +[submodule "External/MockTools"] + path = External/MockTools + url = https://github.com/ToolboxPlane/MockTools.git diff --git a/CMakeLists.txt b/CMakeLists.txt index 623e899..ca8c111 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,6 +1,7 @@ project(ToolboxPlaneMessages) add_subdirectory(External/SI) +add_subdirectory(External/MockTools) set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/External/nanopb/extra) find_package(Nanopb REQUIRED) @@ -22,3 +23,5 @@ target_include_directories(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/.. add_library(ToolboxPlaneMessageConversion INTERFACE) target_link_libraries(ToolboxPlaneMessageConversion INTERFACE ${PROJECT_NAME} SI) + +add_subdirectory(Tests) diff --git a/External/MockTools b/External/MockTools new file mode 160000 index 0000000..5678056 --- /dev/null +++ b/External/MockTools @@ -0,0 +1 @@ +Subproject commit 5678056c3c8544d1338c30259e8f21e15fc8a062 diff --git a/Tests/CMakeLists.txt b/Tests/CMakeLists.txt new file mode 100644 index 0000000..750ce1f --- /dev/null +++ b/Tests/CMakeLists.txt @@ -0,0 +1,14 @@ +add_custom_target(generate_tests + COMMAND ${CMAKE_CURRENT_LIST_DIR}/generate_tests.sh ${CMAKE_SOURCE_DIR} + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + DEPENDS ${CMAKE_CURRENT_LIST_DIR}/generate_tests.sh) + +make_test(MODULE_UNDER_TEST ../MessageDecoding.c + TEST_DEFINITION MessageDecoding.cpp) +target_link_libraries(MessageDecoding.test PUBLIC ToolboxPlaneMessageDefs) +add_dependencies(MessageDecoding.test generate_tests) + +make_test(MODULE_UNDER_TEST ../MessageEncoding.c + TEST_DEFINITION MessageEncoding.cpp) +target_link_libraries(MessageEncoding.test PUBLIC ToolboxPlaneMessageDefs) +add_dependencies(MessageEncoding.test generate_tests) diff --git a/Tests/MessageDecoding.cpp b/Tests/MessageDecoding.cpp new file mode 100644 index 0000000..1dd07b9 --- /dev/null +++ b/Tests/MessageDecoding.cpp @@ -0,0 +1,436 @@ +#include +#include + +extern "C" { +#include +} + +#include "FlightControllerSetpoint.pb.h" + +TEST(TEST_NAME, decode__nominal_decode) { + /* + * Nominal decode test. + * Test: + * * Initialize with message_id as 17 + * * Feed 0xF0 to transition to END_FOUND, expect false + * * Feed 0x0F to transition to START_FOUND, expect false + * * Feed 17 to transition to IN_DATA, expect false + * * Feed 0xF0 to transition to IN_DATA_END_FOUND, expect false + * * Feed 0x0F to transition to START_FOUND, expect true + */ + message_decoding_data_t decodingData; + message_decoding_init(&decodingData, 17, ToolboxPlaneMessages_FlightControllerSetpoint_fields); + + EXPECT_FALSE(message_decoding_decode(&decodingData, 0xF0, nullptr)); + EXPECT_FALSE(message_decoding_decode(&decodingData, 0x0F, nullptr)); + EXPECT_FALSE(message_decoding_decode(&decodingData, 17, nullptr)); + EXPECT_FALSE(message_decoding_decode(&decodingData, 0xF0, nullptr)); + ToolboxPlaneMessages_FlightControllerSetpoint buf; + EXPECT_TRUE(message_decoding_decode(&decodingData, 0x0F, &buf)); +} + +TEST(TEST_NAME, decode__premature_end) { + /* + * Premature end test. + * Test: + * * Initialize with message_id as 17 + * * Feed 0xF0 to transition to END_FOUND, expect false + * * Feed 0x0F to transition to START_FOUND, expect false + * * Feed 17 to transition to IN_DATA, expect false + * * Feed 0x08 to keep in IN_DATA, expect false + * * Feed 0xF0 to transition to IN_DATA_END_FOUND, expect false + * * Feed 0x01 to transition to IN_DATA, expect false + * * Feed 0xF0 to transition to IN_DATA_END_FOUND, expect false + * * Feed 0x0F to transition to START_FOUND, expect true + */ + message_decoding_data_t decodingData; + message_decoding_init(&decodingData, 17, ToolboxPlaneMessages_FlightControllerSetpoint_fields); + + EXPECT_FALSE(message_decoding_decode(&decodingData, 0xF0, nullptr)); + EXPECT_FALSE(message_decoding_decode(&decodingData, 0x0F, nullptr)); + EXPECT_FALSE(message_decoding_decode(&decodingData, 17, nullptr)); + EXPECT_FALSE(message_decoding_decode(&decodingData, 0x08, nullptr)); + EXPECT_FALSE(message_decoding_decode(&decodingData, 0xF0, nullptr)); + EXPECT_FALSE(message_decoding_decode(&decodingData, 0x01, nullptr)); + EXPECT_FALSE(message_decoding_decode(&decodingData, 0xF0, nullptr)); + ToolboxPlaneMessages_FlightControllerSetpoint buf; + EXPECT_TRUE(message_decoding_decode(&decodingData, 0x0F, &buf)); +} + +TEST(TEST_NAME, decode__wrong_data) { + /* + * Wrong data test. + * Test: + * * Initialize with message_id as 17 + * * Feed 0xF0 to transition to END_FOUND, expect false + * * Feed 0x0F to transition to START_FOUND, expect false + * * Feed 18 to transition to INITIAL, expect false + * * Feed 0xF0 to transition to END_FOUND, expect false + * * Feed 0x0F to transition to START_FOUND, expect false + * * Feed 17 to transition to IN_DATA, expect false + * * Feed 0xF0 to transition to IN_DATA_END_FOUND, expect false + * * Feed 0x0F to transition to START_FOUND, expect true + */ + message_decoding_data_t decodingData; + message_decoding_init(&decodingData, 17, ToolboxPlaneMessages_FlightControllerSetpoint_fields); + + EXPECT_FALSE(message_decoding_decode(&decodingData, 0xF0, nullptr)); + EXPECT_FALSE(message_decoding_decode(&decodingData, 0x0F, nullptr)); + EXPECT_FALSE(message_decoding_decode(&decodingData, 18, nullptr)); + EXPECT_FALSE(message_decoding_decode(&decodingData, 0xF0, nullptr)); + EXPECT_FALSE(message_decoding_decode(&decodingData, 0x0F, nullptr)); + EXPECT_FALSE(message_decoding_decode(&decodingData, 17, nullptr)); + EXPECT_FALSE(message_decoding_decode(&decodingData, 0xF0, nullptr)); + ToolboxPlaneMessages_FlightControllerSetpoint buf; + EXPECT_TRUE(message_decoding_decode(&decodingData, 0x0F, &buf)); +} + +TEST(TEST_NAME, decode__wrong_data_premature_end) { + /* + * Wrong Data Premature end test. + * Test: + * * Initialize with message_id as 17 + * * Feed 0xF0 to transition to END_FOUND, expect false + * * Feed 0x0F to transition to START_FOUND, expect false + * * Feed 18 to transition to INITIAL, expect false + * * Feed 0x08 to keep in INITIAL, expect false + * * Feed 0xF0 to transition to END_FOUND, expect false + * * Feed 0x01 to transition to IN_DATA, expect false + * * Feed 0xF0 to transition to IN_DATA_END_FOUND, expect false + * * Feed 0x0F to transition to START_FOUND, expect false + * * Feed 17 to transition to IN_DATA, expect false + * * Feed 0xF0 to transition to IN_DATA_END_FOUND, expect false + * * Feed 0x0F to transition to START_FOUND, expect true + */ + message_decoding_data_t decodingData; + message_decoding_init(&decodingData, 17, ToolboxPlaneMessages_FlightControllerSetpoint_fields); + + EXPECT_FALSE(message_decoding_decode(&decodingData, 0xF0, nullptr)); + EXPECT_FALSE(message_decoding_decode(&decodingData, 0x0F, nullptr)); + EXPECT_FALSE(message_decoding_decode(&decodingData, 18, nullptr)); + EXPECT_FALSE(message_decoding_decode(&decodingData, 0x08, nullptr)); + EXPECT_FALSE(message_decoding_decode(&decodingData, 0xF0, nullptr)); + EXPECT_FALSE(message_decoding_decode(&decodingData, 0x01, nullptr)); + EXPECT_FALSE(message_decoding_decode(&decodingData, 0xF0, nullptr)); + EXPECT_FALSE(message_decoding_decode(&decodingData, 0x0F, nullptr)); + EXPECT_FALSE(message_decoding_decode(&decodingData, 17, nullptr)); + EXPECT_FALSE(message_decoding_decode(&decodingData, 0xF0, nullptr)); + ToolboxPlaneMessages_FlightControllerSetpoint buf; + EXPECT_TRUE(message_decoding_decode(&decodingData, 0x0F, &buf)); +} + +TEST(TEST_NAME, decode__multiple_init) { + /* + * Multiple init decode test. + * Test: + * * Initialize with message_id as 17 + * * Feed 0x00 to keep in initial + * * Feed 0xF0 to transition to END_FOUND, expect false + * * Feed 0x0F to transition to START_FOUND, expect false + * * Feed 17 to transition to IN_DATA, expect false + * * Feed 0xF0 to transition to IN_DATA_END_FOUND, expect false + * * Feed 0x0F to transition to START_FOUND, expect true + */ + message_decoding_data_t decodingData; + message_decoding_init(&decodingData, 17, ToolboxPlaneMessages_FlightControllerSetpoint_fields); + + EXPECT_FALSE(message_decoding_decode(&decodingData, 0x00, nullptr)); + EXPECT_FALSE(message_decoding_decode(&decodingData, 0xF0, nullptr)); + EXPECT_FALSE(message_decoding_decode(&decodingData, 0x0F, nullptr)); + EXPECT_FALSE(message_decoding_decode(&decodingData, 17, nullptr)); + EXPECT_FALSE(message_decoding_decode(&decodingData, 0xF0, nullptr)); + ToolboxPlaneMessages_FlightControllerSetpoint buf; + EXPECT_TRUE(message_decoding_decode(&decodingData, 0x0F, &buf)); +} + +TEST(TEST_NAME, decode__init_wrong_end) { + /* + * Init wrong end test. + * Test: + * * Initialize with message_id as 17 + * * Feed 0xF0 to transition to END_FOUND, expect false + * * Feed 0x00 to transition to INITIAL, expect false + * * Feed 0xF0 to transition to END_FOUND, expect false + * * Feed 0x0F to transition to START_FOUND, expect false + * * Feed 17 to transition to IN_DATA, expect false + * * Feed 0xF0 to transition to IN_DATA_END_FOUND, expect false + * * Feed 0x0F to transition to START_FOUND, expect true + */ + message_decoding_data_t decodingData; + message_decoding_init(&decodingData, 17, ToolboxPlaneMessages_FlightControllerSetpoint_fields); + + EXPECT_FALSE(message_decoding_decode(&decodingData, 0xF0, nullptr)); + EXPECT_FALSE(message_decoding_decode(&decodingData, 0x00, nullptr)); + EXPECT_FALSE(message_decoding_decode(&decodingData, 0xF0, nullptr)); + EXPECT_FALSE(message_decoding_decode(&decodingData, 0x0F, nullptr)); + EXPECT_FALSE(message_decoding_decode(&decodingData, 17, nullptr)); + EXPECT_FALSE(message_decoding_decode(&decodingData, 0xF0, nullptr)); + ToolboxPlaneMessages_FlightControllerSetpoint buf; + EXPECT_TRUE(message_decoding_decode(&decodingData, 0x0F, &buf)); +} + +TEST(TEST_NAME, decode__fcs_decode) { + /* + * Flight-Controller-Set-Point min power test: + * * Initialize with message_id as 0 + * * Feed 0xF0 to transition to END_FOUND, expect false + * * Feed 0x0F to transition to START_FOUND, expect false + * * Feed 0 to transition to IN_DATA, expect false + * * Feed data from fcs_min_power.bin, expect false for every byte + * * Feed 0xF0 to transition to IN_DATA_END_FOUND, expect false + * * Feed 0x0F to transition to START_FOUND, expect true + * * Check return message, expect: + * * motor: -2147483648 + * * pitch: 0 + * * roll: 0 + */ + message_decoding_data_t decodingData; + message_decoding_init(&decodingData, 0, ToolboxPlaneMessages_FlightControllerSetpoint_fields); + + EXPECT_FALSE(message_decoding_decode(&decodingData, 0xF0, nullptr)); + EXPECT_FALSE(message_decoding_decode(&decodingData, 0x0F, nullptr)); + EXPECT_FALSE(message_decoding_decode(&decodingData, 0, nullptr)); + + std::ifstream stream{"fcs_decode.bin"}; + using c_stream_it = std::istreambuf_iterator; + + for (auto it = c_stream_it{stream}; it != c_stream_it{}; ++it) { + EXPECT_FALSE(message_decoding_decode(&decodingData, *it, nullptr)); + } + + EXPECT_FALSE(message_decoding_decode(&decodingData, 0xF0, nullptr)); + ToolboxPlaneMessages_FlightControllerSetpoint buf; + EXPECT_TRUE(message_decoding_decode(&decodingData, 0x0F, &buf)); + + EXPECT_EQ(buf.motor, 17); + EXPECT_EQ(buf.pitch, -18); + EXPECT_EQ(buf.roll, 19); +} + +TEST(TEST_NAME, decode__fcs_min_power) { + /* + * Flight-Controller-Set-Point min power test: + * * Initialize with message_id as 0 + * * Feed 0xF0 to transition to END_FOUND, expect false + * * Feed 0x0F to transition to START_FOUND, expect false + * * Feed 0 to transition to IN_DATA, expect false + * * Feed data from fcs_min_power.bin, expect false for every byte + * * Feed 0xF0 to transition to IN_DATA_END_FOUND, expect false + * * Feed 0x0F to transition to START_FOUND, expect true + * * Check return message, expect: + * * motor: -2147483648 + * * pitch: 0 + * * roll: 0 + */ + message_decoding_data_t decodingData; + message_decoding_init(&decodingData, 0, ToolboxPlaneMessages_FlightControllerSetpoint_fields); + + EXPECT_FALSE(message_decoding_decode(&decodingData, 0xF0, nullptr)); + EXPECT_FALSE(message_decoding_decode(&decodingData, 0x0F, nullptr)); + EXPECT_FALSE(message_decoding_decode(&decodingData, 0, nullptr)); + + std::ifstream stream{"fcs_min_power.bin"}; + using c_stream_it = std::istreambuf_iterator; + + for (auto it = c_stream_it{stream}; it != c_stream_it{}; ++it) { + EXPECT_FALSE(message_decoding_decode(&decodingData, *it, nullptr)); + } + + EXPECT_FALSE(message_decoding_decode(&decodingData, 0xF0, nullptr)); + ToolboxPlaneMessages_FlightControllerSetpoint buf; + EXPECT_TRUE(message_decoding_decode(&decodingData, 0x0F, &buf)); + + EXPECT_EQ(buf.motor, -2147483648); + EXPECT_EQ(buf.pitch, 0); + EXPECT_EQ(buf.roll, 0); +} + +TEST(TEST_NAME, decode__fcs_max_power) { + /* + * Flight-Controller-Set-Point min power test: + * * Initialize with message_id as 0 + * * Feed 0xF0 to transition to END_FOUND, expect false + * * Feed 0x0F to transition to START_FOUND, expect false + * * Feed 0 to transition to IN_DATA, expect false + * * Feed data from fcs_max_power.bin, expect false for every byte + * * Feed 0xF0 to transition to IN_DATA_END_FOUND, expect false + * * Feed 0x0F to transition to START_FOUND, expect true + * * Check return message, expect: + * * motor: 2147483647 + * * pitch: 0 + * * roll: 0 + */ + message_decoding_data_t decodingData; + message_decoding_init(&decodingData, 0, ToolboxPlaneMessages_FlightControllerSetpoint_fields); + + EXPECT_FALSE(message_decoding_decode(&decodingData, 0xF0, nullptr)); + EXPECT_FALSE(message_decoding_decode(&decodingData, 0x0F, nullptr)); + EXPECT_FALSE(message_decoding_decode(&decodingData, 0, nullptr)); + + std::ifstream stream{"fcs_max_power.bin"}; + using c_stream_it = std::istreambuf_iterator; + + for (auto it = c_stream_it{stream}; it != c_stream_it{}; ++it) { + EXPECT_FALSE(message_decoding_decode(&decodingData, *it, nullptr)); + } + + EXPECT_FALSE(message_decoding_decode(&decodingData, 0xF0, nullptr)); + ToolboxPlaneMessages_FlightControllerSetpoint buf; + EXPECT_TRUE(message_decoding_decode(&decodingData, 0x0F, &buf)); + + EXPECT_EQ(buf.motor, 2147483647); + EXPECT_EQ(buf.pitch, 0); + EXPECT_EQ(buf.roll, 0); +} + +TEST(TEST_NAME, decode__fcs_min_pitch) { + /* + * Flight-Controller-Set-Point min power test: + * * Initialize with message_id as 0 + * * Feed 0xF0 to transition to END_FOUND, expect false + * * Feed 0x0F to transition to START_FOUND, expect false + * * Feed 0 to transition to IN_DATA, expect false + * * Feed data from fcs_min_pitch.bin, expect false for every byte + * * Feed 0xF0 to transition to IN_DATA_END_FOUND, expect false + * * Feed 0x0F to transition to START_FOUND, expect true + * * Check return message, expect: + * * motor: 0 + * * pitch: -2147483648 + * * roll: 0 + */ + message_decoding_data_t decodingData; + message_decoding_init(&decodingData, 0, ToolboxPlaneMessages_FlightControllerSetpoint_fields); + + EXPECT_FALSE(message_decoding_decode(&decodingData, 0xF0, nullptr)); + EXPECT_FALSE(message_decoding_decode(&decodingData, 0x0F, nullptr)); + EXPECT_FALSE(message_decoding_decode(&decodingData, 0, nullptr)); + + std::ifstream stream{"fcs_min_pitch.bin"}; + using c_stream_it = std::istreambuf_iterator; + + for (auto it = c_stream_it{stream}; it != c_stream_it{}; ++it) { + EXPECT_FALSE(message_decoding_decode(&decodingData, *it, nullptr)); + } + + EXPECT_FALSE(message_decoding_decode(&decodingData, 0xF0, nullptr)); + ToolboxPlaneMessages_FlightControllerSetpoint buf; + EXPECT_TRUE(message_decoding_decode(&decodingData, 0x0F, &buf)); + + EXPECT_EQ(buf.motor, 0); + EXPECT_EQ(buf.pitch, -2147483648); + EXPECT_EQ(buf.roll, 0); +} + +TEST(TEST_NAME, decode__fcs_max_pitch) { + /* + * Flight-Controller-Set-Point min power test: + * * Initialize with message_id as 0 + * * Feed 0xF0 to transition to END_FOUND, expect false + * * Feed 0x0F to transition to START_FOUND, expect false + * * Feed 0 to transition to IN_DATA, expect false + * * Feed data from fcs_max_pitch.bin, expect false for every byte + * * Feed 0xF0 to transition to IN_DATA_END_FOUND, expect false + * * Feed 0x0F to transition to START_FOUND, expect true + * * Check return message, expect: + * * motor: 0 + * * pitch: 2147483647 + * * roll: 0 + */ + message_decoding_data_t decodingData; + message_decoding_init(&decodingData, 0, ToolboxPlaneMessages_FlightControllerSetpoint_fields); + + EXPECT_FALSE(message_decoding_decode(&decodingData, 0xF0, nullptr)); + EXPECT_FALSE(message_decoding_decode(&decodingData, 0x0F, nullptr)); + EXPECT_FALSE(message_decoding_decode(&decodingData, 0, nullptr)); + + std::ifstream stream{"fcs_max_pitch.bin"}; + using c_stream_it = std::istreambuf_iterator; + + for (auto it = c_stream_it{stream}; it != c_stream_it{}; ++it) { + EXPECT_FALSE(message_decoding_decode(&decodingData, *it, nullptr)); + } + + EXPECT_FALSE(message_decoding_decode(&decodingData, 0xF0, nullptr)); + ToolboxPlaneMessages_FlightControllerSetpoint buf; + EXPECT_TRUE(message_decoding_decode(&decodingData, 0x0F, &buf)); + + EXPECT_EQ(buf.motor, 0); + EXPECT_EQ(buf.pitch, 2147483647); + EXPECT_EQ(buf.roll, 0); +} + +TEST(TEST_NAME, decode__fcs_min_roll) { + /* + * Flight-Controller-Set-Point min power test: + * * Initialize with message_id as 0 + * * Feed 0xF0 to transition to END_FOUND, expect false + * * Feed 0x0F to transition to START_FOUND, expect false + * * Feed 0 to transition to IN_DATA, expect false + * * Feed data from fcs_min_roll.bin, expect false for every byte + * * Feed 0xF0 to transition to IN_DATA_END_FOUND, expect false + * * Feed 0x0F to transition to START_FOUND, expect true + * * Check return message, expect: + * * motor: 0 + * * pitch: 0 + * * roll: -2147483648 + */ + message_decoding_data_t decodingData; + message_decoding_init(&decodingData, 0, ToolboxPlaneMessages_FlightControllerSetpoint_fields); + + EXPECT_FALSE(message_decoding_decode(&decodingData, 0xF0, nullptr)); + EXPECT_FALSE(message_decoding_decode(&decodingData, 0x0F, nullptr)); + EXPECT_FALSE(message_decoding_decode(&decodingData, 0, nullptr)); + + std::ifstream stream{"fcs_min_roll.bin"}; + using c_stream_it = std::istreambuf_iterator; + + for (auto it = c_stream_it{stream}; it != c_stream_it{}; ++it) { + EXPECT_FALSE(message_decoding_decode(&decodingData, *it, nullptr)); + } + + EXPECT_FALSE(message_decoding_decode(&decodingData, 0xF0, nullptr)); + ToolboxPlaneMessages_FlightControllerSetpoint buf; + EXPECT_TRUE(message_decoding_decode(&decodingData, 0x0F, &buf)); + + EXPECT_EQ(buf.motor, 0); + EXPECT_EQ(buf.pitch, 0); + EXPECT_EQ(buf.roll, -2147483648); +} + +TEST(TEST_NAME, decode__fcs_max_roll) { + /* + * Flight-Controller-Set-Point min power test: + * * Initialize with message_id as 0 + * * Feed 0xF0 to transition to END_FOUND, expect false + * * Feed 0x0F to transition to START_FOUND, expect false + * * Feed 0 to transition to IN_DATA, expect false + * * Feed data from fcs_max_roll.bin, expect false for every byte + * * Feed 0xF0 to transition to IN_DATA_END_FOUND, expect false + * * Feed 0x0F to transition to START_FOUND, expect true + * * Check return message, expect: + * * motor: 0 + * * pitch: 0 + * * roll: 2147483647 + */ + message_decoding_data_t decodingData; + message_decoding_init(&decodingData, 0, ToolboxPlaneMessages_FlightControllerSetpoint_fields); + + EXPECT_FALSE(message_decoding_decode(&decodingData, 0xF0, nullptr)); + EXPECT_FALSE(message_decoding_decode(&decodingData, 0x0F, nullptr)); + EXPECT_FALSE(message_decoding_decode(&decodingData, 0, nullptr)); + + std::ifstream stream{"fcs_max_roll.bin"}; + using c_stream_it = std::istreambuf_iterator; + + for (auto it = c_stream_it{stream}; it != c_stream_it{}; ++it) { + EXPECT_FALSE(message_decoding_decode(&decodingData, *it, nullptr)); + } + + EXPECT_FALSE(message_decoding_decode(&decodingData, 0xF0, nullptr)); + ToolboxPlaneMessages_FlightControllerSetpoint buf; + EXPECT_TRUE(message_decoding_decode(&decodingData, 0x0F, &buf)); + + EXPECT_EQ(buf.motor, 0); + EXPECT_EQ(buf.pitch, 0); + EXPECT_EQ(buf.roll, 2147483647); +} diff --git a/Tests/MessageEncoding.cpp b/Tests/MessageEncoding.cpp new file mode 100644 index 0000000..f8851d2 --- /dev/null +++ b/Tests/MessageEncoding.cpp @@ -0,0 +1,80 @@ +#include +#include + +extern "C" { +#include +} + +#include "FlightController.pb.h" + +TEST(TEST_NAME, encode__buffer_format) { + /* + * Encode message with all zero data and id 17, expect: + * * Returned length: 3 + * * First byte: 0x0F + * * Second byte: 17 + * * Third byte: 0xF0 + */ + std::array buf{}; + ToolboxPlaneMessages_FlightController data{}; + EXPECT_EQ(message_encode(buf.data(), buf.size(), ToolboxPlaneMessages_FlightController_fields, &data, 17), + 3); + EXPECT_EQ(buf[0], 0x0F); + EXPECT_EQ(buf[1], 17); + EXPECT_EQ(buf[2], 0xF0); +} + +TEST(TEST_NAME, encode__fc_encode) { + /* + * Encode message with all zero data and id 17, expect: + * * Returned length: 3 + * * First byte: 0x0F + * * Second byte: 17 + * * Third byte: 0xF0 + */ + ToolboxPlaneMessages_FlightController data{ + .has_imu = true, + .imu = { + .imu_ok = true, + .roll_mul_16 = 17, + .pitch_mul_16 = -18, + .yaw_mul_16 = 19, + .dRoll_mul_16 = -20, + .dPitch_mul_16 = 21, + .dYaw_mul_16 = -22, + .accX_mul_100 = 23, + .accY_mul_100 = -24, + .accZ_mul_100 = 25 + }, + .has_remote = true, + .remote = { + .remote_ok = false, + .throttleMixed = -26, + .elevonLeftMixed = 27, + .elevonRightMixed = -28, + .isArmed = true, + .overrideActive = false, + }, + .motor = 29, + .servoLeft = 30, + .servoRight = 31 + }; + + std::ifstream stream{"fc_encode.bin"}; + using c_stream_it = std::istreambuf_iterator; + std::vector expectedData; + expectedData.emplace_back(0x0F); + expectedData.emplace_back(17); + for (auto it = c_stream_it{stream}; it != c_stream_it{}; ++it) { + expectedData.emplace_back(*it); + } + expectedData.emplace_back(0xF0); + + EXPECT_LT(expectedData.size(), ToolboxPlaneMessages_FlightController_size + 3); + std::array buf{}; + EXPECT_EQ(message_encode(buf.data(), buf.size(), ToolboxPlaneMessages_FlightController_fields, &data, 17), + expectedData.size()); + for (auto idx =0U; idx fcs_decode.bin + +echo "motor: -2147483648, pitch: 0, roll: 0" | \ + protoc --encode=ToolboxPlaneMessages.FlightControllerSetpoint \ + --proto_path "$1" \ + Src/Messages/Definitions/FlightControllerSetpoint.proto > fcs_min_power.bin + +echo "motor: 2147483647, pitch: 0, roll: 0" | \ + protoc --encode=ToolboxPlaneMessages.FlightControllerSetpoint \ + --proto_path "$1" \ + Src/Messages/Definitions/FlightControllerSetpoint.proto > fcs_max_power.bin + +echo "motor: 0, pitch: -2147483648, roll: 0" | \ + protoc --encode=ToolboxPlaneMessages.FlightControllerSetpoint \ + --proto_path "$1" \ + Src/Messages/Definitions/FlightControllerSetpoint.proto > fcs_min_pitch.bin + +echo "motor: 0, pitch: 2147483647, roll: 0" | \ + protoc --encode=ToolboxPlaneMessages.FlightControllerSetpoint \ + --proto_path "$1" \ + Src/Messages/Definitions/FlightControllerSetpoint.proto > fcs_max_pitch.bin + +echo "motor: 0, pitch: 0, roll: -2147483648" | \ + protoc --encode=ToolboxPlaneMessages.FlightControllerSetpoint \ + --proto_path "$1" \ + Src/Messages/Definitions/FlightControllerSetpoint.proto > fcs_min_roll.bin + +echo "motor: 0, pitch: 0, roll: 2147483647" | \ + protoc --encode=ToolboxPlaneMessages.FlightControllerSetpoint \ + --proto_path "$1" \ + Src/Messages/Definitions/FlightControllerSetpoint.proto > fcs_max_roll.bin + +echo "imu: { + imu_ok: true, + roll_mul_16: 17, + pitch_mul_16: -18 + yaw_mul_16: 19, + dRoll_mul_16: -20, + dPitch_mul_16: 21, + dYaw_mul_16: -22 + accX_mul_100: 23, + accY_mul_100: -24, + accZ_mul_100: 25 + }, + remote: { + remote_ok: false; + throttleMixed: -26; + elevonLeftMixed: 27; + elevonRightMixed: -28; + isArmed: true; + overrideActive: false; + }, + motor: 29, + servoLeft: 30, + servoRight: 31" | \ + protoc --encode=ToolboxPlaneMessages.FlightController \ + --proto_path "$1" \ + Src/Messages/Definitions/FlightController.proto > fc_encode.bin diff --git a/Tests/main.cpp b/Tests/main.cpp new file mode 100644 index 0000000..7c6d6df --- /dev/null +++ b/Tests/main.cpp @@ -0,0 +1,9 @@ +#include +#include + +int main(int argc, char **argv) { + feenableexcept(FE_INVALID | FE_OVERFLOW | FE_DIVBYZERO); // Floating point exceptions + + testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} From c5a465d003f5b47deb4de6c80af7191e1c75dbe0 Mon Sep 17 00:00:00 2001 From: Paul Nykiel Date: Wed, 8 Feb 2023 19:34:25 +0100 Subject: [PATCH 09/11] Format --- Tests/MessageEncoding.cpp | 56 ++++++++++++++++++--------------------- 1 file changed, 26 insertions(+), 30 deletions(-) diff --git a/Tests/MessageEncoding.cpp b/Tests/MessageEncoding.cpp index f8851d2..e28fae4 100644 --- a/Tests/MessageEncoding.cpp +++ b/Tests/MessageEncoding.cpp @@ -17,8 +17,7 @@ TEST(TEST_NAME, encode__buffer_format) { */ std::array buf{}; ToolboxPlaneMessages_FlightController data{}; - EXPECT_EQ(message_encode(buf.data(), buf.size(), ToolboxPlaneMessages_FlightController_fields, &data, 17), - 3); + EXPECT_EQ(message_encode(buf.data(), buf.size(), ToolboxPlaneMessages_FlightController_fields, &data, 17), 3); EXPECT_EQ(buf[0], 0x0F); EXPECT_EQ(buf[1], 17); EXPECT_EQ(buf[2], 0xF0); @@ -32,33 +31,30 @@ TEST(TEST_NAME, encode__fc_encode) { * * Second byte: 17 * * Third byte: 0xF0 */ - ToolboxPlaneMessages_FlightController data{ - .has_imu = true, - .imu = { - .imu_ok = true, - .roll_mul_16 = 17, - .pitch_mul_16 = -18, - .yaw_mul_16 = 19, - .dRoll_mul_16 = -20, - .dPitch_mul_16 = 21, - .dYaw_mul_16 = -22, - .accX_mul_100 = 23, - .accY_mul_100 = -24, - .accZ_mul_100 = 25 - }, - .has_remote = true, - .remote = { - .remote_ok = false, - .throttleMixed = -26, - .elevonLeftMixed = 27, - .elevonRightMixed = -28, - .isArmed = true, - .overrideActive = false, - }, - .motor = 29, - .servoLeft = 30, - .servoRight = 31 - }; + ToolboxPlaneMessages_FlightController data{.has_imu = true, + .imu = {.imu_ok = true, + .roll_mul_16 = 17, + .pitch_mul_16 = -18, + .yaw_mul_16 = 19, + .dRoll_mul_16 = -20, + .dPitch_mul_16 = 21, + .dYaw_mul_16 = -22, + .accX_mul_100 = 23, + .accY_mul_100 = -24, + .accZ_mul_100 = 25}, + .has_remote = true, + .remote = + { + .remote_ok = false, + .throttleMixed = -26, + .elevonLeftMixed = 27, + .elevonRightMixed = -28, + .isArmed = true, + .overrideActive = false, + }, + .motor = 29, + .servoLeft = 30, + .servoRight = 31}; std::ifstream stream{"fc_encode.bin"}; using c_stream_it = std::istreambuf_iterator; @@ -74,7 +70,7 @@ TEST(TEST_NAME, encode__fc_encode) { std::array buf{}; EXPECT_EQ(message_encode(buf.data(), buf.size(), ToolboxPlaneMessages_FlightController_fields, &data, 17), expectedData.size()); - for (auto idx =0U; idx Date: Mon, 13 Feb 2023 20:15:27 +0100 Subject: [PATCH 10/11] Murks --- MessageEncoding.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/MessageEncoding.c b/MessageEncoding.c index 2fefe46..2f2db48 100644 --- a/MessageEncoding.c +++ b/MessageEncoding.c @@ -9,7 +9,8 @@ #include "MessageDefs.h" -uint16_t message_encode(uint8_t *buf, uint16_t size, const pb_msgdesc_t *fields, const void *message, uint8_t message_id) { +uint16_t message_encode(uint8_t *buf, uint16_t size, const pb_msgdesc_t *fields, const void *message, + uint8_t message_id) { pb_ostream_t ostream = pb_ostream_from_buffer(buf + 2, size - 3); pb_encode(&ostream, fields, message); buf[0] = START_BYTE; From dccfb61076df3b6fef8af663fc3033c050c1bec9 Mon Sep 17 00:00:00 2001 From: Paul Nykiel Date: Mon, 20 Feb 2023 19:55:01 +0100 Subject: [PATCH 11/11] Updated mock tools, use main from mock tools --- External/MockTools | 2 +- Tests/main.cpp | 9 --------- 2 files changed, 1 insertion(+), 10 deletions(-) delete mode 100644 Tests/main.cpp diff --git a/External/MockTools b/External/MockTools index 5678056..0317e24 160000 --- a/External/MockTools +++ b/External/MockTools @@ -1 +1 @@ -Subproject commit 5678056c3c8544d1338c30259e8f21e15fc8a062 +Subproject commit 0317e2490f8a557d418aa4c6c2fce43f29e1e377 diff --git a/Tests/main.cpp b/Tests/main.cpp deleted file mode 100644 index 7c6d6df..0000000 --- a/Tests/main.cpp +++ /dev/null @@ -1,9 +0,0 @@ -#include -#include - -int main(int argc, char **argv) { - feenableexcept(FE_INVALID | FE_OVERFLOW | FE_DIVBYZERO); // Floating point exceptions - - testing::InitGoogleTest(&argc, argv); - return RUN_ALL_TESTS(); -}