1
mirror of https://github.com/DarkFlippers/unleashed-firmware.git synced 2025-12-13 05:06:30 +04:00

Merge remote-tracking branch 'OFW/dev' into dev

This commit is contained in:
MX
2024-06-10 22:55:02 +03:00
63 changed files with 1594 additions and 1132 deletions

View File

@@ -1,4 +1,3 @@
#include <core/common_defines.h>
#include <furi.h>
#include <furi_hal.h>

View File

@@ -72,7 +72,6 @@ CcidTestApp* ccid_test_app_alloc(void) {
//message queue
app->event_queue = furi_message_queue_alloc(8, sizeof(CcidTestAppEvent));
furi_check(app->event_queue);
view_port_input_callback_set(app->view_port, ccid_test_app_input_callback, app->event_queue);
return app;

View File

@@ -64,16 +64,9 @@ static void keypad_test_input_callback(InputEvent* input_event, void* ctx) {
int32_t keypad_test_app(void* p) {
UNUSED(p);
FuriMessageQueue* event_queue = furi_message_queue_alloc(32, sizeof(InputEvent));
furi_check(event_queue);
KeypadTestState state = {{false, false, false, false, false}, 0, 0, 0, 0, 0, NULL};
state.mutex = furi_mutex_alloc(FuriMutexTypeNormal);
if(!state.mutex) {
FURI_LOG_E(TAG, "cannot create mutex");
return 0;
}
ViewPort* view_port = view_port_alloc();
view_port_draw_callback_set(view_port, keypad_test_render_callback, &state);

View File

@@ -74,16 +74,8 @@ static void text_box_test_input_callback(InputEvent* input_event, void* ctx) {
int32_t text_box_element_test_app(void* p) {
UNUSED(p);
FuriMessageQueue* event_queue = furi_message_queue_alloc(32, sizeof(InputEvent));
furi_check(event_queue);
TextBoxTestState state = {.idx = 0, .mutex = NULL};
state.mutex = furi_mutex_alloc(FuriMutexTypeNormal);
if(!state.mutex) {
FURI_LOG_E(TAG, "Cannot create mutex");
return 0;
}
ViewPort* view_port = view_port_alloc();
view_port_draw_callback_set(view_port, text_box_test_render_callback, &state);

View File

@@ -72,6 +72,9 @@ void test_runner_free(TestRunner* instance) {
free(instance);
}
#define TEST_RUNNER_TMP_DIR EXT_PATH(".tmp")
#define TEST_RUNNER_TMP_UNIT_TESTS_DIR TEST_RUNNER_TMP_DIR "/unit_tests"
static bool test_runner_run_plugin(TestRunner* instance, const char* path) {
furi_assert(instance);
@@ -128,6 +131,16 @@ static void test_runner_run_internal(TestRunner* instance) {
File* directory = storage_file_alloc(instance->storage);
do {
if(!storage_simply_mkdir(instance->storage, TEST_RUNNER_TMP_DIR)) {
FURI_LOG_E(TAG, "Cannot create dir %s", TEST_RUNNER_TMP_DIR);
break;
}
if(!storage_simply_mkdir(instance->storage, TEST_RUNNER_TMP_UNIT_TESTS_DIR)) {
FURI_LOG_E(TAG, "Cannot create dir %s", TEST_RUNNER_TMP_UNIT_TESTS_DIR);
break;
}
if(!storage_dir_open(directory, PLUGINS_PATH)) {
FURI_LOG_E(TAG, "Failed to open directory %s", PLUGINS_PATH);
break;

View File

@@ -4,8 +4,8 @@
#include <toolbox/stream/stream.h>
#include "../test.h" // IWYU pragma: keep
#define TEST_DIR_NAME EXT_PATH(".tmp/unit_tests/ff")
#define TEST_DIR TEST_DIR_NAME "/"
#define TEST_DIR_NAME EXT_PATH("unit_tests_tmp")
static const char* test_filetype = "Flipper File test";
static const uint32_t test_version = 666;

View File

@@ -298,7 +298,8 @@ MU_TEST(flipper_format_string_test) {
MU_TEST(flipper_format_file_test) {
Storage* storage = furi_record_open(RECORD_STORAGE);
FlipperFormat* flipper_format = flipper_format_file_alloc(storage);
mu_check(flipper_format_file_open_always(flipper_format, EXT_PATH("flipper.fff")));
mu_check(
flipper_format_file_open_always(flipper_format, EXT_PATH(".tmp/unit_tests/flipper.fff")));
Stream* stream = flipper_format_get_raw_stream(flipper_format);
mu_check(flipper_format_write_header_cstr(flipper_format, test_filetype, test_version));

View File

@@ -0,0 +1,164 @@
#include "../test.h"
#include <furi.h>
#include <furi_hal.h>
#define TAG "TestFuriEventLoop"
#define EVENT_LOOP_EVENT_COUNT (256u)
typedef struct {
FuriMessageQueue* mq;
FuriEventLoop* producer_event_loop;
uint32_t producer_counter;
FuriEventLoop* consumer_event_loop;
uint32_t consumer_counter;
} TestFuriData;
bool test_furi_event_loop_producer_mq_callback(FuriMessageQueue* queue, void* context) {
furi_check(context);
TestFuriData* data = context;
furi_check(data->mq == queue, "Invalid queue");
FURI_LOG_I(
TAG, "producer_mq_callback: %lu %lu", data->producer_counter, data->consumer_counter);
// Remove and add should not cause crash
// if(data->producer_counter == EVENT_LOOP_EVENT_COUNT/2) {
// furi_event_loop_message_queue_remove(data->producer_event_loop, data->mq);
// furi_event_loop_message_queue_add(
// data->producer_event_loop,
// data->mq,
// FuriEventLoopEventOut,
// test_furi_event_loop_producer_mq_callback,
// data);
// }
if(data->producer_counter == EVENT_LOOP_EVENT_COUNT) {
furi_event_loop_stop(data->producer_event_loop);
return false;
}
data->producer_counter++;
furi_check(
furi_message_queue_put(data->mq, &data->producer_counter, 0) == FuriStatusOk,
"furi_message_queue_put failed");
furi_delay_us(furi_hal_random_get() % 1000);
return true;
}
int32_t test_furi_event_loop_producer(void* p) {
furi_check(p);
FURI_LOG_I(TAG, "producer start");
TestFuriData* data = p;
data->producer_event_loop = furi_event_loop_alloc();
furi_event_loop_message_queue_subscribe(
data->producer_event_loop,
data->mq,
FuriEventLoopEventOut,
test_furi_event_loop_producer_mq_callback,
data);
furi_event_loop_run(data->producer_event_loop);
furi_event_loop_message_queue_unsubscribe(data->producer_event_loop, data->mq);
furi_event_loop_free(data->producer_event_loop);
FURI_LOG_I(TAG, "producer end");
return 0;
}
bool test_furi_event_loop_consumer_mq_callback(FuriMessageQueue* queue, void* context) {
furi_check(context);
TestFuriData* data = context;
furi_check(data->mq == queue);
furi_delay_us(furi_hal_random_get() % 1000);
furi_check(furi_message_queue_get(data->mq, &data->consumer_counter, 0) == FuriStatusOk);
FURI_LOG_I(
TAG, "consumer_mq_callback: %lu %lu", data->producer_counter, data->consumer_counter);
// Remove and add should not cause crash
// if(data->producer_counter == EVENT_LOOP_EVENT_COUNT/2) {
// furi_event_loop_message_queue_remove(data->consumer_event_loop, data->mq);
// furi_event_loop_message_queue_add(
// data->consumer_event_loop,
// data->mq,
// FuriEventLoopEventIn,
// test_furi_event_loop_producer_mq_callback,
// data);
// }
if(data->consumer_counter == EVENT_LOOP_EVENT_COUNT) {
furi_event_loop_stop(data->consumer_event_loop);
return false;
}
return true;
}
int32_t test_furi_event_loop_consumer(void* p) {
furi_check(p);
FURI_LOG_I(TAG, "consumer start");
TestFuriData* data = p;
data->consumer_event_loop = furi_event_loop_alloc();
furi_event_loop_message_queue_subscribe(
data->consumer_event_loop,
data->mq,
FuriEventLoopEventIn,
test_furi_event_loop_consumer_mq_callback,
data);
furi_event_loop_run(data->consumer_event_loop);
furi_event_loop_message_queue_unsubscribe(data->consumer_event_loop, data->mq);
furi_event_loop_free(data->consumer_event_loop);
FURI_LOG_I(TAG, "consumer end");
return 0;
}
void test_furi_event_loop(void) {
TestFuriData data = {};
data.mq = furi_message_queue_alloc(16, sizeof(uint32_t));
FuriThread* producer_thread = furi_thread_alloc();
furi_thread_set_name(producer_thread, "producer_thread");
furi_thread_set_stack_size(producer_thread, 1 * 1024);
furi_thread_set_callback(producer_thread, test_furi_event_loop_producer);
furi_thread_set_context(producer_thread, &data);
furi_thread_start(producer_thread);
FuriThread* consumer_thread = furi_thread_alloc();
furi_thread_set_name(consumer_thread, "consumer_thread");
furi_thread_set_stack_size(consumer_thread, 1 * 1024);
furi_thread_set_callback(consumer_thread, test_furi_event_loop_consumer);
furi_thread_set_context(consumer_thread, &data);
furi_thread_start(consumer_thread);
// Wait for thread to complete their tasks
furi_thread_join(producer_thread);
furi_thread_join(consumer_thread);
// The test itself
mu_assert_int_eq(data.producer_counter, data.consumer_counter);
// Release memory
furi_thread_free(consumer_thread);
furi_thread_free(producer_thread);
furi_message_queue_free(data.mq);
}

View File

@@ -6,8 +6,8 @@
void test_furi_create_open(void);
void test_furi_concurrent_access(void);
void test_furi_pubsub(void);
void test_furi_memmgr(void);
void test_furi_event_loop(void);
static int foo = 0;
@@ -38,15 +38,19 @@ MU_TEST(mu_test_furi_memmgr) {
test_furi_memmgr();
}
MU_TEST(mu_test_furi_event_loop) {
test_furi_event_loop();
}
MU_TEST_SUITE(test_suite) {
MU_SUITE_CONFIGURE(&test_setup, &test_teardown);
MU_RUN_TEST(test_check);
// v2 tests
MU_RUN_TEST(mu_test_furi_create_open);
MU_RUN_TEST(mu_test_furi_pubsub);
MU_RUN_TEST(mu_test_furi_memmgr);
MU_RUN_TEST(mu_test_furi_event_loop);
}
int run_minunit_test_furi(void) {

View File

@@ -46,8 +46,8 @@ static RpcSessionContext rpc_session[TEST_RPC_SESSIONS];
#define MAX_RECEIVE_OUTPUT_TIMEOUT 3000
#define MAX_NAME_LENGTH 255
#define MAX_DATA_SIZE 512u // have to be exact as in rpc_storage.c
#define TEST_DIR_NAME EXT_PATH(".tmp/unit_tests/rpc")
#define TEST_DIR TEST_DIR_NAME "/"
#define TEST_DIR_NAME EXT_PATH("unit_tests_tmp")
#define MD5SUM_SIZE 16
#define PING_REQUEST 0

View File

@@ -15,6 +15,8 @@ static const char* stream_test_left_data = "There are two cardinal human sins ";
static const char* stream_test_right_data =
"from which all others derive: impatience and indolence.";
#define FILESTREAM_PATH EXT_PATH(".tmp/unit_tests/filestream.str")
MU_TEST_1(stream_composite_subtest, Stream* stream) {
const size_t data_size = 128;
uint8_t data[data_size];
@@ -304,15 +306,14 @@ MU_TEST(stream_composite_test) {
// test file stream
Storage* storage = furi_record_open(RECORD_STORAGE);
stream = file_stream_alloc(storage);
mu_check(
file_stream_open(stream, EXT_PATH("filestream.str"), FSAM_READ_WRITE, FSOM_CREATE_ALWAYS));
mu_check(file_stream_open(stream, FILESTREAM_PATH, FSAM_READ_WRITE, FSOM_CREATE_ALWAYS));
MU_RUN_TEST_1(stream_composite_subtest, stream);
stream_free(stream);
// test buffered file stream
stream = buffered_file_stream_alloc(storage);
mu_check(buffered_file_stream_open(
stream, EXT_PATH("filestream.str"), FSAM_READ_WRITE, FSOM_CREATE_ALWAYS));
mu_check(
buffered_file_stream_open(stream, FILESTREAM_PATH, FSAM_READ_WRITE, FSOM_CREATE_ALWAYS));
MU_RUN_TEST_1(stream_composite_subtest, stream);
stream_free(stream);
furi_record_close(RECORD_STORAGE);
@@ -346,7 +347,7 @@ MU_TEST(stream_write_read_save_load_test) {
mu_check(stream_seek(stream_orig, 0, StreamOffsetFromStart));
mu_assert_int_eq(
strlen(stream_test_data),
stream_save_to_file(stream_orig, storage, EXT_PATH("filestream.str"), FSOM_CREATE_ALWAYS));
stream_save_to_file(stream_orig, storage, FILESTREAM_PATH, FSOM_CREATE_ALWAYS));
stream_free(stream_copy);
stream_free(stream_orig);
@@ -354,8 +355,7 @@ MU_TEST(stream_write_read_save_load_test) {
// load from file, read
Stream* stream_new = string_stream_alloc();
mu_assert_int_eq(
strlen(stream_test_data),
stream_load_from_file(stream_new, storage, EXT_PATH("filestream.str")));
strlen(stream_test_data), stream_load_from_file(stream_new, storage, FILESTREAM_PATH));
MU_RUN_TEST_1(stream_read_subtest, stream_new);
stream_free(stream_new);
@@ -396,15 +396,14 @@ MU_TEST(stream_split_test) {
// test file stream
Storage* storage = furi_record_open(RECORD_STORAGE);
stream = file_stream_alloc(storage);
mu_check(
file_stream_open(stream, EXT_PATH("filestream.str"), FSAM_READ_WRITE, FSOM_CREATE_ALWAYS));
mu_check(file_stream_open(stream, FILESTREAM_PATH, FSAM_READ_WRITE, FSOM_CREATE_ALWAYS));
MU_RUN_TEST_1(stream_split_subtest, stream);
stream_free(stream);
// test buffered stream
stream = buffered_file_stream_alloc(storage);
mu_check(buffered_file_stream_open(
stream, EXT_PATH("filestream.str"), FSAM_READ_WRITE, FSOM_CREATE_ALWAYS));
mu_check(
buffered_file_stream_open(stream, FILESTREAM_PATH, FSAM_READ_WRITE, FSOM_CREATE_ALWAYS));
MU_RUN_TEST_1(stream_split_subtest, stream);
stream_free(stream);
@@ -424,8 +423,8 @@ MU_TEST(stream_buffered_write_after_read_test) {
Storage* storage = furi_record_open(RECORD_STORAGE);
Stream* stream = buffered_file_stream_alloc(storage);
mu_check(buffered_file_stream_open(
stream, EXT_PATH("filestream.str"), FSAM_READ_WRITE, FSOM_CREATE_ALWAYS));
mu_check(
buffered_file_stream_open(stream, FILESTREAM_PATH, FSAM_READ_WRITE, FSOM_CREATE_ALWAYS));
mu_assert_int_eq(strlen(stream_test_data), stream_write_cstring(stream, stream_test_data));
mu_check(stream_rewind(stream));
mu_assert_int_eq(prefix_len, stream_read(stream, (uint8_t*)buf, prefix_len));
@@ -458,8 +457,8 @@ MU_TEST(stream_buffered_large_file_test) {
// write test data to file
Stream* stream = buffered_file_stream_alloc(storage);
mu_check(buffered_file_stream_open(
stream, EXT_PATH("filestream.str"), FSAM_READ_WRITE, FSOM_CREATE_ALWAYS));
mu_check(
buffered_file_stream_open(stream, FILESTREAM_PATH, FSAM_READ_WRITE, FSOM_CREATE_ALWAYS));
mu_assert_int_eq(0, stream_size(stream));
mu_assert_int_eq(furi_string_size(input_data), stream_write_string(stream, input_data));
mu_assert_int_eq(furi_string_size(input_data), stream_size(stream));

View File

@@ -6,11 +6,12 @@
#include <rpc/rpc_i.h>
#include <flipper.pb.h>
#include <core/event_loop.h>
static constexpr auto unit_tests_api_table = sort(create_array_t<sym_entry>(
API_METHOD(resource_manifest_reader_alloc, ResourceManifestReader*, (Storage*)),
API_METHOD(resource_manifest_reader_free, void, (ResourceManifestReader*)),
API_METHOD(resource_manifest_reader_open, bool, (ResourceManifestReader*, const char* filename)),
API_METHOD(resource_manifest_reader_open, bool, (ResourceManifestReader*, const char*)),
API_METHOD(resource_manifest_reader_next, ResourceManifestEntry*, (ResourceManifestReader*)),
API_METHOD(resource_manifest_reader_previous, ResourceManifestEntry*, (ResourceManifestReader*)),
API_METHOD(slix_process_iso15693_3_error, SlixError, (Iso15693_3Error)),
@@ -26,4 +27,17 @@ static constexpr auto unit_tests_api_table = sort(create_array_t<sym_entry>(
xQueueGenericSend,
BaseType_t,
(QueueHandle_t, const void* const, TickType_t, const BaseType_t)),
API_METHOD(furi_event_loop_alloc, FuriEventLoop*, (void)),
API_METHOD(furi_event_loop_free, void, (FuriEventLoop*)),
API_METHOD(
furi_event_loop_message_queue_subscribe,
void,
(FuriEventLoop*,
FuriMessageQueue*,
FuriEventLoopEvent,
FuriEventLoopMessageQueueCallback,
void*)),
API_METHOD(furi_event_loop_message_queue_unsubscribe, void, (FuriEventLoop*, FuriMessageQueue*)),
API_METHOD(furi_event_loop_run, void, (FuriEventLoop*)),
API_METHOD(furi_event_loop_stop, void, (FuriEventLoop*)),
API_VARIABLE(PB_Main_msg, PB_Main_msg_t)));

View File

@@ -40,7 +40,6 @@ static void usb_mouse_input_callback(InputEvent* input_event, void* ctx) {
int32_t usb_mouse_app(void* p) {
UNUSED(p);
FuriMessageQueue* event_queue = furi_message_queue_alloc(8, sizeof(UsbMouseEvent));
furi_check(event_queue);
ViewPort* view_port = view_port_alloc();
FuriHalUsbInterface* usb_mode_prev = furi_hal_usb_get_config();