From c2cb14834d5ef65c36ffcc00ae6bc6ffaf69ca02 Mon Sep 17 00:00:00 2001 From: Sergey Gavrilov Date: Sun, 25 Dec 2022 00:13:21 +1000 Subject: [PATCH] [FL-3062] Fix unit tests (#2180) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * SubGHZ unit test: fail if async_tx is not started * Memgr unit test: fix for multithreaded enviroment * Unit tests: fix failed_tests count * Unit tests: remove debug code * Double update test: increase flipper detection time Co-authored-by: あく --- .../debug/unit_tests/furi/furi_memmgr_test.c | 99 ++++--------------- .../debug/unit_tests/subghz/subghz_test.c | 5 +- applications/debug/unit_tests/test_index.c | 38 +++---- scripts/testing/await_flipper.py | 2 +- 4 files changed, 44 insertions(+), 100 deletions(-) diff --git a/applications/debug/unit_tests/furi/furi_memmgr_test.c b/applications/debug/unit_tests/furi/furi_memmgr_test.c index cf384874..f7bc234a 100644 --- a/applications/debug/unit_tests/furi/furi_memmgr_test.c +++ b/applications/debug/unit_tests/furi/furi_memmgr_test.c @@ -3,98 +3,37 @@ #include #include -// this test is not accurate, but gives a basic understanding -// that memory management is working fine - -// do not include memmgr.h here -// we also test that we are linking against stdlib -extern size_t memmgr_get_free_heap(void); -extern size_t memmgr_get_minimum_free_heap(void); - -// current heap management realization consume: -// X bytes after allocate and 0 bytes after allocate and free, -// where X = sizeof(void*) + sizeof(size_t), look to BlockLink_t -const size_t heap_overhead_max_size = sizeof(void*) + sizeof(size_t); - -bool heap_equal(size_t heap_size, size_t heap_size_old) { - // heap borders with overhead - const size_t heap_low = heap_size_old - heap_overhead_max_size; - const size_t heap_high = heap_size_old + heap_overhead_max_size; - - // not exact, so we must test it against bigger numbers than "overhead size" - const bool result = ((heap_size >= heap_low) && (heap_size <= heap_high)); - - // debug allocation info - if(!result) { - printf("\n(hl: %zu) <= (p: %zu) <= (hh: %zu)\n", heap_low, heap_size, heap_high); - } - - return result; -} - void test_furi_memmgr() { - size_t heap_size = 0; - size_t heap_size_old = 0; - const int alloc_size = 128; - - void* ptr = NULL; - void* original_ptr = NULL; - - // do not include furi memmgr.h case -#ifdef FURI_MEMMGR_GUARD - mu_fail("do not link against furi memmgr.h"); -#endif + void* ptr; // allocate memory case - heap_size_old = memmgr_get_free_heap(); - ptr = malloc(alloc_size); - heap_size = memmgr_get_free_heap(); - mu_assert_pointers_not_eq(ptr, NULL); - mu_assert(heap_equal(heap_size, heap_size_old - alloc_size), "allocate failed"); - - // free memory case - heap_size_old = memmgr_get_free_heap(); + ptr = malloc(100); + mu_check(ptr != NULL); + // test that memory is zero-initialized after allocation + for(int i = 0; i < 100; i++) { + mu_assert_int_eq(0, ((uint8_t*)ptr)[i]); + } free(ptr); - ptr = NULL; - heap_size = memmgr_get_free_heap(); - mu_assert(heap_equal(heap_size, heap_size_old + alloc_size), "free failed"); // reallocate memory case + ptr = malloc(100); + memset(ptr, 66, 100); + ptr = realloc(ptr, 200); + mu_check(ptr != NULL); - // get filled array with some data - original_ptr = malloc(alloc_size); - mu_assert_pointers_not_eq(original_ptr, NULL); - for(int i = 0; i < alloc_size; i++) { - *(unsigned char*)(original_ptr + i) = i; + // test that memory is really reallocated + for(int i = 0; i < 100; i++) { + mu_assert_int_eq(66, ((uint8_t*)ptr)[i]); } - // malloc array and copy data - ptr = malloc(alloc_size); - mu_assert_pointers_not_eq(ptr, NULL); - memcpy(ptr, original_ptr, alloc_size); - - // reallocate array - heap_size_old = memmgr_get_free_heap(); - ptr = realloc(ptr, alloc_size * 2); - heap_size = memmgr_get_free_heap(); - mu_assert(heap_equal(heap_size, heap_size_old - alloc_size), "reallocate failed"); - mu_assert_int_eq(memcmp(original_ptr, ptr, alloc_size), 0); - free(original_ptr); + // TODO: fix realloc to copy only old size, and write testcase that leftover of reallocated memory is zero-initialized free(ptr); // allocate and zero-initialize array (calloc) - original_ptr = malloc(alloc_size); - mu_assert_pointers_not_eq(original_ptr, NULL); - - for(int i = 0; i < alloc_size; i++) { - *(unsigned char*)(original_ptr + i) = 0; + ptr = calloc(100, 2); + mu_check(ptr != NULL); + for(int i = 0; i < 100 * 2; i++) { + mu_assert_int_eq(0, ((uint8_t*)ptr)[i]); } - heap_size_old = memmgr_get_free_heap(); - ptr = calloc(1, alloc_size); - heap_size = memmgr_get_free_heap(); - mu_assert(heap_equal(heap_size, heap_size_old - alloc_size), "callocate failed"); - mu_assert_int_eq(memcmp(original_ptr, ptr, alloc_size), 0); - - free(original_ptr); free(ptr); } diff --git a/applications/debug/unit_tests/subghz/subghz_test.c b/applications/debug/unit_tests/subghz/subghz_test.c index d954ddd9..cb89e1f0 100644 --- a/applications/debug/unit_tests/subghz/subghz_test.c +++ b/applications/debug/unit_tests/subghz/subghz_test.c @@ -318,7 +318,10 @@ bool subghz_hal_async_tx_test_run(SubGhzHalAsyncTxTestType type) { furi_hal_subghz_load_preset(FuriHalSubGhzPresetOok650Async); furi_hal_subghz_set_frequency_and_path(433920000); - furi_hal_subghz_start_async_tx(subghz_hal_async_tx_test_yield, &test); + if(!furi_hal_subghz_start_async_tx(subghz_hal_async_tx_test_yield, &test)) { + return false; + } + while(!furi_hal_subghz_is_async_tx_complete()) { furi_delay_ms(10); } diff --git a/applications/debug/unit_tests/test_index.c b/applications/debug/unit_tests/test_index.c index 36c2b4ae..5bc53c82 100644 --- a/applications/debug/unit_tests/test_index.c +++ b/applications/debug/unit_tests/test_index.c @@ -73,7 +73,6 @@ void unit_tests_cli(Cli* cli, FuriString* args, void* context) { UNUSED(cli); UNUSED(args); UNUSED(context); - uint32_t failed_tests = 0; minunit_run = 0; minunit_assert = 0; minunit_fail = 0; @@ -99,32 +98,35 @@ void unit_tests_cli(Cli* cli, FuriString* args, void* context) { if(furi_string_size(args)) { if(furi_string_cmp_str(args, unit_tests[i].name) == 0) { - failed_tests += unit_tests[i].entry(); + unit_tests[i].entry(); } else { printf("Skipping %s\r\n", unit_tests[i].name); } } else { - failed_tests += unit_tests[i].entry(); + unit_tests[i].entry(); } } - printf("\r\nFailed tests: %lu\r\n", failed_tests); - // Time report - cycle_counter = (furi_get_tick() - cycle_counter); - printf("Consumed: %lu ms\r\n", cycle_counter); + if(minunit_run != 0) { + printf("\r\nFailed tests: %u\r\n", minunit_fail); - // Wait for tested services and apps to deallocate memory - furi_delay_ms(200); - uint32_t heap_after = memmgr_get_free_heap(); - printf("Leaked: %ld\r\n", heap_before - heap_after); + // Time report + cycle_counter = (furi_get_tick() - cycle_counter); + printf("Consumed: %lu ms\r\n", cycle_counter); - // Final Report - if(failed_tests == 0) { - notification_message(notification, &sequence_success); - printf("Status: PASSED\r\n"); - } else { - notification_message(notification, &sequence_error); - printf("Status: FAILED\r\n"); + // Wait for tested services and apps to deallocate memory + furi_delay_ms(200); + uint32_t heap_after = memmgr_get_free_heap(); + printf("Leaked: %ld\r\n", heap_before - heap_after); + + // Final Report + if(minunit_fail == 0) { + notification_message(notification, &sequence_success); + printf("Status: PASSED\r\n"); + } else { + notification_message(notification, &sequence_error); + printf("Status: FAILED\r\n"); + } } } diff --git a/scripts/testing/await_flipper.py b/scripts/testing/await_flipper.py index efae6765..704d75a7 100755 --- a/scripts/testing/await_flipper.py +++ b/scripts/testing/await_flipper.py @@ -24,7 +24,7 @@ def flp_serial_by_name(flp_name): return "" -UPDATE_TIMEOUT = 60 +UPDATE_TIMEOUT = 60 * 4 # 4 minutes def main():