diff --git a/CMakeLists.txt b/CMakeLists.txt index a5a0a9238feadb767c8c71cba0e99cc112399f96..4ffafbe6f93def1d8625dd6b425b80c48ad0938b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,7 +2,7 @@ project(cellframe-sdk C) cmake_minimum_required(VERSION 2.8) set(CMAKE_C_STANDARD 11) -set(CELLFRAME_SDK_NATIVE_VERSION "2.1-0") +set(CELLFRAME_SDK_NATIVE_VERSION "2.1-1") include(cmake/OS_Detection.cmake) add_definitions ("-DCELLFRAME_SDK_VERSION=\"${CELLFRAME_SDK_NATIVE_VERSION}\"") @@ -16,6 +16,16 @@ if (CELLFRAME_MODULES MATCHES "network") set(DAPSDK_MODULES "${DAPSDK_MODULES} network-core network-client network-server") endif() +if (BUILD_CRYPTO_TESTS) + if ( NOT(DAPSDK_MODULES MATCHES "core")) + SET(DAPSDK_MODULES "${DAPSDK_MODULES} core") + endif() + if ( NOT(DAPSDK_MODULES MATCHES "crypto")) + SET(DAPSDK_MODULES "${DAPSDK_MODULES} crypto") + endif() + set(BUILD_TESTS ON) +endif() + add_subdirectory(dap-sdk) add_subdirectory(3rdparty/monero_crypto) add_subdirectory(3rdparty/cuttdb) diff --git a/dap-sdk/crypto/test/CMakeLists.txt b/dap-sdk/crypto/test/CMakeLists.txt index 18ed49801c7a0238d38ae31ff7cc41f2d75d6867..fe129624464d805d51780fd653889e6425e914f9 100755 --- a/dap-sdk/crypto/test/CMakeLists.txt +++ b/dap-sdk/crypto/test/CMakeLists.txt @@ -1,11 +1,7 @@ -cmake_minimum_required(VERSION 3.0) +cmake_minimum_required(VERSION 3.0) project(test) set(CMAKE_C_STANDARD 11) -if(NOT SUBMODULES_NO_BUILD) - add_subdirectory(libdap-test) -endif() - add_subdirectory(crypto) add_subdirectory(cert) diff --git a/modules/CMakeLists.txt b/modules/CMakeLists.txt index 7b810fc7857b9a1aaf5b2bea64720b4e381bcc12..19026903b6ce517c04a435c744cb06bc802ccad1 100644 --- a/modules/CMakeLists.txt +++ b/modules/CMakeLists.txt @@ -75,3 +75,8 @@ endif() if (CELLFRAME_MODULES MATCHES "srv-vpn") add_subdirectory(service/vpn) endif() + +# Unit tests +if( BUILD_TESTS) + add_subdirectory(test) +endif() \ No newline at end of file diff --git a/modules/test/CMakeLists.txt b/modules/test/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..70e543e45b934bcc5d43a765db96d620a4af9280 --- /dev/null +++ b/modules/test/CMakeLists.txt @@ -0,0 +1,9 @@ +cmake_minimum_required(VERSION 3.0) +if(TARGET dap_test) + return() # The project has already been built. +endif() +project(dap_test) + +add_library(${PROJECT_NAME} STATIC dap_test.h dap_test.c dap_test_generator.h dap_test_generator.c) + +target_include_directories(dap_test INTERFACE .) diff --git a/modules/test/dap_test.c b/modules/test/dap_test.c new file mode 100644 index 0000000000000000000000000000000000000000..e4603b71d210ea96d5db7dc2690861a920a449a3 --- /dev/null +++ b/modules/test/dap_test.c @@ -0,0 +1,112 @@ +#include "dap_test.h" + +#include <sys/time.h> + +/* + How to use benchmark_xxx() functions: + + void mytest_func() + { + // doing something ... + } + + // Repeat mytest_func() 5 time + int dt = benchmark_test_time(mytest_func, 5); + // Display result, sample 'Encode and decode PASS. (4 msec.)' + benchmark_mgs_time("Encode and decode", dt); + + // Repeat mytest_func() within 2 second + float rate = benchmark_test_rate(mytest_func, 2); + // Display result, sample 'Encode and decode PASS. (703 times/sec.)' + benchmark_mgs_rate("Encode and decode", rate); + + */ + +#define dap_pass_msg_benchmark(testname, benchmark_text) \ + printf("\t%s%s PASS. %s%s\n", TEXT_COLOR_GRN, testname, benchmark_text, TEXT_COLOR_RESET); \ + fflush(stdout); \ + +/** + * Display time in the format 'x.xx sec.' or 'xx msec.' + */ +void benchmark_mgs_time(const char *test_name, int dt) +{ + char buf[120]; + if(abs(dt) >= 1000) { + snprintf(buf, 120, "(%.3lf sec.)", dt * 1. / 1000); + } + else { + + snprintf(buf, 120, "(%d msec.)", dt); + } + dap_pass_msg_benchmark(test_name, buf); +} + +/** + * Display rate in the format 'xx times/sec.' + */ +void benchmark_mgs_rate(const char *test_name, float rate) +{ + char buf[120]; + if(rate > 100) { + snprintf(buf, 120, "(%.0lf times/sec.)", rate); + } + else if(rate > 10) { + snprintf(buf, 120, "%.1lf times/sec.", rate); + } + else { + snprintf(buf, 120, "%.2lf times/sec.", rate); + } + dap_pass_msg_benchmark(test_name, buf); +} + +/** + * @return current time in milliseconds + */ +static int get_cur_time_msec(void) +{ + struct timespec time; + clock_gettime(CLOCK_MONOTONIC, &time); + int msec = time.tv_sec * 1000 + (time.tv_nsec + 500000) / 1000000; + return msec; +} + +/** + * Calculate the runtime of a function that repeat several times + * @func_name function for repeats + * @repeat how many times repeats + * @return time in milliseconds + */ +int benchmark_test_time(void (*func_name)(void), int repeat) +{ + int t1 = get_cur_time_msec(); + for(int i = 0; i < repeat; i++) + func_name(); + int t2 = get_cur_time_msec(); + return t2 - t1; +} + +/** + * Calculate the rate of a function that repeat at a minimum specified number of seconds + * @func_name function for repeats + * @repeat how many times repeats + * @return function rate, i.e. count per second + */ +float benchmark_test_rate(void (*func_name)(void), float sec) +{ + if(sec < 0.1f) { + dap_test_msg("undefined times/sec."); + return 0; + } + int t1 = get_cur_time_msec(); + int repeat = 0, dt; + do { + func_name(); + dt = (get_cur_time_msec() - t1); + repeat++; + } + while(dt < sec * 1000); + float rate = repeat * 1000.f / dt; + return rate; +} + diff --git a/modules/test/dap_test.h b/modules/test/dap_test.h new file mode 100644 index 0000000000000000000000000000000000000000..0c346732faf6f13ae2d744601ee77f1156693b3b --- /dev/null +++ b/modules/test/dap_test.h @@ -0,0 +1,112 @@ +#pragma once +#include <assert.h> +#include <stdbool.h> +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <time.h> + +#define TEXT_COLOR_RED "\x1B[31m" +#define TEXT_COLOR_GRN "\x1B[32m" +#define TEXT_COLOR_YEL "\x1B[33m" +#define TEXT_COLOR_BLU "\x1B[34m" +#define TEXT_COLOR_MAG "\x1B[35m" +#define TEXT_COLOR_CYN "\x1B[36m" +#define TEXT_COLOR_WHT "\x1B[37m" +#define TEXT_COLOR_RESET "\x1B[0m" + +/* Can be used like debug info during write test*/ +/** + * @brief Can be used like debug info during write test + */ +#define dap_test_msg(...) { \ + printf("\t%s", TEXT_COLOR_WHT); \ + printf(__VA_ARGS__); \ + printf("%s\n", TEXT_COLOR_RESET); \ + fflush(stdout); } + +#define dap_fail(msg) {\ + printf("\t%s%s!%s\n", TEXT_COLOR_RED, msg, TEXT_COLOR_RESET); \ + abort();} + +/* PIF - print if failed. For checking value in loop, for don't repeat output */ +/** + * @brief PIF - print if failed. For checking value in loop, for don't repeat output + */ +#define dap_assert_PIF(expr, msg) { \ + if(expr) {} \ + else { \ + printf("\t%s%s FAILED!%s\n", TEXT_COLOR_RED, msg, TEXT_COLOR_RESET); \ + abort(); } } + +/** + * @brief +*/ +#define dap_assert(expr, testname) { \ + if(expr) { \ + printf("\t%s%s PASS.%s\n", TEXT_COLOR_GRN, testname, TEXT_COLOR_RESET); \ + fflush(stdout); \ + } else { \ + printf("\t%s%s FAILED!%s\n", TEXT_COLOR_RED, testname, TEXT_COLOR_RESET); \ + abort(); } } \ + +/** + * @brief Display the name test +*/ +#define dap_pass_msg(testname) { \ + printf("\t%s%s PASS.%s\n", TEXT_COLOR_GRN, testname, TEXT_COLOR_RESET); \ + fflush(stdout); } \ + +/** + * @brief Display the name of the test module +*/ +#define dap_print_module_name(module_name) { \ + printf("%s%s passing the tests... %s\n", TEXT_COLOR_CYN, module_name, TEXT_COLOR_RESET); \ + fflush(stdout); } + +#define dap_str_equals(str1, str2) strcmp(str1, str2) == 0 +#define dap_strn_equals(str1, str2, count) strncmp(str1, str2, count) == 0 + +/* + How to use benchmark_xxx() functions: + + void mytest_func() + { + // doing something ... + } + + // Repeat mytest_func() 5 time + int dt = benchmark_test_time(mytest_func, 5); + // Display result, sample 'Encode and decode PASS. (4 msec.)' + benchmark_mgs_time("Encode and decode", dt); + + // Repeat mytest_func() within 2 second + float rate = benchmark_test_rate(mytest_func, 2); + // Display result, sample 'Encode and decode PASS. (703 times/sec.)' + benchmark_mgs_rate("Encode and decode", rate); + + */ + +/** + * Display time in the format 'x.xx sec.' or 'xx msec.' + */ +void benchmark_mgs_time(const char *text, int dt); + +/** + * Display rate in the format 'xx times/sec.' + */ +void benchmark_mgs_rate(const char *test_name, float rate); +/** + * Calculate the runtime of a function that repeat several times + * @func_name function for repeats + * @repeat how many times repeats + * @return time in milliseconds + */ +int benchmark_test_time(void (*func_name)(void), int repeat); +/** + * Calculate the rate of a function that repeat at a minimum specified number of seconds + * @func_name function for repeats + * @repeat how many times repeats + * @return function rate, i.e. count per second + */ +float benchmark_test_rate(void (*func_name)(void), float sec); diff --git a/modules/test/dap_test_generator.c b/modules/test/dap_test_generator.c new file mode 100644 index 0000000000000000000000000000000000000000..6a540f6928582f3ffba3296af20739e00b5d5733 --- /dev/null +++ b/modules/test/dap_test_generator.c @@ -0,0 +1,21 @@ +#include "dap_test_generator.h" + +#define BYTE_SIZE 255 + +/** + * @brief The function fills an array with random numbers + * @param[out] array Takes a pointer to an array + * @param[in] size Size of the array passed in the array parameter + * + * The function fills an array with random integer non-negative values +*/ +void generate_random_byte_array(uint8_t* array, const size_t size) { + srand((uint32_t)time(NULL)); + for(size_t i = 0; i < size; i++) { + array[i] = (uint8_t)rand() % BYTE_SIZE; + } + + // Last byte not should be 0 + if (array[size - 1] == 0) + array[size - 1] = 1; +} diff --git a/modules/test/dap_test_generator.h b/modules/test/dap_test_generator.h new file mode 100644 index 0000000000000000000000000000000000000000..4c74064744cb844c864d14faf72d7e555a54b7e0 --- /dev/null +++ b/modules/test/dap_test_generator.h @@ -0,0 +1,7 @@ +#pragma once +#include <stdint.h> +#include <stdlib.h> +#include <time.h> + +void generate_random_byte_array(uint8_t* array, const size_t size); +