diff --git a/Makefile b/Makefile index 72f4fb8..f875db4 100644 --- a/Makefile +++ b/Makefile @@ -204,7 +204,7 @@ super-linter: --env RUN_LOCAL=true \ --env DEFAULT_BRANCH=main \ --env IGNORE_GITIGNORED_FILES=true \ - --env FILTER_REGEX_EXCLUDE="(dse/modelc/examples/apis/.*|doc/content/apis/modelc/examples/.*)" \ + --env FILTER_REGEX_EXCLUDE="(dse/mocks/examples/.*|dse/modelc/examples/doc/.*|doc/content/apis/modelc/examples/.*|doc/content/docs/examples/modelc/.*)" \ --env VALIDATE_CPP=true \ --env VALIDATE_YAML=true \ --env VALIDATE_PYTHON_PYLINT=true \ diff --git a/doc/Makefile b/doc/Makefile index 29e4b56..d70b981 100644 --- a/doc/Makefile +++ b/doc/Makefile @@ -73,9 +73,14 @@ DOC_C_MODULES := gateway mcl model runtime schema simmock .PHONY: examples examples: +# API Examples cd ..;mkdir -p doc/content/apis/modelc/examples cd ..;cp dse/modelc/examples/gateway/gateway.c doc/content/apis/modelc/examples/gateway.c - cd ..;cp dse/modelc/examples/apis/*.c doc/content/apis/modelc/examples + cd ..;cp dse/modelc/examples/doc/apis/*.c doc/content/apis/modelc/examples +# DOC Examples + cd ..;mkdir -p doc/content/docs/examples/modelc/mocks + cd ..;find dse/mocks/examples/* -type d | xargs -I % cp -r % doc/content/docs/examples/modelc/mocks + cd ..;find dse/modelc/examples/doc/docs/* -type d | xargs -I % cp -r % doc/content/docs/examples/modelc .PHONY: index index: diff --git a/doc/content/apis/modelc/gateway/index.md b/doc/content/apis/modelc/gateway/index.md index 150008d..d6fb373 100644 --- a/doc/content/apis/modelc/gateway/index.md +++ b/doc/content/apis/modelc/gateway/index.md @@ -59,11 +59,11 @@ center footer Dynamic Simulation Environment ```c typedef struct ModelGatewayDesc { - int * sim; - int * mi; - int * sv; - const char ** argv; - char * name_arg; + int* sim; + int* mi; + int* sv; + const char** argv; + char* name_arg; } ``` diff --git a/doc/content/apis/modelc/mcl/index.md b/doc/content/apis/modelc/mcl/index.md index ddc246c..5b61499 100644 --- a/doc/content/apis/modelc/mcl/index.md +++ b/doc/content/apis/modelc/mcl/index.md @@ -58,7 +58,7 @@ center footer Dynamic Simulation Environment ```c typedef struct MclAdapterDesc { - const char * name; + const char* name; MclLoadHandler load_func; MclInitHandler init_func; MclStepHandler step_func; @@ -70,9 +70,9 @@ typedef struct MclAdapterDesc { ```c typedef struct MclInstanceDesc { - int * model_instance; - int * mcl_channel_sv; - MclStrategyDesc * strategy; + int* model_instance; + int* mcl_channel_sv; + MclStrategyDesc* strategy; int models; } ``` @@ -81,17 +81,17 @@ typedef struct MclInstanceDesc { ```c typedef struct MclModelDesc { - const char * name; - int * model_doc; - char * path; - void * handle; - double * vector_double; - void ** vector_binary; + const char* name; + int* model_doc; + char* path; + void* handle; + double* vector_double; + void** vector_binary; double model_time; double model_time_correction; double step_size; - MclAdapterDesc * adapter; - void * private; + MclAdapterDesc* adapter; + void* private; } ``` @@ -99,14 +99,14 @@ typedef struct MclModelDesc { ```c typedef struct MclStrategyDesc { - const char * name; + const char* name; double model_time; double stop_time; MclExecuteMethod execute; MclExecuteHandler execute_func; MclMarshallOutHandler marshall_out_func; MclMarshallInHandler marshall_in_func; - MclInstanceDesc * mcl_instance; + MclInstanceDesc* mcl_instance; } ``` diff --git a/doc/content/apis/modelc/model/index.md b/doc/content/apis/modelc/model/index.md index 087ab1d..6f94ba7 100644 --- a/doc/content/apis/modelc/model/index.md +++ b/doc/content/apis/modelc/model/index.md @@ -100,9 +100,9 @@ center footer Dynamic Simulation Environment typedef struct ModelDesc { ModelVTable vtable; ModelIndex index; - SimulationSpec * sim; - ModelInstanceSpec * mi; - SignalVector * sv; + SimulationSpec* sim; + ModelInstanceSpec* mi; + SignalVector* sv; } ``` @@ -110,9 +110,9 @@ typedef struct ModelDesc { ```c typedef struct ModelSignalIndex { - SignalVector * sv; - double * scalar; - void ** binary; + SignalVector* sv; + double* scalar; + void** binary; uint32_t vector; uint32_t signal; } @@ -133,18 +133,18 @@ typedef struct ModelVTable { ```c typedef struct SignalVector { - const char * name; - const char * alias; - const char * function_name; + const char* name; + const char* alias; + const char* function_name; _Bool is_binary; uint32_t count; - const char ** signal; + const char** signal; BinarySignalAppendFunc append; BinarySignalResetFunc reset; BinarySignalReleaseFunc release; SignalAnnotationGetFunc annotation; BinarySignalCodecFunc codec; - ModelInstanceSpec * mi; + ModelInstanceSpec* mi; } ``` diff --git a/doc/content/apis/modelc/runtime/index.md b/doc/content/apis/modelc/runtime/index.md index 241facf..fd5feea 100644 --- a/doc/content/apis/modelc/runtime/index.md +++ b/doc/content/apis/modelc/runtime/index.md @@ -17,9 +17,9 @@ which can be used to load, configure and execute a model. ```c typedef struct ChannelSpec { - const char * name; - const char * alias; - void * private; + const char* name; + const char* alias; + void* private; } ``` @@ -27,19 +27,19 @@ typedef struct ChannelSpec { ```c typedef struct ModelCArguments { - const char * transport; - char * uri; - const char * host; + const char* transport; + char* uri; + const char* host; int port; double timeout; int log_level; double step_size; double end_time; int uid; - const char * name; - const char * file; - const char * path; - void * yaml_doc_list; + const char* name; + const char* file; + const char* path; + void* yaml_doc_list; int timeout_set_by_cli; int log_level_set_by_cli; int steps; @@ -50,16 +50,16 @@ typedef struct ModelCArguments { ```c typedef struct ModelChannelDesc { - const char * name; - const char * function_name; - const char ** signal_names; + const char* name; + const char* function_name; + const char** signal_names; int signal_count; int propagator_source_channel; int propagator_target_channel; - double * vector_double; - void ** vector_binary; - int * vector_binary_size; - int * vector_binary_buffer_size; + double* vector_double; + void** vector_binary; + int* vector_binary_size; + int* vector_binary_buffer_size; } ``` @@ -67,12 +67,12 @@ typedef struct ModelChannelDesc { ```c typedef struct ModelDefinitionSpec { - const char * name; - const char * path; - const char * file; - char * full_path; - void * doc; - void * channels; + const char* name; + const char* path; + const char* file; + char* full_path; + void* doc; + void* channels; } ``` @@ -81,12 +81,12 @@ typedef struct ModelDefinitionSpec { ```c typedef struct ModelInstanceSpec { int uid; - char * name; - int * model_desc; + char* name; + int* model_desc; ModelDefinitionSpec model_definition; - void * spec; - void * yaml_doc_list; - void * private; + void* spec; + void* yaml_doc_list; + void* private; } ``` @@ -94,13 +94,13 @@ typedef struct ModelInstanceSpec { ```c typedef struct SimulationSpec { - const char * transport; - char * uri; + const char* transport; + char* uri; int uid; double timeout; double step_size; double end_time; - ModelInstanceSpec * instance_list; + ModelInstanceSpec* instance_list; } ``` diff --git a/doc/content/apis/modelc/schema/index.md b/doc/content/apis/modelc/schema/index.md index 8fbf730..eb1f9b0 100644 --- a/doc/content/apis/modelc/schema/index.md +++ b/doc/content/apis/modelc/schema/index.md @@ -16,8 +16,8 @@ documents which represent (some of) the Schemas of the Model C Library. ```c typedef struct SchemaLabel { - const char * name; - const char * value; + const char* name; + const char* value; } ``` @@ -25,10 +25,10 @@ typedef struct SchemaLabel { ```c typedef struct SchemaObject { - const char * kind; - const char * name; - void * doc; - void * data; + const char* kind; + const char* name; + void* doc; + void* data; } ``` @@ -36,11 +36,11 @@ typedef struct SchemaObject { ```c typedef struct SchemaObjectSelector { - const char * kind; - const char * name; - SchemaLabel * labels; + const char* kind; + const char* name; + SchemaLabel* labels; int labels_len; - void * data; + void* data; } ``` @@ -48,8 +48,8 @@ typedef struct SchemaObjectSelector { ```c typedef struct SchemaSignalObject { - const char * signal; - void * data; + const char* signal; + void* data; } ``` diff --git a/doc/content/apis/modelc/simmock/index.md b/doc/content/apis/modelc/simmock/index.md index aa5f29f..eec4c3b 100644 --- a/doc/content/apis/modelc/simmock/index.md +++ b/doc/content/apis/modelc/simmock/index.md @@ -96,7 +96,7 @@ center footer Dynamic Simulation Environment ```c typedef struct BinaryCheck { int index; - int * buffer; + int* buffer; int len; } ``` @@ -116,11 +116,11 @@ typedef struct FrameCheck { ```c typedef struct ModelMock { - const char * name; - int * mi; - int * sv_signal; - int * sv_network; - int * sv_save; + const char* name; + int* mi; + int* sv_signal; + int* sv_network; + int* sv_save; int vtable; } ``` @@ -140,12 +140,12 @@ typedef struct SignalCheck { typedef struct SimMock { int sim; double step_size; - ModelMock * model; - void * doc_list; + ModelMock* model; + void* doc_list; double model_time; - int * sv_signal; - int * sv_network_rx; - int * sv_network_tx; + int* sv_signal; + int* sv_network_rx; + int* sv_network_tx; } ``` diff --git a/doc/content/docs/devel/modelc_ncodec.md b/doc/content/docs/devel/modelc_ncodec/index.md similarity index 60% rename from doc/content/docs/devel/modelc_ncodec.md rename to doc/content/docs/devel/modelc_ncodec/index.md index b2b9f30..37963c7 100644 --- a/doc/content/docs/devel/modelc_ncodec.md +++ b/doc/content/docs/devel/modelc_ncodec/index.md @@ -94,66 +94,17 @@ spec: Additional configuration information is available [here](https://github.com/boschglobal/dse.standards/blob/main/dse/ncodec/libs/automotive-bus/README.md). Especially the behaviour of `bus_id`,`node_id`and `interface_id` configuration items are described. - Configuration items can also be set at runtime with the `ncodec_config()` API as the following example shows: -```c -#include -#include - - -static void _setup_node_id(SignalVector* sv, uint32_t idx) -{ - const char* v = sv->annotation(sv, idx, "node_id"); - if (v) { - NCODEC* nc = sv->codec(sv, idx); - ncodec_config(nc, (struct NCodecConfigItem){ - .name = "node_id", - .value = v, - }); - } -} -``` +{{< readfile file="../../examples/modelc/ncodec/ncodec_config.c" code="true" lang="c" >}} + ### Usage in Model Code The Network Codec integration is fairly easy to use. The general approach is as follows: -```c -#include -#include - - -void do_bus_rx(SignalVector* sv, uint32_t idx) -{ - NCODEC* nc = sv->codec(sv, idx); - - while (1) { - NCodecMessage msg = {}; - len = ncodec_read(nc, &msg); - if (len < 0) break; - put_rx_frame_to_queue(msg.frame_id, msg.buffer, msg.len); - } -} - -void do_bus_tx(SignalVector* sv, uint32_t idx) -{ - uint32_t id; - uint8_t* msg; - size_t len; - NCODEC* nc = sv->codec(sv, idx); - - while (get_tx_frame_from_queue(&id, &msg, &len)) { - ncodec_write(nc, &(struct NCodecMessage){ - .frame_id = id, - .buffer = msg, - .len = len, - }); - } - ncodec_flush(nc); -} +{{< readfile file="../../examples/modelc/ncodec/ncodec_model.c" code="true" lang="c" >}} -``` ### Usage in Test Cases @@ -163,60 +114,4 @@ particularly useful for testing messaging behaviour of a model under specific circumstances. When doing this its necessary to circumvent the `node_id` filtering of that codec, as the following example illustrates. -```c -#include -#include -#include - - -char* get_ncodec_node_id(NCODEC* nc) -{ - assert_non_null(nc); - int index = 0; - char* node_id = NULL; - while (index >= 0) { - NCodecConfigItem ci = ncodec_stat(nc, &index); - if (strcmp(ci.name, "node_id") == 0) { - node_id = ci.value; - break; - } - index++; - } - if (node_id) return strdup(node_id); - return NULL; -} - -void set_ncodec_node_id(NCODEC* nc, char* node_id) -{ - assert_non_null(nc); - ncodec_config(nc, (struct NCodecConfigItem){ - .name = "node_id", - .value = node_id, - }); -} - -void test_message_sequence(void** state) -{ - ModelCMock* mock = *state; - NCODEC* nc = sv->codec(sv, idx); - - // ... - - // Modify the node_id. - char* node_id_save = get_ncodec_node_id(nc); - set_ncodec_node_id(nc, "42"); - // Send a message (which will not be filtered). - ncodec_write(nc, &(struct NCodecMessage){ - .frame_id = frame_id, - .buffer = data, - .len = len, - }); - ncodec_flush(nc); - // Restore the existing node_id. - set_ncodec_node_id(nc, node_id_save); - free(node_id_save); - - // ... -} - -``` +{{< readfile file="../../examples/modelc/ncodec/ncodec_test.c" code="true" lang="c" >}} diff --git a/doc/content/docs/devel/modelc_simmock/index.md b/doc/content/docs/devel/modelc_simmock/index.md index 7ce9010..8d4fe38 100644 --- a/doc/content/docs/devel/modelc_simmock/index.md +++ b/doc/content/docs/devel/modelc_simmock/index.md @@ -26,9 +26,9 @@ Model Developer is able to easily develop CMocka Testcases which: ### Example Test Files
-tests/cmocka/network/test_network.c +network/test_network.c -{{< readfile file="examples/tests/cmocka/network/test_network.c" code="true" lang="c" >}} +{{< readfile file="../../examples/modelc/mocks/network/test_network.c" code="true" lang="c" >}}
diff --git a/doc/content/docs/devel/modelc_simmock/examples/tests/cmocka/network/test_network.c b/doc/content/docs/examples/modelc/mocks/network/test_network.c similarity index 84% rename from doc/content/docs/devel/modelc_simmock/examples/tests/cmocka/network/test_network.c rename to doc/content/docs/examples/modelc/mocks/network/test_network.c index 8877b34..c988054 100644 --- a/doc/content/docs/devel/modelc_simmock/examples/tests/cmocka/network/test_network.c +++ b/doc/content/docs/examples/modelc/mocks/network/test_network.c @@ -1,11 +1,6 @@ -// Copyright 2023 Robert Bosch GmbH - #include #include -#include -#include -#include - +#include static int test_setup(void** state) { @@ -25,7 +20,7 @@ static int test_setup(void** state) }; SimMock* mock = simmock_alloc(inst_names, ARRAY_SIZE(inst_names)); simmock_configure(mock, argv, ARRAY_SIZE(argv), ARRAY_SIZE(inst_names)); - simmock_load(mock, true); + simmock_load(mock); simmock_setup(mock, "signal", "network"); /* Return the mock. */ @@ -33,7 +28,6 @@ static int test_setup(void** state) return 0; } - static int test_teardown(void** state) { SimMock* mock = *state; @@ -42,7 +36,6 @@ static int test_teardown(void** state) return 0; } - #define SIG_reset_counters 0 #define SIG_task_init_done 1 #define SIG_task_5_active 2 @@ -54,10 +47,9 @@ static int test_teardown(void** state) #define SIG_task_20_counter 8 #define SIG_task_40_counter 9 - void test_network__network2target2network(void** state) { - SimMock* mock = *state; + SimMock* mock = *state; ModelMock* network_model = &mock->model[1]; assert_non_null(network_model); @@ -75,8 +67,10 @@ void test_network__network2target2network(void** state) { .index = SIG_task_20_active, .value = 0.0 }, { .index = SIG_task_20_counter, .value = 0.0 }, }; - simmock_signal_check(mock, "target_inst", s_checks, ARRAY_SIZE(s_checks), NULL); - simmock_signal_check(mock, "network_inst", s_checks, ARRAY_SIZE(s_checks), NULL); + simmock_signal_check( + mock, "target_inst", s_checks, ARRAY_SIZE(s_checks), NULL); + simmock_signal_check( + mock, "network_inst", s_checks, ARRAY_SIZE(s_checks), NULL); } /* Inject a message carrying the reset_counters signal. */ uint8_t buffer[8] = { 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; @@ -106,18 +100,20 @@ void test_network__network2target2network(void** state) simmock_print_scalar_signals(mock, LOG_DEBUG); simmock_print_network_frames(mock, LOG_DEBUG); assert_int_equal(network_model->sv_network->length[0] > 0, true); - simmock_signal_check(mock, "network_inst", s_checks, ARRAY_SIZE(s_checks), NULL); - simmock_frame_check(mock, "network_inst", "can_bus", f_checks, ARRAY_SIZE(f_checks)); + simmock_signal_check( + mock, "network_inst", s_checks, ARRAY_SIZE(s_checks), NULL); + simmock_frame_check( + mock, "network_inst", "can_bus", f_checks, ARRAY_SIZE(f_checks)); } } - int run_network_tests(void) { - void* s = test_setup; - void* t = test_teardown; + void* s = test_setup; + void* t = test_teardown; const struct CMUnitTest tests[] = { - cmocka_unit_test_setup_teardown(test_network__network2target2network, s, t), + cmocka_unit_test_setup_teardown( + test_network__network2target2network, s, t), }; return cmocka_run_group_tests_name("NETWORK", tests, NULL, NULL); } diff --git a/doc/content/docs/examples/modelc/ncodec/ncodec_config.c b/doc/content/docs/examples/modelc/ncodec/ncodec_config.c new file mode 100644 index 0000000..b4d3c49 --- /dev/null +++ b/doc/content/docs/examples/modelc/ncodec/ncodec_config.c @@ -0,0 +1,14 @@ +#include +#include + +void _setup_node_id(SignalVector* sv, uint32_t idx) +{ + const char* v = sv->annotation(sv, idx, "node_id"); + if (v) { + NCODEC* nc = sv->codec(sv, idx); + ncodec_config(nc, (struct NCodecConfigItem){ + .name = "node_id", + .value = v, + }); + } +} \ No newline at end of file diff --git a/doc/content/docs/examples/modelc/ncodec/ncodec_model.c b/doc/content/docs/examples/modelc/ncodec/ncodec_model.c new file mode 100644 index 0000000..9dd8210 --- /dev/null +++ b/doc/content/docs/examples/modelc/ncodec/ncodec_model.c @@ -0,0 +1,34 @@ +#include +#include + +extern int put_rx_frame_to_queue(uint32_t, uint8_t*, size_t); +extern int get_tx_frame_from_queue(uint32_t*, uint8_t**, size_t*); + +void do_bus_rx(SignalVector* sv, uint32_t idx) +{ + NCODEC* nc = sv->codec(sv, idx); + + while (1) { + NCodecMessage msg = {}; + int len = ncodec_read(nc, &msg); + if (len < 0) break; + put_rx_frame_to_queue(msg.frame_id, msg.buffer, msg.len); + } +} + +void do_bus_tx(SignalVector* sv, uint32_t idx) +{ + uint32_t id; + uint8_t* msg; + size_t len; + NCODEC* nc = sv->codec(sv, idx); + + while (get_tx_frame_from_queue(&id, &msg, &len)) { + ncodec_write(nc, &(struct NCodecMessage){ + .frame_id = id, + .buffer = msg, + .len = len, + }); + } + ncodec_flush(nc); +} diff --git a/doc/content/docs/examples/modelc/ncodec/ncodec_test.c b/doc/content/docs/examples/modelc/ncodec/ncodec_test.c new file mode 100644 index 0000000..99afe6a --- /dev/null +++ b/doc/content/docs/examples/modelc/ncodec/ncodec_test.c @@ -0,0 +1,60 @@ +#include +#include +#include + +typedef struct ModelCMock { + SimulationSpec sim; + ModelInstanceSpec* mi; +} ModelCMock; + +char* get_ncodec_node_id(NCODEC* nc) +{ + assert_non_null(nc); + int index = 0; + const char* node_id = NULL; + while (index >= 0) { + NCodecConfigItem ci = ncodec_stat(nc, &index); + if (strcmp(ci.name, "node_id") == 0) { + node_id = ci.value; + break; + } + index++; + } + if (node_id) return strdup(node_id); + return NULL; +} + +void set_ncodec_node_id(NCODEC* nc, const char* node_id) +{ + assert_non_null(nc); + ncodec_config(nc, (struct NCodecConfigItem){ + .name = "node_id", + .value = node_id, + }); +} + +void test_message_sequence(void** state) +{ + ModelCMock* mock = *state; + SignalVector* sv = mock->mi->model_desc->sv; + NCODEC* nc = sv->codec(sv, 2); + const char* buffer = "hello world"; + + // ... + + // Modify the node_id. + char* node_id_save = get_ncodec_node_id(nc); + set_ncodec_node_id(nc, "42"); + // Send a message (which will not be filtered). + ncodec_write(nc, &(struct NCodecMessage){ + .frame_id = 42, + .buffer = (uint8_t*)buffer, + .len = strlen(buffer), + }); + ncodec_flush(nc); + // Restore the existing node_id. + set_ncodec_node_id(nc, node_id_save); + free(node_id_save); + + // ... +} diff --git a/dse/mocks/CMakeLists.txt b/dse/mocks/CMakeLists.txt index 2583c7f..268d972 100644 --- a/dse/mocks/CMakeLists.txt +++ b/dse/mocks/CMakeLists.txt @@ -26,3 +26,9 @@ target_include_directories(mocks ${DSE_NCODEC_INCLUDE_DIR} ../.. ) + + +# Code examples for documentation. +if(UNIX) +add_subdirectory(examples) +endif() diff --git a/dse/mocks/examples/CMakeLists.txt b/dse/mocks/examples/CMakeLists.txt new file mode 100644 index 0000000..dafb229 --- /dev/null +++ b/dse/mocks/examples/CMakeLists.txt @@ -0,0 +1,58 @@ +# Copyright 2024 Robert Bosch GmbH +# +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.21) + +set(VERSION "$ENV{PACKAGE_VERSION}") + +project(examples DESCRIPTION "ModelC - Example Code") + +set(CMAKE_C_STANDARD 99) +set(CMAKE_C_STANDARD_REQUIRED TRUE) +set(CMAKE_POSITION_INDEPENDENT_CODE ON) +set(CMAKE_C_FLAGS_DEBUG "-g -ggdb") +set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -O3") +list(APPEND C_CXX_WARNING_FLAGS + -Wall + -W + -Wwrite-strings + -Wno-missing-field-initializers + -Wno-misleading-indentation +) +add_compile_options(${C_CXX_WARNING_FLAGS}) + + +include(FetchContent) + +# External Project - DSE C Lib +# ---------------------------- +FetchContent_Declare(dse_clib + URL $ENV{DSE_CLIB_URL} + HTTP_USERNAME $ENV{GHE_USER} + HTTP_PASSWORD $ENV{GHE_TOKEN} +) +FetchContent_MakeAvailable(dse_clib) +set(DSE_CLIB_SOURCE_DIR ${dse_clib_SOURCE_DIR}/dse) +set(DSE_CLIB_SOURCE_FILES ) +set(DSE_CLIB_INCLUDE_DIR "${DSE_CLIB_SOURCE_DIR}/..") + + + +# Targets +# ======= + +# APIs +# ---- +add_library(examples OBJECT + network/test_network.c +) +target_include_directories(examples + PRIVATE + ${DSE_CLIB_INCLUDE_DIR} + ../../.. +) +target_compile_definitions(examples + PUBLIC + CMOCKA_TESTING +) diff --git a/dse/mocks/examples/network/test_network.c b/dse/mocks/examples/network/test_network.c new file mode 100644 index 0000000..c988054 --- /dev/null +++ b/dse/mocks/examples/network/test_network.c @@ -0,0 +1,119 @@ +#include +#include +#include + +static int test_setup(void** state) +{ + const char* inst_names[] = { + "target_inst", + "network_inst", + }; + char* argv[] = { + (char*)"test_runnable", + (char*)"--name=target_inst;network_inst", + (char*)"--logger=5", // 1=debug, 5=QUIET (commit with 5!) + (char*)"../../../../tests/cmocka/network/stack.yaml", + (char*)"../../../../tests/cmocka/network/signalgroup.yaml", + (char*)"../../../../tests/cmocka/network/network.yaml", + (char*)"../../../../tests/cmocka/network/model.yaml", + (char*)"../../../../tests/cmocka/network/runnable.yaml", + }; + SimMock* mock = simmock_alloc(inst_names, ARRAY_SIZE(inst_names)); + simmock_configure(mock, argv, ARRAY_SIZE(argv), ARRAY_SIZE(inst_names)); + simmock_load(mock); + simmock_setup(mock, "signal", "network"); + + /* Return the mock. */ + *state = mock; + return 0; +} + +static int test_teardown(void** state) +{ + SimMock* mock = *state; + simmock_exit(mock); + simmock_free(mock); + return 0; +} + +#define SIG_reset_counters 0 +#define SIG_task_init_done 1 +#define SIG_task_5_active 2 +#define SIG_task_10_active 3 +#define SIG_task_20_active 4 +#define SIG_task_40_active 5 +#define SIG_task_5_counter 6 +#define SIG_task_10_counter 7 +#define SIG_task_20_counter 8 +#define SIG_task_40_counter 9 + +void test_network__network2target2network(void** state) +{ + SimMock* mock = *state; + ModelMock* network_model = &mock->model[1]; + assert_non_null(network_model); + + /* 0-19.5ms */ + { + for (uint32_t i = 0; i < 39; i++) { + assert_int_equal(simmock_step(mock, true), 0); + } + SignalCheck s_checks[] = { + { .index = SIG_task_init_done, .value = 1.0 }, + { .index = SIG_task_5_active, .value = 1.0 }, + { .index = SIG_task_5_counter, .value = 3.0 }, + { .index = SIG_task_10_active, .value = 1.0 }, + { .index = SIG_task_10_counter, .value = 1.0 }, + { .index = SIG_task_20_active, .value = 0.0 }, + { .index = SIG_task_20_counter, .value = 0.0 }, + }; + simmock_signal_check( + mock, "target_inst", s_checks, ARRAY_SIZE(s_checks), NULL); + simmock_signal_check( + mock, "network_inst", s_checks, ARRAY_SIZE(s_checks), NULL); + } + /* Inject a message carrying the reset_counters signal. */ + uint8_t buffer[8] = { 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + simmock_write_frame(mock->sv_network_tx, "can_bus", buffer, 8, 0x1f0u); + assert_int_equal(simmock_step(mock, true), 0); + /* 20ms */ + { + for (uint32_t i = 0; i < 1; i++) { + assert_int_equal(simmock_step(mock, true), 0); + } + SignalCheck s_checks[] = { + { .index = SIG_task_init_done, .value = 1.0 }, + { .index = SIG_task_5_active, .value = 1.0 }, + { .index = SIG_task_5_counter, .value = 1.0 }, + { .index = SIG_task_10_active, .value = 1.0 }, + { .index = SIG_task_10_counter, .value = 1.0 }, + { .index = SIG_task_20_active, .value = 1.0 }, + { .index = SIG_task_20_counter, .value = 1.0 }, + }; + FrameCheck f_checks[] = { + { .frame_id = 0x1f4u, .offset = 1, .value = 0x02 }, + { .frame_id = 0x1f4u, .offset = 2, .value = 0x02 }, + { .frame_id = 0x1f4u, .offset = 3, .value = 0x02 }, + { .frame_id = 0x1f5u, .offset = 4, .value = 0x02 }, + { .frame_id = 0x1f7u, .offset = 4, .value = 0x02 }, + }; + simmock_print_scalar_signals(mock, LOG_DEBUG); + simmock_print_network_frames(mock, LOG_DEBUG); + assert_int_equal(network_model->sv_network->length[0] > 0, true); + simmock_signal_check( + mock, "network_inst", s_checks, ARRAY_SIZE(s_checks), NULL); + simmock_frame_check( + mock, "network_inst", "can_bus", f_checks, ARRAY_SIZE(f_checks)); + } +} + +int run_network_tests(void) +{ + void* s = test_setup; + void* t = test_teardown; + const struct CMUnitTest tests[] = { + cmocka_unit_test_setup_teardown( + test_network__network2target2network, s, t), + }; + return cmocka_run_group_tests_name("NETWORK", tests, NULL, NULL); +} diff --git a/dse/modelc/examples/CMakeLists.txt b/dse/modelc/examples/CMakeLists.txt index 60b7564..cc90928 100644 --- a/dse/modelc/examples/CMakeLists.txt +++ b/dse/modelc/examples/CMakeLists.txt @@ -14,5 +14,5 @@ add_subdirectory(gateway) # Code examples for documentation. if(UNIX) -add_subdirectory(apis) +add_subdirectory(doc) endif() diff --git a/dse/modelc/examples/doc/CMakeLists.txt b/dse/modelc/examples/doc/CMakeLists.txt new file mode 100644 index 0000000..7c4fe16 --- /dev/null +++ b/dse/modelc/examples/doc/CMakeLists.txt @@ -0,0 +1,8 @@ +# Copyright 2024 Robert Bosch GmbH +# +# SPDX-License-Identifier: Apache-2.0 + +if(UNIX) +add_subdirectory(apis) +add_subdirectory(docs) +endif() diff --git a/dse/modelc/examples/apis/CMakeLists.txt b/dse/modelc/examples/doc/apis/CMakeLists.txt similarity index 98% rename from dse/modelc/examples/apis/CMakeLists.txt rename to dse/modelc/examples/doc/apis/CMakeLists.txt index ee73a29..ec64831 100644 --- a/dse/modelc/examples/apis/CMakeLists.txt +++ b/dse/modelc/examples/doc/apis/CMakeLists.txt @@ -57,7 +57,7 @@ add_library(apis OBJECT target_include_directories(apis PRIVATE ${DSE_CLIB_INCLUDE_DIR} - ../../../.. + ../../../../.. ) target_compile_definitions(apis PUBLIC diff --git a/dse/modelc/examples/apis/model_create.c b/dse/modelc/examples/doc/apis/model_create.c similarity index 100% rename from dse/modelc/examples/apis/model_create.c rename to dse/modelc/examples/doc/apis/model_create.c diff --git a/dse/modelc/examples/apis/model_interface.c b/dse/modelc/examples/doc/apis/model_interface.c similarity index 100% rename from dse/modelc/examples/apis/model_interface.c rename to dse/modelc/examples/doc/apis/model_interface.c diff --git a/dse/modelc/examples/apis/schema_object_search.c b/dse/modelc/examples/doc/apis/schema_object_search.c similarity index 100% rename from dse/modelc/examples/apis/schema_object_search.c rename to dse/modelc/examples/doc/apis/schema_object_search.c diff --git a/dse/modelc/examples/apis/signalvector_annotation.c b/dse/modelc/examples/doc/apis/signalvector_annotation.c similarity index 100% rename from dse/modelc/examples/apis/signalvector_annotation.c rename to dse/modelc/examples/doc/apis/signalvector_annotation.c diff --git a/dse/modelc/examples/apis/signalvector_interface.c b/dse/modelc/examples/doc/apis/signalvector_interface.c similarity index 100% rename from dse/modelc/examples/apis/signalvector_interface.c rename to dse/modelc/examples/doc/apis/signalvector_interface.c diff --git a/dse/modelc/examples/apis/simmock_configure.c b/dse/modelc/examples/doc/apis/simmock_configure.c similarity index 100% rename from dse/modelc/examples/apis/simmock_configure.c rename to dse/modelc/examples/doc/apis/simmock_configure.c diff --git a/dse/modelc/examples/apis/simmock_frame_check.c b/dse/modelc/examples/doc/apis/simmock_frame_check.c similarity index 100% rename from dse/modelc/examples/apis/simmock_frame_check.c rename to dse/modelc/examples/doc/apis/simmock_frame_check.c diff --git a/dse/modelc/examples/apis/simmock_signal_check.c b/dse/modelc/examples/doc/apis/simmock_signal_check.c similarity index 100% rename from dse/modelc/examples/apis/simmock_signal_check.c rename to dse/modelc/examples/doc/apis/simmock_signal_check.c diff --git a/dse/modelc/examples/doc/docs/CMakeLists.txt b/dse/modelc/examples/doc/docs/CMakeLists.txt new file mode 100644 index 0000000..9602cc4 --- /dev/null +++ b/dse/modelc/examples/doc/docs/CMakeLists.txt @@ -0,0 +1,67 @@ +# Copyright 2024 Robert Bosch GmbH +# +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.21) + +set(VERSION "$ENV{PACKAGE_VERSION}") + +project(apis DESCRIPTION "ModelC - Example Code") + +set(CMAKE_C_STANDARD 99) +set(CMAKE_C_STANDARD_REQUIRED TRUE) +set(CMAKE_POSITION_INDEPENDENT_CODE ON) +set(CMAKE_C_FLAGS_DEBUG "-g -ggdb") +set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -O3") +list(APPEND C_CXX_WARNING_FLAGS + -Wall + -W + -Wwrite-strings + -Wno-missing-field-initializers + -Wno-misleading-indentation +) +add_compile_options(${C_CXX_WARNING_FLAGS}) + + +include(FetchContent) + +# External Project - DSE C Lib +# ---------------------------- +FetchContent_Declare(dse_clib + URL $ENV{DSE_CLIB_URL} + HTTP_USERNAME $ENV{GHE_USER} + HTTP_PASSWORD $ENV{GHE_TOKEN} +) +FetchContent_MakeAvailable(dse_clib) +set(DSE_CLIB_SOURCE_DIR ${dse_clib_SOURCE_DIR}/dse) +set(DSE_CLIB_SOURCE_FILES ) +set(DSE_CLIB_INCLUDE_DIR "${DSE_CLIB_SOURCE_DIR}/..") + + +# External Project - DSE Network Codec +# ------------------------------------ +set(DSE_NCODEC_SOURCE_DIR "$ENV{EXTERNAL_BUILD_DIR}/dse_ncodec") +set(DSE_NCODEC_INCLUDE_DIR "${DSE_NCODEC_SOURCE_DIR}") + + + +# Targets +# ======= + +# APIs +# ---- +add_library(docs OBJECT + ncodec/ncodec_config.c + ncodec/ncodec_model.c + ncodec/ncodec_test.c +) +target_include_directories(docs + PRIVATE + ${DSE_CLIB_INCLUDE_DIR} + ${DSE_NCODEC_INCLUDE_DIR} + ../../../../.. +) +target_compile_definitions(docs + PUBLIC + CMOCKA_TESTING +) diff --git a/dse/modelc/examples/doc/docs/ncodec/ncodec_config.c b/dse/modelc/examples/doc/docs/ncodec/ncodec_config.c new file mode 100644 index 0000000..b4d3c49 --- /dev/null +++ b/dse/modelc/examples/doc/docs/ncodec/ncodec_config.c @@ -0,0 +1,14 @@ +#include +#include + +void _setup_node_id(SignalVector* sv, uint32_t idx) +{ + const char* v = sv->annotation(sv, idx, "node_id"); + if (v) { + NCODEC* nc = sv->codec(sv, idx); + ncodec_config(nc, (struct NCodecConfigItem){ + .name = "node_id", + .value = v, + }); + } +} \ No newline at end of file diff --git a/dse/modelc/examples/doc/docs/ncodec/ncodec_model.c b/dse/modelc/examples/doc/docs/ncodec/ncodec_model.c new file mode 100644 index 0000000..9dd8210 --- /dev/null +++ b/dse/modelc/examples/doc/docs/ncodec/ncodec_model.c @@ -0,0 +1,34 @@ +#include +#include + +extern int put_rx_frame_to_queue(uint32_t, uint8_t*, size_t); +extern int get_tx_frame_from_queue(uint32_t*, uint8_t**, size_t*); + +void do_bus_rx(SignalVector* sv, uint32_t idx) +{ + NCODEC* nc = sv->codec(sv, idx); + + while (1) { + NCodecMessage msg = {}; + int len = ncodec_read(nc, &msg); + if (len < 0) break; + put_rx_frame_to_queue(msg.frame_id, msg.buffer, msg.len); + } +} + +void do_bus_tx(SignalVector* sv, uint32_t idx) +{ + uint32_t id; + uint8_t* msg; + size_t len; + NCODEC* nc = sv->codec(sv, idx); + + while (get_tx_frame_from_queue(&id, &msg, &len)) { + ncodec_write(nc, &(struct NCodecMessage){ + .frame_id = id, + .buffer = msg, + .len = len, + }); + } + ncodec_flush(nc); +} diff --git a/dse/modelc/examples/doc/docs/ncodec/ncodec_test.c b/dse/modelc/examples/doc/docs/ncodec/ncodec_test.c new file mode 100644 index 0000000..99afe6a --- /dev/null +++ b/dse/modelc/examples/doc/docs/ncodec/ncodec_test.c @@ -0,0 +1,60 @@ +#include +#include +#include + +typedef struct ModelCMock { + SimulationSpec sim; + ModelInstanceSpec* mi; +} ModelCMock; + +char* get_ncodec_node_id(NCODEC* nc) +{ + assert_non_null(nc); + int index = 0; + const char* node_id = NULL; + while (index >= 0) { + NCodecConfigItem ci = ncodec_stat(nc, &index); + if (strcmp(ci.name, "node_id") == 0) { + node_id = ci.value; + break; + } + index++; + } + if (node_id) return strdup(node_id); + return NULL; +} + +void set_ncodec_node_id(NCODEC* nc, const char* node_id) +{ + assert_non_null(nc); + ncodec_config(nc, (struct NCodecConfigItem){ + .name = "node_id", + .value = node_id, + }); +} + +void test_message_sequence(void** state) +{ + ModelCMock* mock = *state; + SignalVector* sv = mock->mi->model_desc->sv; + NCODEC* nc = sv->codec(sv, 2); + const char* buffer = "hello world"; + + // ... + + // Modify the node_id. + char* node_id_save = get_ncodec_node_id(nc); + set_ncodec_node_id(nc, "42"); + // Send a message (which will not be filtered). + ncodec_write(nc, &(struct NCodecMessage){ + .frame_id = 42, + .buffer = (uint8_t*)buffer, + .len = strlen(buffer), + }); + ncodec_flush(nc); + // Restore the existing node_id. + set_ncodec_node_id(nc, node_id_save); + free(node_id_save); + + // ... +} diff --git a/tests/cmocka/model/interface/__test__.c b/tests/cmocka/model/interface/__test__.c index 6d8403f..5e46027 100644 --- a/tests/cmocka/model/interface/__test__.c +++ b/tests/cmocka/model/interface/__test__.c @@ -1,7 +1,6 @@ // Copyright 2024 Robert Bosch GmbH // // SPDX-License-Identifier: Apache-2.0 -// SPDX-License-Identifier: BIOS-4.0 #include diff --git a/tests/cmocka/model/interface/test_model_interface.c b/tests/cmocka/model/interface/test_model_interface.c index 1f7cd1c..c1287e2 100644 --- a/tests/cmocka/model/interface/test_model_interface.c +++ b/tests/cmocka/model/interface/test_model_interface.c @@ -1,7 +1,6 @@ // Copyright 2024 Robert Bosch GmbH // // SPDX-License-Identifier: Apache-2.0 -// SPDX-License-Identifier: BIOS-4.0 #include #include