[FL-3062] Fix unit tests (#2180)
* 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: あく <alleteam@gmail.com>
This commit is contained in:
parent
b0970953b9
commit
c2cb14834d
@ -3,98 +3,37 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
|
||||||
// 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() {
|
void test_furi_memmgr() {
|
||||||
size_t heap_size = 0;
|
void* ptr;
|
||||||
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
|
|
||||||
|
|
||||||
// allocate memory case
|
// allocate memory case
|
||||||
heap_size_old = memmgr_get_free_heap();
|
ptr = malloc(100);
|
||||||
ptr = malloc(alloc_size);
|
mu_check(ptr != NULL);
|
||||||
heap_size = memmgr_get_free_heap();
|
// test that memory is zero-initialized after allocation
|
||||||
mu_assert_pointers_not_eq(ptr, NULL);
|
for(int i = 0; i < 100; i++) {
|
||||||
mu_assert(heap_equal(heap_size, heap_size_old - alloc_size), "allocate failed");
|
mu_assert_int_eq(0, ((uint8_t*)ptr)[i]);
|
||||||
|
}
|
||||||
// free memory case
|
|
||||||
heap_size_old = memmgr_get_free_heap();
|
|
||||||
free(ptr);
|
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
|
// reallocate memory case
|
||||||
|
ptr = malloc(100);
|
||||||
|
memset(ptr, 66, 100);
|
||||||
|
ptr = realloc(ptr, 200);
|
||||||
|
mu_check(ptr != NULL);
|
||||||
|
|
||||||
// get filled array with some data
|
// test that memory is really reallocated
|
||||||
original_ptr = malloc(alloc_size);
|
for(int i = 0; i < 100; i++) {
|
||||||
mu_assert_pointers_not_eq(original_ptr, NULL);
|
mu_assert_int_eq(66, ((uint8_t*)ptr)[i]);
|
||||||
for(int i = 0; i < alloc_size; i++) {
|
|
||||||
*(unsigned char*)(original_ptr + i) = i;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// malloc array and copy data
|
// TODO: fix realloc to copy only old size, and write testcase that leftover of reallocated memory is zero-initialized
|
||||||
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);
|
|
||||||
free(ptr);
|
free(ptr);
|
||||||
|
|
||||||
// allocate and zero-initialize array (calloc)
|
// allocate and zero-initialize array (calloc)
|
||||||
original_ptr = malloc(alloc_size);
|
ptr = calloc(100, 2);
|
||||||
mu_assert_pointers_not_eq(original_ptr, NULL);
|
mu_check(ptr != NULL);
|
||||||
|
for(int i = 0; i < 100 * 2; i++) {
|
||||||
for(int i = 0; i < alloc_size; i++) {
|
mu_assert_int_eq(0, ((uint8_t*)ptr)[i]);
|
||||||
*(unsigned char*)(original_ptr + i) = 0;
|
|
||||||
}
|
}
|
||||||
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);
|
free(ptr);
|
||||||
}
|
}
|
||||||
|
@ -318,7 +318,10 @@ bool subghz_hal_async_tx_test_run(SubGhzHalAsyncTxTestType type) {
|
|||||||
furi_hal_subghz_load_preset(FuriHalSubGhzPresetOok650Async);
|
furi_hal_subghz_load_preset(FuriHalSubGhzPresetOok650Async);
|
||||||
furi_hal_subghz_set_frequency_and_path(433920000);
|
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()) {
|
while(!furi_hal_subghz_is_async_tx_complete()) {
|
||||||
furi_delay_ms(10);
|
furi_delay_ms(10);
|
||||||
}
|
}
|
||||||
|
@ -73,7 +73,6 @@ void unit_tests_cli(Cli* cli, FuriString* args, void* context) {
|
|||||||
UNUSED(cli);
|
UNUSED(cli);
|
||||||
UNUSED(args);
|
UNUSED(args);
|
||||||
UNUSED(context);
|
UNUSED(context);
|
||||||
uint32_t failed_tests = 0;
|
|
||||||
minunit_run = 0;
|
minunit_run = 0;
|
||||||
minunit_assert = 0;
|
minunit_assert = 0;
|
||||||
minunit_fail = 0;
|
minunit_fail = 0;
|
||||||
@ -99,15 +98,17 @@ void unit_tests_cli(Cli* cli, FuriString* args, void* context) {
|
|||||||
|
|
||||||
if(furi_string_size(args)) {
|
if(furi_string_size(args)) {
|
||||||
if(furi_string_cmp_str(args, unit_tests[i].name) == 0) {
|
if(furi_string_cmp_str(args, unit_tests[i].name) == 0) {
|
||||||
failed_tests += unit_tests[i].entry();
|
unit_tests[i].entry();
|
||||||
} else {
|
} else {
|
||||||
printf("Skipping %s\r\n", unit_tests[i].name);
|
printf("Skipping %s\r\n", unit_tests[i].name);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
failed_tests += unit_tests[i].entry();
|
unit_tests[i].entry();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
printf("\r\nFailed tests: %lu\r\n", failed_tests);
|
|
||||||
|
if(minunit_run != 0) {
|
||||||
|
printf("\r\nFailed tests: %u\r\n", minunit_fail);
|
||||||
|
|
||||||
// Time report
|
// Time report
|
||||||
cycle_counter = (furi_get_tick() - cycle_counter);
|
cycle_counter = (furi_get_tick() - cycle_counter);
|
||||||
@ -119,7 +120,7 @@ void unit_tests_cli(Cli* cli, FuriString* args, void* context) {
|
|||||||
printf("Leaked: %ld\r\n", heap_before - heap_after);
|
printf("Leaked: %ld\r\n", heap_before - heap_after);
|
||||||
|
|
||||||
// Final Report
|
// Final Report
|
||||||
if(failed_tests == 0) {
|
if(minunit_fail == 0) {
|
||||||
notification_message(notification, &sequence_success);
|
notification_message(notification, &sequence_success);
|
||||||
printf("Status: PASSED\r\n");
|
printf("Status: PASSED\r\n");
|
||||||
} else {
|
} else {
|
||||||
@ -127,6 +128,7 @@ void unit_tests_cli(Cli* cli, FuriString* args, void* context) {
|
|||||||
printf("Status: FAILED\r\n");
|
printf("Status: FAILED\r\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
furi_record_close(RECORD_NOTIFICATION);
|
furi_record_close(RECORD_NOTIFICATION);
|
||||||
furi_record_close(RECORD_LOADER);
|
furi_record_close(RECORD_LOADER);
|
||||||
|
@ -24,7 +24,7 @@ def flp_serial_by_name(flp_name):
|
|||||||
return ""
|
return ""
|
||||||
|
|
||||||
|
|
||||||
UPDATE_TIMEOUT = 60
|
UPDATE_TIMEOUT = 60 * 4 # 4 minutes
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
|
Loading…
Reference in New Issue
Block a user