diff --git a/.github/workflows/unit-tests.yml b/.github/workflows/unit-tests.yml index fc8a7123d..1ced71f16 100644 --- a/.github/workflows/unit-tests.yml +++ b/.github/workflows/unit-tests.yml @@ -11,7 +11,7 @@ jobs: run: strategy: matrix: - platform: [ubuntu-latest, macos-latest, windows-latest] + platform: [ubuntu-latest, macos-latest] runs-on: ${{ matrix.platform }} steps: @@ -24,4 +24,13 @@ jobs: cd build cmake .. ${{ inputs.cmake-args }} cmake --build . - make test + sudo make test + - name: Run RTI unit tests + run: | + cd core/federated/RTI + mkdir build + cd build + cmake .. + cmake --build . + ctest + diff --git a/.gitignore b/.gitignore index b8237101d..d11ccaa7a 100644 --- a/.gitignore +++ b/.gitignore @@ -16,3 +16,6 @@ util/tracing/trace_to_csv.o util/tracing/trace_to_influxdb util/tracing/trace_to_influxdb.o util/tracing/trace_util.o + +# Generated trace lib +trace/**/*.a diff --git a/CMakeLists.txt b/CMakeLists.txt index 8a916023f..186e5b670 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -22,10 +22,6 @@ if(DEFINED LF_SINGLE_THREADED) add_compile_definitions(LF_SINGLE_THREADED=1) endif() -# Warnings as errors -add_compile_options(-Werror) - -set(Test test) set(Lib lib) set(CoreLibPath core) set(CoreLib reactor-c) @@ -42,7 +38,6 @@ include_directories(${CMAKE_SOURCE_DIR}/include/core/utils) include_directories(${CMAKE_SOURCE_DIR}/include/api) enable_testing() -add_subdirectory(${Test}) add_subdirectory(${Lib}) add_subdirectory(${CoreLibPath}) diff --git a/README.md b/README.md index 3d1313a1f..8c714a165 100644 --- a/README.md +++ b/README.md @@ -41,6 +41,11 @@ To run tests for the multithreaded runtime, provide a nonzero number of workers when invoking `cmake`. For example: - `cmake .. -DNUMBER_OF_WORKERS=2` +- `cmake --build .` +- `sudo make test` + +Note that one of the tests in the multithreaded test suite requires sudo because +it changes the scheduling policy and priorities. To define/undefine other preprocessor definitions such as `LOG_LEVEL`, pass them as arguments to `cmake` in the same way as with `NUMBER_OF_WORKERS`, using the same diff --git a/core/federated/RTI/CMakeLists.txt b/core/federated/RTI/CMakeLists.txt index 9c4f996d2..5bfbf0196 100644 --- a/core/federated/RTI/CMakeLists.txt +++ b/core/federated/RTI/CMakeLists.txt @@ -1,58 +1,15 @@ -# This is a cmake build script providing a solution for compiling -# the RTI in this directory.. -# -# Usage: -# -# To compile with cmake, run the following commands: -# -# $> mkdir build && cd build -# $> cmake ../ -# $> make -# $> sudo make install -# -# This create a binary RTI in the current working directory. Please put this in -# a directory that is on the path. -# -# To enable DEBUG messages, use the following build commands instead: -# -# $> mkdir build && cd build -# $> cmake -DCMAKE_BUILD_TYPE=DEBUG ../ -# $> make -# $> sudo make install -# -# If you would like to go back to non-DEBUG mode, you would have to remove all -# contents of the `build` folder. - -# To enable simple HMAC-based authentication of federates, -# add `-DAUTH=ON` option to the cmake command as shown below: -# -# $> mkdir build && cd build -# $> cmake -DAUTH=ON ../ -# $> make -# $> sudo make install -# -# If you would like to go back to non-AUTH mode, you would have to remove all -# contents of the `build` folder. - cmake_minimum_required(VERSION 3.12) project(RTI VERSION 1.0.0 LANGUAGES C) set(CoreLib ../../../core) set(LF_ROOT ${CMAKE_CURRENT_LIST_DIR}/../../..) - set(IncludeDir ../../../include/core) -include_directories(../../../include) -include_directories(${IncludeDir}) -include_directories(${IncludeDir}/federated) -include_directories(${IncludeDir}/federated/network) -include_directories(${IncludeDir}/modal_models) -include_directories(${IncludeDir}/utils) - - -# Declare a new executable target and list all its sources -add_executable( - RTI - main.c +set(RTI_LIB rti_lib) +set(RTI_MAIN RTI) + +# Add common RTI functionality to a static library. This is done to simplify +# the building of unit tests. +add_library(${RTI_LIB} STATIC rti_common.c rti_remote.c ${CoreLib}/tracepoint.c @@ -64,6 +21,17 @@ add_executable( ${CoreLib}/utils/pqueue_tag.c ${CoreLib}/utils/pqueue.c ) + +# Add the main target which will link with the library. +add_executable(${RTI_MAIN} main.c) + +target_include_directories(${RTI_LIB} PUBLIC ../../../include) +target_include_directories(${RTI_LIB} PUBLIC ${IncludeDir}) +target_include_directories(${RTI_LIB} PUBLIC ${IncludeDir}/federated) +target_include_directories(${RTI_LIB} PUBLIC ${IncludeDir}/federated/network) +target_include_directories(${RTI_LIB} PUBLIC ${IncludeDir}/modal_models) +target_include_directories(${RTI_LIB} PUBLIC ${IncludeDir}/utils) + if (NOT DEFINED LOG_LEVEL) set(LOG_LEVEL 0) ENDIF(NOT DEFINED LOG_LEVEL) @@ -73,62 +41,79 @@ IF(CMAKE_BUILD_TYPE MATCHES DEBUG) message("-- Building RTI with DEBUG messages enabled") set(LOG_LEVEL 4) ENDIF(CMAKE_BUILD_TYPE MATCHES DEBUG) -target_compile_definitions(RTI PUBLIC LOG_LEVEL=${LOG_LEVEL}) +target_compile_definitions(${RTI_LIB} PUBLIC LOG_LEVEL=${LOG_LEVEL}) include(${LF_ROOT}/version/api/CMakeLists.txt) -target_link_libraries(RTI lf::version-api) +target_link_libraries(${RTI_LIB} PUBLIC lf::version-api) include(${LF_ROOT}/logging/api/CMakeLists.txt) -target_link_libraries(RTI lf::logging-api) +target_link_libraries(${RTI_LIB} PUBLIC lf::logging-api) include(${LF_ROOT}/tag/api/CMakeLists.txt) -target_link_libraries(RTI lf::tag-api) +target_link_libraries(${RTI_LIB} PUBLIC lf::tag-api) include(${LF_ROOT}/platform/api/CMakeLists.txt) -target_link_libraries(RTI lf::platform-api) +target_link_libraries(${RTI_LIB} PUBLIC lf::platform-api) include(${LF_ROOT}/platform/impl/CMakeLists.txt) -target_link_libraries(RTI lf::platform-impl) +target_link_libraries(${RTI_LIB} PUBLIC lf::platform-impl) include(${LF_ROOT}/trace/api/CMakeLists.txt) -target_link_libraries(RTI lf::trace-api) +target_link_libraries(${RTI_LIB} PUBLIC lf::trace-api) include(${LF_ROOT}/trace/impl/CMakeLists.txt) -target_link_libraries(RTI lf::trace-impl) +target_link_libraries(${RTI_LIB} PUBLIC lf::trace-impl) include(${LF_ROOT}/low_level_platform/impl/CMakeLists.txt) -target_link_libraries(RTI lf::low-level-platform-impl) +target_link_libraries(${RTI_LIB} PUBLIC lf::low-level-platform-impl) include(${LF_ROOT}/low_level_platform/api/CMakeLists.txt) -target_link_libraries(RTI lf::low-level-platform-api) +target_link_libraries(${RTI_LIB} PUBLIC lf::low-level-platform-api) # Set the STANDALONE_RTI flag to include the rti_remote and rti_common. -target_compile_definitions(RTI PUBLIC STANDALONE_RTI=1) +target_compile_definitions(${RTI_LIB} PUBLIC STANDALONE_RTI=1) # Set FEDERATED to get federated compilation support -target_compile_definitions(RTI PUBLIC FEDERATED=1) - -target_compile_definitions(RTI PUBLIC PLATFORM_${CMAKE_SYSTEM_NAME}) +target_compile_definitions(${RTI_LIB} PUBLIC FEDERATED=1) +target_compile_definitions(${RTI_LIB} PUBLIC PLATFORM_${CMAKE_SYSTEM_NAME}) # Set RTI Tracing -target_compile_definitions(RTI PUBLIC RTI_TRACE) +target_compile_definitions(${RTI_LIB} PUBLIC RTI_TRACE) # Warnings as errors -target_compile_options(RTI PUBLIC -Werror) +target_compile_options(${RTI_LIB} PUBLIC -Werror) + # Find threads and link to it find_package(Threads REQUIRED) -target_link_libraries(RTI Threads::Threads) +target_link_libraries(${RTI_LIB} PUBLIC Threads::Threads) # Option for enabling federate authentication by RTI. option(AUTH "Federate authentication by RTI enabled." OFF) IF(AUTH MATCHES ON) - add_compile_definitions(__RTI_AUTH__) + target_compile_definitions(${RTI_LIB} PUBLIC __RTI_AUTH__) # Find OpenSSL and link to it find_package(OpenSSL REQUIRED) - target_link_libraries(RTI OpenSSL::SSL) + target_link_libraries(${RTI_LIB} PUBLIC OpenSSL::SSL) ENDIF(AUTH MATCHES ON) +# Link the main target with the library. +target_link_libraries(${RTI_MAIN} PRIVATE ${RTI_LIB}) + install( TARGETS RTI DESTINATION bin ) + +# Build unit tests +enable_testing() +set(TEST_DIR ${CMAKE_CURRENT_SOURCE_DIR}/test) +set(TEST_SRCS + ${TEST_DIR}/rti_common_test.c +) +foreach(TEST_SRC ${TEST_SRCS}) + get_filename_component(TEST_NAME ${TEST_SRC} NAME_WE) + add_executable(${TEST_NAME} ${TEST_SRC}) + add_test(NAME ${TEST_NAME} COMMAND ${TEST_NAME}) + target_link_libraries(${TEST_NAME} PUBLIC ${RTI_LIB}) + target_include_directories(${TEST_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) +endforeach() diff --git a/core/federated/RTI/README.md b/core/federated/RTI/README.md index 916959f6e..cea8581c5 100644 --- a/core/federated/RTI/README.md +++ b/core/federated/RTI/README.md @@ -8,6 +8,11 @@ make sudo make install ``` +To run the unit tests +```bash +make test +``` + **Note:** To enable DEBUG messages, use the following build commands instead: ```bash @@ -47,3 +52,4 @@ docker login -u [username] ``` To authenticate, request a PAT on [DockerHub](https://hub.docker.com/settings/security). + diff --git a/test/RTI/rti_common_test.c b/core/federated/RTI/test/rti_common_test.c similarity index 99% rename from test/RTI/rti_common_test.c rename to core/federated/RTI/test/rti_common_test.c index 3d2c73af9..107d08057 100644 --- a/test/RTI/rti_common_test.c +++ b/core/federated/RTI/test/rti_common_test.c @@ -1,4 +1,3 @@ -#if defined STANDALONE_RTI #include #include #include @@ -246,7 +245,7 @@ static void multiple_nodes() { assert(lf_tag_compare(test_rti.scheduling_nodes[3]->min_delays[0].min_delay, (tag_t){NSEC(3), 0}) == 0); } -int main(int argc, char** argv) { +int main() { initialize_rti_common(&test_rti); // Tests for the function update_min_delays_upstream() @@ -257,4 +256,3 @@ int main(int argc, char** argv) { two_nodes_normal_delay(); multiple_nodes(); } -#endif \ No newline at end of file diff --git a/low_level_platform/api/low_level_platform.h b/low_level_platform/api/low_level_platform.h index 2867aa0f4..8494a4d85 100644 --- a/low_level_platform/api/low_level_platform.h +++ b/low_level_platform/api/low_level_platform.h @@ -162,7 +162,7 @@ typedef struct { * @param cpu_number the CPU ID * @return 0 on success, platform-specific error number otherwise. */ -int lf_thread_set_cpu(lf_thread_t thread, int cpu_number); +int lf_thread_set_cpu(lf_thread_t thread, size_t cpu_number); /** * @brief Set the priority of a thread. diff --git a/low_level_platform/impl/src/lf_linux_support.c b/low_level_platform/impl/src/lf_linux_support.c index 3f28dcb3b..30ef30bdf 100644 --- a/low_level_platform/impl/src/lf_linux_support.c +++ b/low_level_platform/impl/src/lf_linux_support.c @@ -45,9 +45,9 @@ THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #else #include "lf_POSIX_threads_support.c" -int lf_thread_set_cpu(lf_thread_t thread, int cpu_number) { - // First verify that we have num_cores>cpu_number - if (lf_available_cores() <= cpu_number) { +int lf_thread_set_cpu(lf_thread_t thread, size_t cpu_number) { + // Sanitize input + if (lf_available_cores() <= 0 || cpu_number >= (size_t)lf_available_cores()) { return -1; } @@ -89,6 +89,7 @@ int lf_thread_set_priority(lf_thread_t thread, int priority) { int lf_thread_set_scheduling_policy(lf_thread_t thread, lf_scheduling_policy_t* policy) { int posix_policy, res; + bool set_priority; struct sched_param schedparam; // Get the current scheduling policy @@ -103,14 +104,18 @@ int lf_thread_set_scheduling_policy(lf_thread_t thread, lf_scheduling_policy_t* switch (policy->policy) { case LF_SCHED_FAIR: posix_policy = SCHED_OTHER; + schedparam.sched_priority = 0; + set_priority = false; break; case LF_SCHED_TIMESLICE: posix_policy = SCHED_RR; schedparam.sched_priority = sched_get_priority_max(SCHED_RR); + set_priority = true; break; case LF_SCHED_PRIORITY: posix_policy = SCHED_FIFO; schedparam.sched_priority = sched_get_priority_max(SCHED_FIFO); + set_priority = true; break; default: return -1; @@ -123,10 +128,13 @@ int lf_thread_set_scheduling_policy(lf_thread_t thread, lf_scheduling_policy_t* return res; } - // Set the priority - res = lf_thread_set_priority(thread, policy->priority); - if (res != 0) - return res; + // Set the priority of we chose a RT scheduler + if (set_priority) { + res = lf_thread_set_priority(thread, policy->priority); + if (res != 0) { + return res; + } + } return 0; } diff --git a/low_level_platform/impl/src/lf_macos_support.c b/low_level_platform/impl/src/lf_macos_support.c index d6b59c4c9..bf96362cb 100644 --- a/low_level_platform/impl/src/lf_macos_support.c +++ b/low_level_platform/impl/src/lf_macos_support.c @@ -42,7 +42,7 @@ THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. /** * Real-time scheduling API not implemented for macOS. */ -int lf_thread_set_cpu(lf_thread_t thread, int cpu_number) { return -1; } +int lf_thread_set_cpu(lf_thread_t thread, size_t cpu_number) { return -1; } int lf_thread_set_priority(lf_thread_t thread, int priority) { return -1; } diff --git a/low_level_platform/impl/src/lf_windows_support.c b/low_level_platform/impl/src/lf_windows_support.c index a0f1fe4dc..1d48bc6c7 100644 --- a/low_level_platform/impl/src/lf_windows_support.c +++ b/low_level_platform/impl/src/lf_windows_support.c @@ -190,7 +190,7 @@ int lf_thread_join(lf_thread_t thread, void** thread_return) { /** * Real-time scheduling API not implemented for Windows. */ -int lf_thread_set_cpu(lf_thread_t thread, int cpu_number) { return -1; } +int lf_thread_set_cpu(lf_thread_t thread, size_t cpu_number) { return -1; } int lf_thread_set_priority(lf_thread_t thread, int priority) { return -1; } diff --git a/low_level_platform/impl/src/lf_zephyr_support.c b/low_level_platform/impl/src/lf_zephyr_support.c index f3470edbb..1a564d1c7 100644 --- a/low_level_platform/impl/src/lf_zephyr_support.c +++ b/low_level_platform/impl/src/lf_zephyr_support.c @@ -157,7 +157,7 @@ int lf_thread_id() { return *((int*)k_thread_custom_data_get()); } lf_thread_t lf_thread_self() { return k_current_get(); } -int lf_thread_set_cpu(lf_thread_t thread, int cpu_number) { return k_thread_cpu_pin(thread, cpu_number); } +int lf_thread_set_cpu(lf_thread_t thread, size_t cpu_number) { return k_thread_cpu_pin(thread, cpu_number); } /** * Real-time scheduling API diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt deleted file mode 100644 index 89ed5d967..000000000 --- a/test/CMakeLists.txt +++ /dev/null @@ -1,2 +0,0 @@ -add_library(test-lib STATIC src_gen_stub.c rand_utils.c) -target_link_libraries(test-lib PRIVATE lf::low-level-platform-api) diff --git a/test/Tests.cmake b/test/Tests.cmake index 2ec3a90ba..a5b8c2ccc 100644 --- a/test/Tests.cmake +++ b/test/Tests.cmake @@ -1,10 +1,12 @@ # This adds all tests in the test directory. include(CTest) -set(TestLib test-lib) set(TEST_DIR ${CMAKE_CURRENT_SOURCE_DIR}/test) set(TEST_SUFFIX test.c) # Files that are tests must have names ending with TEST_SUFFIX. set(LF_ROOT ${CMAKE_CURRENT_LIST_DIR}/..) +set(TEST_MOCK_SRCS ${TEST_DIR}/src_gen_stub.c ${TEST_DIR}/rand_utils.c) + +include(${LF_ROOT}/core/lf_utils.cmake) # Add the test files found in DIR to TEST_FILES. function(add_test_dir DIR) @@ -21,75 +23,24 @@ endfunction() # Add the appropriate directories for the provided build parameters. add_test_dir(${TEST_DIR}/general) if(NUMBER_OF_WORKERS) - add_test_dir(${TEST_DIR}/multithreaded) -else() - add_test_dir(${TEST_DIR}/single-threaded) + if (${CMAKE_SYSTEM_NAME} STREQUAL "Linux") + add_test_dir(${TEST_DIR}/scheduling) + endif() endif(NUMBER_OF_WORKERS) # Create executables for each test. foreach(FILE ${TEST_FILES}) string(REGEX REPLACE "[./]" "_" NAME ${FILE}) - add_executable(${NAME} ${TEST_DIR}/${FILE}) + add_executable(${NAME} ${TEST_DIR}/${FILE} ${TEST_MOCK_SRCS}) add_test(NAME ${NAME} COMMAND ${NAME}) + # This is needed for the tests to use the threading API declared in + # low_level_platform.h. Ideally this would not be needed. + target_link_libraries(${NAME} PRIVATE lf::low-level-platform-impl) target_link_libraries( - ${NAME} PUBLIC - ${CoreLib} ${Lib} ${TestLib} + ${NAME} PRIVATE + ${CoreLib} ${Lib} ) target_include_directories(${NAME} PRIVATE ${TEST_DIR}) + # Warnings as errors + lf_enable_compiler_warnings(${NAME}) endforeach(FILE ${TEST_FILES}) - -# Add the test for the RTI. -if (NOT DEFINED LF_SINGLE_THREADED) - # Check which system we are running on to select the correct platform support - # file and assign the file's path to LF_PLATFORM_FILE - # FIXME: This is effectively a second build script for the RTI that we have to maintain. This is code duplication. - # FIXME: We should not be reaching into the platform directory and bypassing its CMake build. - if(${CMAKE_SYSTEM_NAME} STREQUAL "Linux") - set(LF_PLATFORM_FILE ${LF_ROOT}/low_level_platform/impl/src/lf_linux_support.c) - elseif(${CMAKE_SYSTEM_NAME} STREQUAL "Darwin") - set(LF_PLATFORM_FILE ${LF_ROOT}/low_level_platform/impl/src/lf_macos_support.c) - else() - message(FATAL_ERROR "Your platform is not supported! RTI supports Linux and MacOS.") - endif() - - set(IncludeDir include/core) - - set(RTI_DIR ${CoreLibPath}/federated/RTI) - add_executable( - rti_common_test - ${TEST_DIR}/RTI/rti_common_test.c - ${RTI_DIR}/rti_common.c - ${RTI_DIR}/rti_remote.c - ${CoreLibPath}/tracepoint.c - ${LF_PLATFORM_FILE} - ${LF_ROOT}/low_level_platform/impl/src/lf_platform_util.c - ${LF_ROOT}/low_level_platform/impl/src/lf_atomic_gcc_clang.c - ${LF_ROOT}/low_level_platform/impl/src/lf_unix_clock_support.c - ${CoreLibPath}/utils/util.c - ${CoreLibPath}/tag.c - ${CoreLibPath}/clock.c - ${CoreLibPath}/federated/network/net_util.c - ${CoreLibPath}/utils/pqueue_base.c - ${CoreLibPath}/utils/pqueue_tag.c - ${CoreLibPath}/utils/pqueue.c - ) - add_test(NAME rti_common_test COMMAND rti_common_test) - target_include_directories(rti_common_test PUBLIC ${RTI_DIR}) - target_include_directories(rti_common_test PUBLIC ${IncludeDir}) - target_include_directories(rti_common_test PUBLIC ${IncludeDir}/federated) - target_include_directories(rti_common_test PUBLIC ${IncludeDir}/modal_models) - target_link_libraries(rti_common_test lf::low-level-platform-api) - target_link_libraries(rti_common_test lf::logging-api) - target_include_directories(rti_common_test PUBLIC ${IncludeDir}/utils) - # Set the STANDALONE_RTI flag to include the rti_remote and rti_common. - target_compile_definitions(rti_common_test PUBLIC STANDALONE_RTI=1) - - # Set FEDERATED to get federated compilation support - target_compile_definitions(rti_common_test PUBLIC FEDERATED=1) - - target_compile_definitions(rti_common_test PUBLIC PLATFORM_${CMAKE_SYSTEM_NAME}) - - # Find threads and link to it - find_package(Threads REQUIRED) - target_link_libraries(rti_common_test Threads::Threads) -endif() diff --git a/test/general/tag_test.c b/test/general/tag_test.c index aff2d6875..24fb7b174 100644 --- a/test/general/tag_test.c +++ b/test/general/tag_test.c @@ -2,7 +2,7 @@ #include #include "lf_types.h" -int main(int argc, char** argv) { +int main() { char* buf = malloc(sizeof(char) * 128); lf_readable_time(buf, 0); printf("%s", buf); diff --git a/test/general/utils/hashmap_test.c b/test/general/utils/hashmap_test.c index 28e8deb27..c0fd25443 100644 --- a/test/general/utils/hashmap_test.c +++ b/test/general/utils/hashmap_test.c @@ -35,7 +35,7 @@ void test_get(hashmap_object2int_t* h) { if (desired.value != found) { // It is possible that two distinct values were associated with the same key. Search the // "mock" array to check if this is the case. - for (size_t i = mock_size - 1; i >= 0; i--) { + for (int i = (int)mock_size - 1; i >= 0; i--) { if (mock[i].key == desired.key) { if (mock[i].value == found) return; // Everything is OK. diff --git a/test/general/utils/hashset_test.c b/test/general/utils/hashset_test.c index 4b425b848..1fffcf4c1 100644 --- a/test/general/utils/hashset_test.c +++ b/test/general/utils/hashset_test.c @@ -199,7 +199,7 @@ static void test_fill_with_deleted_items() { hashset_destroy(set); } -int main(int argc, char* argv[]) { +int main() { trivial(); test_gaps(); test_exceptions(); @@ -207,8 +207,6 @@ int main(int argc, char* argv[]) { test_iterating(); test_fill_with_deleted_items(); - (void)argc; - (void)argv; printf("Tests passed.\n"); return 0; } diff --git a/test/general/utils/pqueue_test.c b/test/general/utils/pqueue_test.c index da8e2c6b7..665c4e13f 100644 --- a/test/general/utils/pqueue_test.c +++ b/test/general/utils/pqueue_test.c @@ -47,7 +47,7 @@ static void find_from_queue(pqueue_tag_t* q) { } static void insert_if_no_match(pqueue_tag_t* q) { - int size = pqueue_tag_size(q); + size_t size = pqueue_tag_size(q); tag_t t1 = {.time = USEC(3), .microstep = 0}; tag_t t4 = {.time = USEC(1), .microstep = 2}; // Return value is non-zero on failure to insert: @@ -84,7 +84,7 @@ static void remove_from_queue(pqueue_tag_t* q, pqueue_tag_element_t* e1, pqueue_ assert(pqueue_tag_size(q) == 1); } -int main(int argc, char* argv[]) { +int main() { trivial(); // Create an event queue. pqueue_tag_t* q = pqueue_tag_init(2); diff --git a/test/rand_utils.c b/test/rand_utils.c index 49c1b5230..39b0aadab 100644 --- a/test/rand_utils.c +++ b/test/rand_utils.c @@ -12,7 +12,7 @@ */ void perturb(int* src, size_t size, int* out) { out[size - 1] = src[size - 1]; - for (int a = 0; a < size - 1; a += 2) { + for (size_t a = 0; a < size - 1; a += 2) { int min = src[a] < src[a + 1] ? src[a] : src[a + 1]; int diff = rand() % (min * 2) - min; out[a] = src[a] + diff; diff --git a/test/scheduling/scheduling_api_test.c b/test/scheduling/scheduling_api_test.c new file mode 100644 index 000000000..3315fe0e8 --- /dev/null +++ b/test/scheduling/scheduling_api_test.c @@ -0,0 +1,85 @@ +/** + * This tests the real-time scheduling API implementation in Linux. + */ +#include +#include +#include "core/utils/util.h" +#include "low_level_platform.h" + +#if !defined PLATFORM_Linux +#error scheduling_api_test.c should only be compiled on Linux +#endif + +int main() { + int res; + + // Set the CPU Set of the current thread. + res = lf_thread_set_cpu(lf_thread_self(), lf_available_cores() - 1); + if (res != 0) { + lf_print_error_and_exit("lf_thread_set_cpu failed with %d", res); + } + + // Configure SCHED_FIFO + { + lf_scheduling_policy_t cfg; + cfg.policy = LF_SCHED_PRIORITY; + cfg.priority = 99; + cfg.time_slice = 0; + res = lf_thread_set_scheduling_policy(lf_thread_self(), &cfg); + if (res != 0) { + lf_print_error_and_exit("lf_thread_set_scheduling_policy FIFO failed with %d", res); + } + } + + // Configure SCHED_RR + { + lf_scheduling_policy_t cfg; + cfg.policy = LF_SCHED_TIMESLICE; + cfg.priority = 99; + cfg.time_slice = 0; + res = lf_thread_set_scheduling_policy(lf_thread_self(), &cfg); + if (res != 0) { + lf_print_error_and_exit("lf_thread_set_scheduling_policy RR failed with %d", res); + } + } + + // Try illegal priority + { + lf_scheduling_policy_t cfg; + cfg.policy = LF_SCHED_TIMESLICE; + cfg.time_slice = 0; + cfg.priority = 10000; + res = lf_thread_set_scheduling_policy(lf_thread_self(), &cfg); + if (res == 0) { + lf_print_error_and_exit("lf_thread_set_scheduling_policy should have failed with illegal priority"); + } + } + + // Set the priority + res = lf_thread_set_priority(lf_thread_self(), 50); + if (res != 0) { + lf_print_error_and_exit("lf_thread_set_priority failed with %d", res); + } + + // Try negative priority + res = lf_thread_set_priority(lf_thread_self(), -50); + if (res == 0) { + lf_print_error_and_exit("lf_thread_set_priority should have failed for -50"); + } + + // Configure back to SCHED_OTHER + { + lf_scheduling_policy_t cfg; + cfg.policy = LF_SCHED_FAIR; + res = lf_thread_set_scheduling_policy(lf_thread_self(), &cfg); + if (res != 0) { + lf_print_error_and_exit("lf_thread_set_scheduling_policy RR failed with %d", res); + } + } + + // Try pinning to non-existant CPU core. + res = lf_thread_set_cpu(lf_thread_self(), lf_available_cores()); + if (res == 0) { + lf_print_error_and_exit("lf_thread_set_cpu should fail for too high CPU id"); + } +} diff --git a/test/src_gen_stub.c b/test/src_gen_stub.c index 1e4630a6e..919d14b43 100644 --- a/test/src_gen_stub.c +++ b/test/src_gen_stub.c @@ -14,8 +14,8 @@ environment_t _env; void _lf_initialize_trigger_objects(void) {} void lf_terminate_execution(void) {} void lf_set_default_command_line_options(void) {} -void _lf_initialize_watchdogs(environment_t** envs) {} -void logical_tag_complete(tag_t tag_to_send) {} +void _lf_initialize_watchdogs(environment_t** envs) { (void)envs; } +void logical_tag_complete(tag_t tag_to_send) { (void)tag_to_send; } int _lf_get_environments(environment_t** envs) { *envs = &_env; return 1;