[FL-2627] Flipper applications: SDK, build and debug system (#1387)
* Added support for running applications from SD card (FAPs - Flipper Application Packages) * Added plugin_dist target for fbt to build FAPs * All apps of type FlipperAppType.EXTERNAL and FlipperAppType.PLUGIN are built as FAPs by default * Updated VSCode configuration for new fbt features - re-deploy stock configuration to use them * Added debugging support for FAPs with fbt debug & VSCode * Added public firmware API with automated versioning Co-authored-by: hedger <hedger@users.noreply.github.com> Co-authored-by: SG <who.just.the.doctor@gmail.com> Co-authored-by: あく <alleteam@gmail.com>
This commit is contained in:
18
applications/debug/unit_tests/application.fam
Normal file
18
applications/debug/unit_tests/application.fam
Normal file
@@ -0,0 +1,18 @@
|
||||
App(
|
||||
appid="unit_tests",
|
||||
apptype=FlipperAppType.STARTUP,
|
||||
entry_point="unit_tests_on_system_start",
|
||||
cdefines=["APP_UNIT_TESTS"],
|
||||
provides=["delay_test"],
|
||||
order=100,
|
||||
)
|
||||
|
||||
App(
|
||||
appid="delay_test",
|
||||
name="Delay Test",
|
||||
apptype=FlipperAppType.SYSTEM,
|
||||
entry_point="delay_test_app",
|
||||
stack_size=1 * 1024,
|
||||
requires=["unit_tests"],
|
||||
order=110,
|
||||
)
|
@@ -0,0 +1,337 @@
|
||||
#include <furi.h>
|
||||
#include <flipper_format/flipper_format.h>
|
||||
#include <flipper_format/flipper_format_i.h>
|
||||
#include <toolbox/stream/stream.h>
|
||||
#include <storage/storage.h>
|
||||
#include "../minunit.h"
|
||||
|
||||
static const char* test_filetype = "Flipper Format test";
|
||||
static const uint32_t test_version = 666;
|
||||
|
||||
static const char* test_string_key = "String data";
|
||||
static const char* test_string_data = "String";
|
||||
static const char* test_string_updated_data = "New string";
|
||||
static const char* test_string_updated_2_data = "And some more";
|
||||
|
||||
static const char* test_int_key = "Int32 data";
|
||||
static const int32_t test_int_data[] = {1234, -6345, 7813, 0};
|
||||
static const int32_t test_int_updated_data[] = {-1337, 69};
|
||||
static const int32_t test_int_updated_2_data[] = {-3, -2, -1, 0, 1, 2, 3};
|
||||
|
||||
static const char* test_uint_key = "Uint32 data";
|
||||
static const uint32_t test_uint_data[] = {1234, 0, 5678, 9098, 7654321};
|
||||
static const uint32_t test_uint_updated_data[] = {8, 800, 555, 35, 35};
|
||||
static const uint32_t test_uint_updated_2_data[] = {20, 21};
|
||||
|
||||
static const char* test_float_key = "Float data";
|
||||
static const float test_float_data[] = {1.5f, 1000.0f};
|
||||
static const float test_float_updated_data[] = {1.2f};
|
||||
static const float test_float_updated_2_data[] = {0.01f, 0.0f, -51.6f};
|
||||
|
||||
static const char* test_hex_key = "Hex data";
|
||||
static const uint8_t test_hex_data[] = {0xDE, 0xAD, 0xBE};
|
||||
static const uint8_t test_hex_updated_data[] = {0xFE, 0xCA};
|
||||
static const uint8_t test_hex_updated_2_data[] = {0xCA, 0xCA, 0x05};
|
||||
|
||||
static const char* test_hex_new_key = "New Hex data";
|
||||
static const uint8_t test_hex_new_data[] = {0xFF, 0x6A, 0x91};
|
||||
|
||||
static const char* test_data_nix = "Filetype: Flipper Format test\n"
|
||||
"Version: 666\n"
|
||||
"# This is comment\n"
|
||||
"String data: String\n"
|
||||
"Int32 data: 1234 -6345 7813 0\n"
|
||||
"Uint32 data: 1234 0 5678 9098 7654321\n"
|
||||
"Float data: 1.5 1000.0\n"
|
||||
"Hex data: DE AD BE";
|
||||
|
||||
static const char* test_data_win = "Filetype: Flipper Format test\r\n"
|
||||
"Version: 666\r\n"
|
||||
"# This is comment\r\n"
|
||||
"String data: String\r\n"
|
||||
"Int32 data: 1234 -6345 7813 0\r\n"
|
||||
"Uint32 data: 1234 0 5678 9098 7654321\r\n"
|
||||
"Float data: 1.5 1000.0\r\n"
|
||||
"Hex data: DE AD BE";
|
||||
|
||||
#define ARRAY_W_COUNT(x) (x), (COUNT_OF(x))
|
||||
#define ARRAY_W_BSIZE(x) (x), (sizeof(x))
|
||||
|
||||
MU_TEST_1(flipper_format_read_and_update_test, FlipperFormat* flipper_format) {
|
||||
string_t tmpstr;
|
||||
uint32_t version;
|
||||
uint32_t uint32_data[COUNT_OF(test_uint_data)];
|
||||
int32_t int32_data[COUNT_OF(test_int_data)];
|
||||
float float_data[COUNT_OF(test_float_data)];
|
||||
uint8_t hex_data[COUNT_OF(test_hex_data)];
|
||||
|
||||
uint32_t count;
|
||||
|
||||
// key exist test
|
||||
size_t position_before = stream_tell(flipper_format_get_raw_stream(flipper_format));
|
||||
mu_check(flipper_format_key_exist(flipper_format, test_hex_key));
|
||||
mu_assert_int_eq(position_before, stream_tell(flipper_format_get_raw_stream(flipper_format)));
|
||||
|
||||
mu_check(!flipper_format_key_exist(flipper_format, "invalid key"));
|
||||
mu_assert_int_eq(position_before, stream_tell(flipper_format_get_raw_stream(flipper_format)));
|
||||
|
||||
// stream seek to end test
|
||||
mu_check(flipper_format_seek_to_end(flipper_format));
|
||||
mu_assert_int_eq(
|
||||
stream_size(flipper_format_get_raw_stream(flipper_format)),
|
||||
stream_tell(flipper_format_get_raw_stream(flipper_format)));
|
||||
|
||||
// key exist test
|
||||
position_before = stream_tell(flipper_format_get_raw_stream(flipper_format));
|
||||
mu_check(flipper_format_key_exist(flipper_format, test_hex_key));
|
||||
mu_assert_int_eq(position_before, stream_tell(flipper_format_get_raw_stream(flipper_format)));
|
||||
|
||||
mu_check(!flipper_format_key_exist(flipper_format, "invalid key"));
|
||||
mu_assert_int_eq(position_before, stream_tell(flipper_format_get_raw_stream(flipper_format)));
|
||||
|
||||
// rewind
|
||||
mu_check(flipper_format_rewind(flipper_format));
|
||||
|
||||
// key exist test
|
||||
position_before = stream_tell(flipper_format_get_raw_stream(flipper_format));
|
||||
mu_check(flipper_format_key_exist(flipper_format, test_hex_key));
|
||||
mu_assert_int_eq(position_before, stream_tell(flipper_format_get_raw_stream(flipper_format)));
|
||||
|
||||
mu_check(!flipper_format_key_exist(flipper_format, "invalid key"));
|
||||
mu_assert_int_eq(position_before, stream_tell(flipper_format_get_raw_stream(flipper_format)));
|
||||
|
||||
// read test
|
||||
string_init(tmpstr);
|
||||
|
||||
mu_check(flipper_format_read_header(flipper_format, tmpstr, &version));
|
||||
mu_assert_string_eq(test_filetype, string_get_cstr(tmpstr));
|
||||
mu_assert_int_eq(test_version, version);
|
||||
|
||||
mu_check(flipper_format_read_string(flipper_format, test_string_key, tmpstr));
|
||||
mu_assert_string_eq(test_string_data, string_get_cstr(tmpstr));
|
||||
|
||||
mu_check(flipper_format_get_value_count(flipper_format, test_int_key, &count));
|
||||
mu_assert_int_eq(COUNT_OF(test_int_data), count);
|
||||
mu_check(flipper_format_read_int32(flipper_format, test_int_key, ARRAY_W_COUNT(int32_data)));
|
||||
mu_check(memcmp(test_int_data, ARRAY_W_BSIZE(int32_data)) == 0);
|
||||
|
||||
mu_check(flipper_format_get_value_count(flipper_format, test_uint_key, &count));
|
||||
mu_assert_int_eq(COUNT_OF(test_uint_data), count);
|
||||
mu_check(
|
||||
flipper_format_read_uint32(flipper_format, test_uint_key, ARRAY_W_COUNT(uint32_data)));
|
||||
mu_check(memcmp(test_uint_data, ARRAY_W_BSIZE(uint32_data)) == 0);
|
||||
|
||||
mu_check(flipper_format_get_value_count(flipper_format, test_float_key, &count));
|
||||
mu_assert_int_eq(COUNT_OF(test_float_data), count);
|
||||
mu_check(flipper_format_read_float(flipper_format, test_float_key, ARRAY_W_COUNT(float_data)));
|
||||
mu_check(memcmp(test_float_data, ARRAY_W_BSIZE(float_data)) == 0);
|
||||
|
||||
mu_check(flipper_format_get_value_count(flipper_format, test_hex_key, &count));
|
||||
mu_assert_int_eq(COUNT_OF(test_hex_data), count);
|
||||
mu_check(flipper_format_read_hex(flipper_format, test_hex_key, ARRAY_W_COUNT(hex_data)));
|
||||
mu_check(memcmp(test_hex_data, ARRAY_W_BSIZE(hex_data)) == 0);
|
||||
|
||||
mu_check(!flipper_format_read_string(flipper_format, "Key that doesn't exist", tmpstr));
|
||||
|
||||
string_clear(tmpstr);
|
||||
|
||||
// update data
|
||||
mu_check(flipper_format_rewind(flipper_format));
|
||||
mu_check(flipper_format_update_string_cstr(
|
||||
flipper_format, test_string_key, test_string_updated_data));
|
||||
mu_check(flipper_format_update_int32(
|
||||
flipper_format, test_int_key, ARRAY_W_COUNT(test_int_updated_data)));
|
||||
mu_check(flipper_format_update_uint32(
|
||||
flipper_format, test_uint_key, ARRAY_W_COUNT(test_uint_updated_data)));
|
||||
mu_check(flipper_format_update_float(
|
||||
flipper_format, test_float_key, ARRAY_W_COUNT(test_float_updated_data)));
|
||||
mu_check(flipper_format_update_hex(
|
||||
flipper_format, test_hex_key, ARRAY_W_COUNT(test_hex_updated_data)));
|
||||
|
||||
// read updated data test
|
||||
uint32_t uint32_updated_data[COUNT_OF(test_uint_updated_data)];
|
||||
int32_t int32_updated_data[COUNT_OF(test_int_updated_data)];
|
||||
float float_updated_data[COUNT_OF(test_float_updated_data)];
|
||||
uint8_t hex_updated_data[COUNT_OF(test_hex_updated_data)];
|
||||
|
||||
mu_check(flipper_format_rewind(flipper_format));
|
||||
string_init(tmpstr);
|
||||
|
||||
mu_check(flipper_format_read_header(flipper_format, tmpstr, &version));
|
||||
mu_assert_string_eq(test_filetype, string_get_cstr(tmpstr));
|
||||
mu_assert_int_eq(test_version, version);
|
||||
|
||||
mu_check(flipper_format_read_string(flipper_format, test_string_key, tmpstr));
|
||||
mu_assert_string_eq(test_string_updated_data, string_get_cstr(tmpstr));
|
||||
|
||||
mu_check(flipper_format_get_value_count(flipper_format, test_int_key, &count));
|
||||
mu_assert_int_eq(COUNT_OF(test_int_updated_data), count);
|
||||
mu_check(flipper_format_read_int32(
|
||||
flipper_format, test_int_key, ARRAY_W_COUNT(int32_updated_data)));
|
||||
mu_check(memcmp(test_int_updated_data, ARRAY_W_BSIZE(int32_updated_data)) == 0);
|
||||
|
||||
mu_check(flipper_format_get_value_count(flipper_format, test_uint_key, &count));
|
||||
mu_assert_int_eq(COUNT_OF(test_uint_updated_data), count);
|
||||
mu_check(flipper_format_read_uint32(
|
||||
flipper_format, test_uint_key, ARRAY_W_COUNT(uint32_updated_data)));
|
||||
mu_check(memcmp(test_uint_updated_data, ARRAY_W_BSIZE(uint32_updated_data)) == 0);
|
||||
|
||||
mu_check(flipper_format_get_value_count(flipper_format, test_float_key, &count));
|
||||
mu_assert_int_eq(COUNT_OF(test_float_updated_data), count);
|
||||
mu_check(flipper_format_read_float(
|
||||
flipper_format, test_float_key, ARRAY_W_COUNT(float_updated_data)));
|
||||
mu_check(memcmp(test_float_updated_data, ARRAY_W_BSIZE(float_updated_data)) == 0);
|
||||
|
||||
mu_check(flipper_format_get_value_count(flipper_format, test_hex_key, &count));
|
||||
mu_assert_int_eq(COUNT_OF(test_hex_updated_data), count);
|
||||
mu_check(
|
||||
flipper_format_read_hex(flipper_format, test_hex_key, ARRAY_W_COUNT(hex_updated_data)));
|
||||
mu_check(memcmp(test_hex_updated_data, ARRAY_W_BSIZE(hex_updated_data)) == 0);
|
||||
|
||||
mu_check(!flipper_format_read_string(flipper_format, "Key that doesn't exist", tmpstr));
|
||||
|
||||
string_clear(tmpstr);
|
||||
|
||||
// update data
|
||||
mu_check(flipper_format_rewind(flipper_format));
|
||||
mu_check(flipper_format_insert_or_update_string_cstr(
|
||||
flipper_format, test_string_key, test_string_updated_2_data));
|
||||
mu_check(flipper_format_insert_or_update_int32(
|
||||
flipper_format, test_int_key, ARRAY_W_COUNT(test_int_updated_2_data)));
|
||||
mu_check(flipper_format_insert_or_update_uint32(
|
||||
flipper_format, test_uint_key, ARRAY_W_COUNT(test_uint_updated_2_data)));
|
||||
mu_check(flipper_format_insert_or_update_float(
|
||||
flipper_format, test_float_key, ARRAY_W_COUNT(test_float_updated_2_data)));
|
||||
mu_check(flipper_format_insert_or_update_hex(
|
||||
flipper_format, test_hex_key, ARRAY_W_COUNT(test_hex_updated_2_data)));
|
||||
mu_check(flipper_format_insert_or_update_hex(
|
||||
flipper_format, test_hex_new_key, ARRAY_W_COUNT(test_hex_new_data)));
|
||||
|
||||
uint32_t uint32_updated_2_data[COUNT_OF(test_uint_updated_2_data)];
|
||||
int32_t int32_updated_2_data[COUNT_OF(test_int_updated_2_data)];
|
||||
float float_updated_2_data[COUNT_OF(test_float_updated_2_data)];
|
||||
uint8_t hex_updated_2_data[COUNT_OF(test_hex_updated_2_data)];
|
||||
uint8_t hex_new_data[COUNT_OF(test_hex_new_data)];
|
||||
|
||||
mu_check(flipper_format_rewind(flipper_format));
|
||||
string_init(tmpstr);
|
||||
|
||||
mu_check(flipper_format_read_header(flipper_format, tmpstr, &version));
|
||||
mu_assert_string_eq(test_filetype, string_get_cstr(tmpstr));
|
||||
mu_assert_int_eq(test_version, version);
|
||||
|
||||
mu_check(flipper_format_read_string(flipper_format, test_string_key, tmpstr));
|
||||
mu_assert_string_eq(test_string_updated_2_data, string_get_cstr(tmpstr));
|
||||
|
||||
mu_check(flipper_format_get_value_count(flipper_format, test_int_key, &count));
|
||||
mu_assert_int_eq(COUNT_OF(test_int_updated_2_data), count);
|
||||
mu_check(flipper_format_read_int32(
|
||||
flipper_format, test_int_key, ARRAY_W_COUNT(int32_updated_2_data)));
|
||||
mu_check(memcmp(test_int_updated_2_data, ARRAY_W_BSIZE(int32_updated_2_data)) == 0);
|
||||
|
||||
mu_check(flipper_format_get_value_count(flipper_format, test_uint_key, &count));
|
||||
mu_assert_int_eq(COUNT_OF(test_uint_updated_2_data), count);
|
||||
mu_check(flipper_format_read_uint32(
|
||||
flipper_format, test_uint_key, ARRAY_W_COUNT(uint32_updated_2_data)));
|
||||
mu_check(memcmp(test_uint_updated_2_data, ARRAY_W_BSIZE(uint32_updated_2_data)) == 0);
|
||||
|
||||
mu_check(flipper_format_get_value_count(flipper_format, test_float_key, &count));
|
||||
mu_assert_int_eq(COUNT_OF(test_float_updated_2_data), count);
|
||||
mu_check(flipper_format_read_float(
|
||||
flipper_format, test_float_key, ARRAY_W_COUNT(float_updated_2_data)));
|
||||
mu_check(memcmp(test_float_updated_2_data, ARRAY_W_BSIZE(float_updated_2_data)) == 0);
|
||||
|
||||
mu_check(flipper_format_get_value_count(flipper_format, test_hex_key, &count));
|
||||
mu_assert_int_eq(COUNT_OF(test_hex_updated_2_data), count);
|
||||
mu_check(
|
||||
flipper_format_read_hex(flipper_format, test_hex_key, ARRAY_W_COUNT(hex_updated_2_data)));
|
||||
mu_check(memcmp(test_hex_updated_2_data, ARRAY_W_BSIZE(hex_updated_2_data)) == 0);
|
||||
|
||||
mu_check(flipper_format_get_value_count(flipper_format, test_hex_new_key, &count));
|
||||
mu_assert_int_eq(COUNT_OF(test_hex_new_data), count);
|
||||
mu_check(
|
||||
flipper_format_read_hex(flipper_format, test_hex_new_key, ARRAY_W_COUNT(hex_new_data)));
|
||||
mu_check(memcmp(test_hex_new_data, ARRAY_W_BSIZE(hex_new_data)) == 0);
|
||||
|
||||
mu_check(!flipper_format_read_string(flipper_format, "Key that doesn't exist", tmpstr));
|
||||
|
||||
string_clear(tmpstr);
|
||||
|
||||
// delete key test
|
||||
mu_check(flipper_format_rewind(flipper_format));
|
||||
mu_check(flipper_format_delete_key(flipper_format, test_uint_key));
|
||||
|
||||
// deleted key read test
|
||||
mu_check(flipper_format_rewind(flipper_format));
|
||||
mu_check(!flipper_format_read_uint32(
|
||||
flipper_format, test_uint_key, ARRAY_W_COUNT(uint32_updated_data)));
|
||||
}
|
||||
|
||||
MU_TEST(flipper_format_string_test) {
|
||||
FlipperFormat* flipper_format = flipper_format_string_alloc();
|
||||
Stream* stream = flipper_format_get_raw_stream(flipper_format);
|
||||
|
||||
mu_check(flipper_format_write_header_cstr(flipper_format, test_filetype, test_version));
|
||||
mu_check(flipper_format_write_comment_cstr(flipper_format, "This is comment"));
|
||||
mu_check(flipper_format_write_string_cstr(flipper_format, test_string_key, test_string_data));
|
||||
mu_check(
|
||||
flipper_format_write_int32(flipper_format, test_int_key, ARRAY_W_COUNT(test_int_data)));
|
||||
mu_check(
|
||||
flipper_format_write_uint32(flipper_format, test_uint_key, ARRAY_W_COUNT(test_uint_data)));
|
||||
mu_check(flipper_format_write_float(
|
||||
flipper_format, test_float_key, ARRAY_W_COUNT(test_float_data)));
|
||||
mu_check(flipper_format_write_hex(flipper_format, test_hex_key, ARRAY_W_COUNT(test_hex_data)));
|
||||
|
||||
MU_RUN_TEST_1(flipper_format_read_and_update_test, flipper_format);
|
||||
|
||||
stream_clean(stream);
|
||||
stream_write_cstring(stream, test_data_nix);
|
||||
MU_RUN_TEST_1(flipper_format_read_and_update_test, flipper_format);
|
||||
|
||||
stream_clean(stream);
|
||||
stream_write_cstring(stream, test_data_win);
|
||||
MU_RUN_TEST_1(flipper_format_read_and_update_test, flipper_format);
|
||||
|
||||
flipper_format_free(flipper_format);
|
||||
}
|
||||
|
||||
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")));
|
||||
Stream* stream = flipper_format_get_raw_stream(flipper_format);
|
||||
|
||||
mu_check(flipper_format_write_header_cstr(flipper_format, test_filetype, test_version));
|
||||
mu_check(flipper_format_write_comment_cstr(flipper_format, "This is comment"));
|
||||
mu_check(flipper_format_write_string_cstr(flipper_format, test_string_key, test_string_data));
|
||||
mu_check(
|
||||
flipper_format_write_int32(flipper_format, test_int_key, ARRAY_W_COUNT(test_int_data)));
|
||||
mu_check(
|
||||
flipper_format_write_uint32(flipper_format, test_uint_key, ARRAY_W_COUNT(test_uint_data)));
|
||||
mu_check(flipper_format_write_float(
|
||||
flipper_format, test_float_key, ARRAY_W_COUNT(test_float_data)));
|
||||
mu_check(flipper_format_write_hex(flipper_format, test_hex_key, ARRAY_W_COUNT(test_hex_data)));
|
||||
|
||||
MU_RUN_TEST_1(flipper_format_read_and_update_test, flipper_format);
|
||||
|
||||
stream_clean(stream);
|
||||
stream_write_cstring(stream, test_data_nix);
|
||||
MU_RUN_TEST_1(flipper_format_read_and_update_test, flipper_format);
|
||||
|
||||
stream_clean(stream);
|
||||
stream_write_cstring(stream, test_data_win);
|
||||
MU_RUN_TEST_1(flipper_format_read_and_update_test, flipper_format);
|
||||
|
||||
flipper_format_free(flipper_format);
|
||||
furi_record_close(RECORD_STORAGE);
|
||||
}
|
||||
|
||||
MU_TEST_SUITE(flipper_format_string_suite) {
|
||||
MU_RUN_TEST(flipper_format_string_test);
|
||||
MU_RUN_TEST(flipper_format_file_test);
|
||||
}
|
||||
|
||||
int run_minunit_test_flipper_format_string() {
|
||||
MU_RUN_SUITE(flipper_format_string_suite);
|
||||
return MU_EXIT_CODE;
|
||||
}
|
@@ -0,0 +1,525 @@
|
||||
#include <furi.h>
|
||||
#include <flipper_format/flipper_format.h>
|
||||
#include <flipper_format/flipper_format_i.h>
|
||||
#include <toolbox/stream/stream.h>
|
||||
#include "../minunit.h"
|
||||
|
||||
#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;
|
||||
|
||||
static const char* test_string_key = "String data";
|
||||
static const char* test_string_data = "String";
|
||||
static const char* test_string_updated_data = "New string";
|
||||
|
||||
static const char* test_int_key = "Int32 data";
|
||||
static const int32_t test_int_data[] = {1234, -6345, 7813, 0};
|
||||
static const int32_t test_int_updated_data[] = {-1337, 69};
|
||||
|
||||
static const char* test_uint_key = "Uint32 data";
|
||||
static const uint32_t test_uint_data[] = {1234, 0, 5678, 9098, 7654321};
|
||||
static const uint32_t test_uint_updated_data[] = {8, 800, 555, 35, 35};
|
||||
|
||||
static const char* test_float_key = "Float data";
|
||||
static const float test_float_data[] = {1.5f, 1000.0f};
|
||||
static const float test_float_updated_data[] = {1.2f};
|
||||
|
||||
static const char* test_bool_key = "Bool data";
|
||||
static const bool test_bool_data[] = {true, false};
|
||||
static const bool test_bool_updated_data[] = {false, true, true};
|
||||
|
||||
static const char* test_hex_key = "Hex data";
|
||||
static const uint8_t test_hex_data[] = {0xDE, 0xAD, 0xBE};
|
||||
static const uint8_t test_hex_updated_data[] = {0xFE, 0xCA};
|
||||
|
||||
#define READ_TEST_NIX "ff_nix.test"
|
||||
static const char* test_data_nix = "Filetype: Flipper File test\n"
|
||||
"Version: 666\n"
|
||||
"# This is comment\n"
|
||||
"String data: String\n"
|
||||
"Int32 data: 1234 -6345 7813 0\n"
|
||||
"Uint32 data: 1234 0 5678 9098 7654321\n"
|
||||
"Float data: 1.5 1000.0\n"
|
||||
"Bool data: true false\n"
|
||||
"Hex data: DE AD BE";
|
||||
|
||||
#define READ_TEST_WIN "ff_win.test"
|
||||
static const char* test_data_win = "Filetype: Flipper File test\r\n"
|
||||
"Version: 666\r\n"
|
||||
"# This is comment\r\n"
|
||||
"String data: String\r\n"
|
||||
"Int32 data: 1234 -6345 7813 0\r\n"
|
||||
"Uint32 data: 1234 0 5678 9098 7654321\r\n"
|
||||
"Float data: 1.5 1000.0\r\n"
|
||||
"Bool data: true false\r\n"
|
||||
"Hex data: DE AD BE";
|
||||
|
||||
#define READ_TEST_FLP "ff_flp.test"
|
||||
|
||||
// data created by user on linux machine
|
||||
static const char* test_file_linux = TEST_DIR READ_TEST_NIX;
|
||||
// data created by user on windows machine
|
||||
static const char* test_file_windows = TEST_DIR READ_TEST_WIN;
|
||||
// data created by flipper itself
|
||||
static const char* test_file_flipper = TEST_DIR READ_TEST_FLP;
|
||||
|
||||
static bool storage_write_string(const char* path, const char* data) {
|
||||
Storage* storage = furi_record_open(RECORD_STORAGE);
|
||||
File* file = storage_file_alloc(storage);
|
||||
bool result = false;
|
||||
|
||||
do {
|
||||
if(!storage_file_open(file, path, FSAM_WRITE, FSOM_CREATE_ALWAYS)) break;
|
||||
if(storage_file_write(file, data, strlen(data)) != strlen(data)) break;
|
||||
|
||||
result = true;
|
||||
} while(false);
|
||||
|
||||
storage_file_close(file);
|
||||
storage_file_free(file);
|
||||
furi_record_close(RECORD_STORAGE);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static void tests_setup() {
|
||||
Storage* storage = furi_record_open(RECORD_STORAGE);
|
||||
mu_assert(storage_simply_remove_recursive(storage, TEST_DIR_NAME), "Cannot clean data");
|
||||
mu_assert(storage_simply_mkdir(storage, TEST_DIR_NAME), "Cannot create dir");
|
||||
furi_record_close(RECORD_STORAGE);
|
||||
}
|
||||
|
||||
static void tests_teardown() {
|
||||
Storage* storage = furi_record_open(RECORD_STORAGE);
|
||||
mu_assert(storage_simply_remove_recursive(storage, TEST_DIR_NAME), "Cannot clean data");
|
||||
furi_record_close(RECORD_STORAGE);
|
||||
}
|
||||
|
||||
static bool test_read(const char* file_name) {
|
||||
Storage* storage = furi_record_open(RECORD_STORAGE);
|
||||
bool result = false;
|
||||
|
||||
FlipperFormat* file = flipper_format_file_alloc(storage);
|
||||
string_t string_value;
|
||||
string_init(string_value);
|
||||
uint32_t uint32_value;
|
||||
void* scratchpad = malloc(512);
|
||||
|
||||
do {
|
||||
if(!flipper_format_file_open_existing(file, file_name)) break;
|
||||
|
||||
if(!flipper_format_read_header(file, string_value, &uint32_value)) break;
|
||||
if(string_cmp_str(string_value, test_filetype) != 0) break;
|
||||
if(uint32_value != test_version) break;
|
||||
|
||||
if(!flipper_format_read_string(file, test_string_key, string_value)) break;
|
||||
if(string_cmp_str(string_value, test_string_data) != 0) break;
|
||||
|
||||
if(!flipper_format_get_value_count(file, test_int_key, &uint32_value)) break;
|
||||
if(uint32_value != COUNT_OF(test_int_data)) break;
|
||||
if(!flipper_format_read_int32(file, test_int_key, scratchpad, uint32_value)) break;
|
||||
if(memcmp(scratchpad, test_int_data, sizeof(int32_t) * COUNT_OF(test_int_data)) != 0)
|
||||
break;
|
||||
|
||||
if(!flipper_format_get_value_count(file, test_uint_key, &uint32_value)) break;
|
||||
if(uint32_value != COUNT_OF(test_uint_data)) break;
|
||||
if(!flipper_format_read_uint32(file, test_uint_key, scratchpad, uint32_value)) break;
|
||||
if(memcmp(scratchpad, test_uint_data, sizeof(uint32_t) * COUNT_OF(test_uint_data)) != 0)
|
||||
break;
|
||||
|
||||
if(!flipper_format_get_value_count(file, test_float_key, &uint32_value)) break;
|
||||
if(uint32_value != COUNT_OF(test_float_data)) break;
|
||||
if(!flipper_format_read_float(file, test_float_key, scratchpad, uint32_value)) break;
|
||||
if(memcmp(scratchpad, test_float_data, sizeof(float) * COUNT_OF(test_float_data)) != 0)
|
||||
break;
|
||||
|
||||
if(!flipper_format_get_value_count(file, test_bool_key, &uint32_value)) break;
|
||||
if(uint32_value != COUNT_OF(test_bool_data)) break;
|
||||
if(!flipper_format_read_bool(file, test_bool_key, scratchpad, uint32_value)) break;
|
||||
if(memcmp(scratchpad, test_bool_data, sizeof(bool) * COUNT_OF(test_bool_data)) != 0) break;
|
||||
|
||||
if(!flipper_format_get_value_count(file, test_hex_key, &uint32_value)) break;
|
||||
if(uint32_value != COUNT_OF(test_hex_data)) break;
|
||||
if(!flipper_format_read_hex(file, test_hex_key, scratchpad, uint32_value)) break;
|
||||
if(memcmp(scratchpad, test_hex_data, sizeof(uint8_t) * COUNT_OF(test_hex_data)) != 0)
|
||||
break;
|
||||
|
||||
result = true;
|
||||
} while(false);
|
||||
|
||||
free(scratchpad);
|
||||
string_clear(string_value);
|
||||
|
||||
flipper_format_free(file);
|
||||
|
||||
furi_record_close(RECORD_STORAGE);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static bool test_read_updated(const char* file_name) {
|
||||
Storage* storage = furi_record_open(RECORD_STORAGE);
|
||||
bool result = false;
|
||||
|
||||
FlipperFormat* file = flipper_format_file_alloc(storage);
|
||||
string_t string_value;
|
||||
string_init(string_value);
|
||||
uint32_t uint32_value;
|
||||
void* scratchpad = malloc(512);
|
||||
|
||||
do {
|
||||
if(!flipper_format_file_open_existing(file, file_name)) break;
|
||||
|
||||
if(!flipper_format_read_header(file, string_value, &uint32_value)) break;
|
||||
if(string_cmp_str(string_value, test_filetype) != 0) break;
|
||||
if(uint32_value != test_version) break;
|
||||
|
||||
if(!flipper_format_read_string(file, test_string_key, string_value)) break;
|
||||
if(string_cmp_str(string_value, test_string_updated_data) != 0) break;
|
||||
|
||||
if(!flipper_format_get_value_count(file, test_int_key, &uint32_value)) break;
|
||||
if(uint32_value != COUNT_OF(test_int_updated_data)) break;
|
||||
if(!flipper_format_read_int32(file, test_int_key, scratchpad, uint32_value)) break;
|
||||
if(memcmp(
|
||||
scratchpad,
|
||||
test_int_updated_data,
|
||||
sizeof(int32_t) * COUNT_OF(test_int_updated_data)) != 0)
|
||||
break;
|
||||
|
||||
if(!flipper_format_get_value_count(file, test_uint_key, &uint32_value)) break;
|
||||
if(uint32_value != COUNT_OF(test_uint_updated_data)) break;
|
||||
if(!flipper_format_read_uint32(file, test_uint_key, scratchpad, uint32_value)) break;
|
||||
if(memcmp(
|
||||
scratchpad,
|
||||
test_uint_updated_data,
|
||||
sizeof(uint32_t) * COUNT_OF(test_uint_updated_data)) != 0)
|
||||
break;
|
||||
|
||||
if(!flipper_format_get_value_count(file, test_float_key, &uint32_value)) break;
|
||||
if(uint32_value != COUNT_OF(test_float_updated_data)) break;
|
||||
if(!flipper_format_read_float(file, test_float_key, scratchpad, uint32_value)) break;
|
||||
if(memcmp(
|
||||
scratchpad,
|
||||
test_float_updated_data,
|
||||
sizeof(float) * COUNT_OF(test_float_updated_data)) != 0)
|
||||
break;
|
||||
|
||||
if(!flipper_format_get_value_count(file, test_bool_key, &uint32_value)) break;
|
||||
if(uint32_value != COUNT_OF(test_bool_updated_data)) break;
|
||||
if(!flipper_format_read_bool(file, test_bool_key, scratchpad, uint32_value)) break;
|
||||
if(memcmp(
|
||||
scratchpad,
|
||||
test_bool_updated_data,
|
||||
sizeof(bool) * COUNT_OF(test_bool_updated_data)) != 0)
|
||||
break;
|
||||
|
||||
if(!flipper_format_get_value_count(file, test_hex_key, &uint32_value)) break;
|
||||
if(uint32_value != COUNT_OF(test_hex_updated_data)) break;
|
||||
if(!flipper_format_read_hex(file, test_hex_key, scratchpad, uint32_value)) break;
|
||||
if(memcmp(
|
||||
scratchpad,
|
||||
test_hex_updated_data,
|
||||
sizeof(uint8_t) * COUNT_OF(test_hex_updated_data)) != 0)
|
||||
break;
|
||||
|
||||
result = true;
|
||||
} while(false);
|
||||
|
||||
free(scratchpad);
|
||||
string_clear(string_value);
|
||||
|
||||
flipper_format_free(file);
|
||||
|
||||
furi_record_close(RECORD_STORAGE);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static bool test_write(const char* file_name) {
|
||||
Storage* storage = furi_record_open(RECORD_STORAGE);
|
||||
bool result = false;
|
||||
FlipperFormat* file = flipper_format_file_alloc(storage);
|
||||
|
||||
do {
|
||||
if(!flipper_format_file_open_always(file, file_name)) break;
|
||||
if(!flipper_format_write_header_cstr(file, test_filetype, test_version)) break;
|
||||
if(!flipper_format_write_comment_cstr(file, "This is comment")) break;
|
||||
if(!flipper_format_write_string_cstr(file, test_string_key, test_string_data)) break;
|
||||
if(!flipper_format_write_int32(file, test_int_key, test_int_data, COUNT_OF(test_int_data)))
|
||||
break;
|
||||
if(!flipper_format_write_uint32(
|
||||
file, test_uint_key, test_uint_data, COUNT_OF(test_uint_data)))
|
||||
break;
|
||||
if(!flipper_format_write_float(
|
||||
file, test_float_key, test_float_data, COUNT_OF(test_float_data)))
|
||||
break;
|
||||
if(!flipper_format_write_bool(
|
||||
file, test_bool_key, test_bool_data, COUNT_OF(test_bool_data)))
|
||||
break;
|
||||
if(!flipper_format_write_hex(file, test_hex_key, test_hex_data, COUNT_OF(test_hex_data)))
|
||||
break;
|
||||
result = true;
|
||||
} while(false);
|
||||
|
||||
flipper_format_free(file);
|
||||
furi_record_close(RECORD_STORAGE);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static bool test_delete_last_key(const char* file_name) {
|
||||
Storage* storage = furi_record_open(RECORD_STORAGE);
|
||||
bool result = false;
|
||||
FlipperFormat* file = flipper_format_file_alloc(storage);
|
||||
|
||||
do {
|
||||
if(!flipper_format_file_open_existing(file, file_name)) break;
|
||||
if(!flipper_format_delete_key(file, test_hex_key)) break;
|
||||
result = true;
|
||||
} while(false);
|
||||
|
||||
flipper_format_free(file);
|
||||
furi_record_close(RECORD_STORAGE);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static bool test_append_key(const char* file_name) {
|
||||
Storage* storage = furi_record_open(RECORD_STORAGE);
|
||||
bool result = false;
|
||||
FlipperFormat* file = flipper_format_file_alloc(storage);
|
||||
|
||||
do {
|
||||
if(!flipper_format_file_open_append(file, file_name)) break;
|
||||
if(!flipper_format_write_hex(file, test_hex_key, test_hex_data, COUNT_OF(test_hex_data)))
|
||||
break;
|
||||
result = true;
|
||||
} while(false);
|
||||
|
||||
flipper_format_free(file);
|
||||
furi_record_close(RECORD_STORAGE);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static bool test_update(const char* file_name) {
|
||||
Storage* storage = furi_record_open(RECORD_STORAGE);
|
||||
bool result = false;
|
||||
FlipperFormat* file = flipper_format_file_alloc(storage);
|
||||
|
||||
do {
|
||||
if(!flipper_format_file_open_existing(file, file_name)) break;
|
||||
if(!flipper_format_update_string_cstr(file, test_string_key, test_string_updated_data))
|
||||
break;
|
||||
if(!flipper_format_update_int32(
|
||||
file, test_int_key, test_int_updated_data, COUNT_OF(test_int_updated_data)))
|
||||
break;
|
||||
if(!flipper_format_update_uint32(
|
||||
file, test_uint_key, test_uint_updated_data, COUNT_OF(test_uint_updated_data)))
|
||||
break;
|
||||
if(!flipper_format_update_float(
|
||||
file, test_float_key, test_float_updated_data, COUNT_OF(test_float_updated_data)))
|
||||
break;
|
||||
if(!flipper_format_update_bool(
|
||||
file, test_bool_key, test_bool_updated_data, COUNT_OF(test_bool_updated_data)))
|
||||
break;
|
||||
if(!flipper_format_update_hex(
|
||||
file, test_hex_key, test_hex_updated_data, COUNT_OF(test_hex_updated_data)))
|
||||
break;
|
||||
|
||||
result = true;
|
||||
} while(false);
|
||||
|
||||
flipper_format_free(file);
|
||||
furi_record_close(RECORD_STORAGE);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static bool test_update_backward(const char* file_name) {
|
||||
Storage* storage = furi_record_open(RECORD_STORAGE);
|
||||
bool result = false;
|
||||
FlipperFormat* file = flipper_format_file_alloc(storage);
|
||||
|
||||
do {
|
||||
if(!flipper_format_file_open_existing(file, file_name)) break;
|
||||
if(!flipper_format_update_string_cstr(file, test_string_key, test_string_data)) break;
|
||||
if(!flipper_format_update_int32(file, test_int_key, test_int_data, COUNT_OF(test_int_data)))
|
||||
break;
|
||||
if(!flipper_format_update_uint32(
|
||||
file, test_uint_key, test_uint_data, COUNT_OF(test_uint_data)))
|
||||
break;
|
||||
if(!flipper_format_update_float(
|
||||
file, test_float_key, test_float_data, COUNT_OF(test_float_data)))
|
||||
break;
|
||||
if(!flipper_format_update_bool(
|
||||
file, test_bool_key, test_bool_data, COUNT_OF(test_bool_data)))
|
||||
break;
|
||||
if(!flipper_format_update_hex(file, test_hex_key, test_hex_data, COUNT_OF(test_hex_data)))
|
||||
break;
|
||||
|
||||
result = true;
|
||||
} while(false);
|
||||
|
||||
flipper_format_free(file);
|
||||
furi_record_close(RECORD_STORAGE);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static bool test_write_multikey(const char* file_name) {
|
||||
Storage* storage = furi_record_open(RECORD_STORAGE);
|
||||
bool result = false;
|
||||
FlipperFormat* file = flipper_format_file_alloc(storage);
|
||||
|
||||
do {
|
||||
if(!flipper_format_file_open_always(file, file_name)) break;
|
||||
if(!flipper_format_write_header_cstr(file, test_filetype, test_version)) break;
|
||||
|
||||
bool error = false;
|
||||
for(uint8_t index = 0; index < 100; index++) {
|
||||
if(!flipper_format_write_hex(file, test_hex_key, &index, 1)) {
|
||||
error = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(error) break;
|
||||
|
||||
result = true;
|
||||
} while(false);
|
||||
|
||||
flipper_format_free(file);
|
||||
furi_record_close(RECORD_STORAGE);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static bool test_read_multikey(const char* file_name) {
|
||||
Storage* storage = furi_record_open(RECORD_STORAGE);
|
||||
bool result = false;
|
||||
FlipperFormat* file = flipper_format_file_alloc(storage);
|
||||
|
||||
string_t string_value;
|
||||
string_init(string_value);
|
||||
uint32_t uint32_value;
|
||||
|
||||
do {
|
||||
if(!flipper_format_file_open_existing(file, file_name)) break;
|
||||
if(!flipper_format_read_header(file, string_value, &uint32_value)) break;
|
||||
if(string_cmp_str(string_value, test_filetype) != 0) break;
|
||||
if(uint32_value != test_version) break;
|
||||
|
||||
bool error = false;
|
||||
uint8_t uint8_value;
|
||||
for(uint8_t index = 0; index < 100; index++) {
|
||||
if(!flipper_format_read_hex(file, test_hex_key, &uint8_value, 1)) {
|
||||
error = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if(uint8_value != index) {
|
||||
error = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(error) break;
|
||||
|
||||
result = true;
|
||||
} while(false);
|
||||
|
||||
string_clear(string_value);
|
||||
|
||||
flipper_format_free(file);
|
||||
furi_record_close(RECORD_STORAGE);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
MU_TEST(flipper_format_write_test) {
|
||||
mu_assert(storage_write_string(test_file_linux, test_data_nix), "Write test error [Linux]");
|
||||
mu_assert(
|
||||
storage_write_string(test_file_windows, test_data_win), "Write test error [Windows]");
|
||||
mu_assert(test_write(test_file_flipper), "Write test error [Flipper]");
|
||||
}
|
||||
|
||||
MU_TEST(flipper_format_read_test) {
|
||||
mu_assert(test_read(test_file_linux), "Read test error [Linux]");
|
||||
mu_assert(test_read(test_file_windows), "Read test error [Windows]");
|
||||
mu_assert(test_read(test_file_flipper), "Read test error [Flipper]");
|
||||
}
|
||||
|
||||
MU_TEST(flipper_format_delete_test) {
|
||||
mu_assert(test_delete_last_key(test_file_linux), "Cannot delete key [Linux]");
|
||||
mu_assert(test_delete_last_key(test_file_windows), "Cannot delete key [Windows]");
|
||||
mu_assert(test_delete_last_key(test_file_flipper), "Cannot delete key [Flipper]");
|
||||
}
|
||||
|
||||
MU_TEST(flipper_format_delete_result_test) {
|
||||
mu_assert(!test_read(test_file_linux), "Key deleted incorrectly [Linux]");
|
||||
mu_assert(!test_read(test_file_windows), "Key deleted incorrectly [Windows]");
|
||||
mu_assert(!test_read(test_file_flipper), "Key deleted incorrectly [Flipper]");
|
||||
}
|
||||
|
||||
MU_TEST(flipper_format_append_test) {
|
||||
mu_assert(test_append_key(test_file_linux), "Cannot append data [Linux]");
|
||||
mu_assert(test_append_key(test_file_windows), "Cannot append data [Windows]");
|
||||
mu_assert(test_append_key(test_file_flipper), "Cannot append data [Flipper]");
|
||||
}
|
||||
|
||||
MU_TEST(flipper_format_append_result_test) {
|
||||
mu_assert(test_read(test_file_linux), "Data appended incorrectly [Linux]");
|
||||
mu_assert(test_read(test_file_windows), "Data appended incorrectly [Windows]");
|
||||
mu_assert(test_read(test_file_flipper), "Data appended incorrectly [Flipper]");
|
||||
}
|
||||
|
||||
MU_TEST(flipper_format_update_1_test) {
|
||||
mu_assert(test_update(test_file_linux), "Cannot update data #1 [Linux]");
|
||||
mu_assert(test_update(test_file_windows), "Cannot update data #1 [Windows]");
|
||||
mu_assert(test_update(test_file_flipper), "Cannot update data #1 [Flipper]");
|
||||
}
|
||||
|
||||
MU_TEST(flipper_format_update_1_result_test) {
|
||||
mu_assert(test_read_updated(test_file_linux), "Data #1 updated incorrectly [Linux]");
|
||||
mu_assert(test_read_updated(test_file_windows), "Data #1 updated incorrectly [Windows]");
|
||||
mu_assert(test_read_updated(test_file_flipper), "Data #1 updated incorrectly [Flipper]");
|
||||
}
|
||||
|
||||
MU_TEST(flipper_format_update_2_test) {
|
||||
mu_assert(test_update_backward(test_file_linux), "Cannot update data #2 [Linux]");
|
||||
mu_assert(test_update_backward(test_file_windows), "Cannot update data #2 [Windows]");
|
||||
mu_assert(test_update_backward(test_file_flipper), "Cannot update data #2 [Flipper]");
|
||||
}
|
||||
|
||||
MU_TEST(flipper_format_update_2_result_test) {
|
||||
mu_assert(test_read(test_file_linux), "Data #2 updated incorrectly [Linux]");
|
||||
mu_assert(test_read(test_file_windows), "Data #2 updated incorrectly [Windows]");
|
||||
mu_assert(test_read(test_file_flipper), "Data #2 updated incorrectly [Flipper]");
|
||||
}
|
||||
|
||||
MU_TEST(flipper_format_multikey_test) {
|
||||
mu_assert(test_write_multikey(TEST_DIR "ff_multiline.test"), "Multikey write test error");
|
||||
mu_assert(test_read_multikey(TEST_DIR "ff_multiline.test"), "Multikey read test error");
|
||||
}
|
||||
|
||||
MU_TEST_SUITE(flipper_format) {
|
||||
tests_setup();
|
||||
MU_RUN_TEST(flipper_format_write_test);
|
||||
MU_RUN_TEST(flipper_format_read_test);
|
||||
MU_RUN_TEST(flipper_format_delete_test);
|
||||
MU_RUN_TEST(flipper_format_delete_result_test);
|
||||
MU_RUN_TEST(flipper_format_append_test);
|
||||
MU_RUN_TEST(flipper_format_append_result_test);
|
||||
MU_RUN_TEST(flipper_format_update_1_test);
|
||||
MU_RUN_TEST(flipper_format_update_1_result_test);
|
||||
MU_RUN_TEST(flipper_format_update_2_test);
|
||||
MU_RUN_TEST(flipper_format_update_2_result_test);
|
||||
MU_RUN_TEST(flipper_format_multikey_test);
|
||||
tests_teardown();
|
||||
}
|
||||
|
||||
int run_minunit_test_flipper_format() {
|
||||
MU_RUN_SUITE(flipper_format);
|
||||
return MU_EXIT_CODE;
|
||||
}
|
100
applications/debug/unit_tests/furi/furi_memmgr_test.c
Normal file
100
applications/debug/unit_tests/furi/furi_memmgr_test.c
Normal file
@@ -0,0 +1,100 @@
|
||||
#include "../minunit.h"
|
||||
#include <stdlib.h>
|
||||
#include <string.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 managment 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 extact, 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
|
||||
|
||||
// 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();
|
||||
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
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
// 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);
|
||||
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;
|
||||
}
|
||||
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);
|
||||
}
|
45
applications/debug/unit_tests/furi/furi_pubsub_test.c
Normal file
45
applications/debug/unit_tests/furi/furi_pubsub_test.c
Normal file
@@ -0,0 +1,45 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <furi.h>
|
||||
#include "../minunit.h"
|
||||
|
||||
const uint32_t context_value = 0xdeadbeef;
|
||||
const uint32_t notify_value_0 = 0x12345678;
|
||||
const uint32_t notify_value_1 = 0x11223344;
|
||||
|
||||
uint32_t pubsub_value = 0;
|
||||
uint32_t pubsub_context_value = 0;
|
||||
|
||||
void test_pubsub_handler(const void* arg, void* ctx) {
|
||||
pubsub_value = *(uint32_t*)arg;
|
||||
pubsub_context_value = *(uint32_t*)ctx;
|
||||
}
|
||||
|
||||
void test_furi_pubsub() {
|
||||
FuriPubSub* test_pubsub = NULL;
|
||||
FuriPubSubSubscription* test_pubsub_subscription = NULL;
|
||||
|
||||
// init pubsub case
|
||||
test_pubsub = furi_pubsub_alloc();
|
||||
mu_assert_pointers_not_eq(test_pubsub, NULL);
|
||||
|
||||
// subscribe pubsub case
|
||||
test_pubsub_subscription =
|
||||
furi_pubsub_subscribe(test_pubsub, test_pubsub_handler, (void*)&context_value);
|
||||
mu_assert_pointers_not_eq(test_pubsub_subscription, NULL);
|
||||
|
||||
/// notify pubsub case
|
||||
furi_pubsub_publish(test_pubsub, (void*)¬ify_value_0);
|
||||
mu_assert_int_eq(pubsub_value, notify_value_0);
|
||||
mu_assert_int_eq(pubsub_context_value, context_value);
|
||||
|
||||
// unsubscribe pubsub case
|
||||
furi_pubsub_unsubscribe(test_pubsub, test_pubsub_subscription);
|
||||
|
||||
/// notify unsubscribed pubsub case
|
||||
furi_pubsub_publish(test_pubsub, (void*)¬ify_value_1);
|
||||
mu_assert_int_not_eq(pubsub_value, notify_value_1);
|
||||
|
||||
// delete pubsub case
|
||||
furi_pubsub_free(test_pubsub);
|
||||
}
|
20
applications/debug/unit_tests/furi/furi_record_test.c
Normal file
20
applications/debug/unit_tests/furi/furi_record_test.c
Normal file
@@ -0,0 +1,20 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <furi.h>
|
||||
#include "../minunit.h"
|
||||
|
||||
void test_furi_create_open() {
|
||||
// 1. Create record
|
||||
uint8_t test_data = 0;
|
||||
furi_record_create("test/holding", (void*)&test_data);
|
||||
|
||||
// 2. Open it
|
||||
void* record = furi_record_open("test/holding");
|
||||
mu_assert_pointers_eq(record, &test_data);
|
||||
|
||||
// 3. Close it
|
||||
furi_record_close("test/holding");
|
||||
|
||||
// 4. Clean up
|
||||
furi_record_destroy("test/holding");
|
||||
}
|
63
applications/debug/unit_tests/furi/furi_test.c
Normal file
63
applications/debug/unit_tests/furi/furi_test.c
Normal file
@@ -0,0 +1,63 @@
|
||||
#include <stdio.h>
|
||||
#include <furi.h>
|
||||
#include <furi_hal.h>
|
||||
#include "../minunit.h"
|
||||
|
||||
// v2 tests
|
||||
void test_furi_create_open();
|
||||
void test_furi_valuemutex();
|
||||
void test_furi_concurrent_access();
|
||||
void test_furi_pubsub();
|
||||
|
||||
void test_furi_memmgr();
|
||||
|
||||
static int foo = 0;
|
||||
|
||||
void test_setup(void) {
|
||||
foo = 7;
|
||||
}
|
||||
|
||||
void test_teardown(void) {
|
||||
/* Nothing */
|
||||
}
|
||||
|
||||
MU_TEST(test_check) {
|
||||
mu_check(foo != 6);
|
||||
}
|
||||
|
||||
// v2 tests
|
||||
MU_TEST(mu_test_furi_create_open) {
|
||||
test_furi_create_open();
|
||||
}
|
||||
|
||||
MU_TEST(mu_test_furi_valuemutex) {
|
||||
test_furi_valuemutex();
|
||||
}
|
||||
|
||||
MU_TEST(mu_test_furi_pubsub) {
|
||||
test_furi_pubsub();
|
||||
}
|
||||
|
||||
MU_TEST(mu_test_furi_memmgr) {
|
||||
// this test is not accurate, but gives a basic understanding
|
||||
// that memory management is working fine
|
||||
test_furi_memmgr();
|
||||
}
|
||||
|
||||
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_valuemutex);
|
||||
MU_RUN_TEST(mu_test_furi_pubsub);
|
||||
MU_RUN_TEST(mu_test_furi_memmgr);
|
||||
}
|
||||
|
||||
int run_minunit_test_furi() {
|
||||
MU_RUN_SUITE(test_suite);
|
||||
|
||||
return MU_EXIT_CODE;
|
||||
}
|
41
applications/debug/unit_tests/furi/furi_valuemutex_test.c
Normal file
41
applications/debug/unit_tests/furi/furi_valuemutex_test.c
Normal file
@@ -0,0 +1,41 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <furi.h>
|
||||
|
||||
#include "../minunit.h"
|
||||
|
||||
void test_furi_valuemutex() {
|
||||
const int init_value = 0xdeadbeef;
|
||||
const int changed_value = 0x12345678;
|
||||
|
||||
int value = init_value;
|
||||
bool result;
|
||||
ValueMutex valuemutex;
|
||||
|
||||
// init mutex case
|
||||
result = init_mutex(&valuemutex, &value, sizeof(value));
|
||||
mu_assert(result, "init mutex failed");
|
||||
|
||||
// acquire mutex case
|
||||
int* value_pointer = acquire_mutex(&valuemutex, 100);
|
||||
mu_assert_pointers_eq(value_pointer, &value);
|
||||
|
||||
// second acquire mutex case
|
||||
int* value_pointer_second = acquire_mutex(&valuemutex, 100);
|
||||
mu_assert_pointers_eq(value_pointer_second, NULL);
|
||||
|
||||
// change value case
|
||||
*value_pointer = changed_value;
|
||||
mu_assert_int_eq(value, changed_value);
|
||||
|
||||
// release mutex case
|
||||
result = release_mutex(&valuemutex, &value);
|
||||
mu_assert(result, "release mutex failed");
|
||||
|
||||
// TODO
|
||||
//acquire mutex blocking case
|
||||
//write mutex blocking case
|
||||
//read mutex blocking case
|
||||
|
||||
mu_check(delete_mutex(&valuemutex));
|
||||
}
|
521
applications/debug/unit_tests/infrared/infrared_test.c
Normal file
521
applications/debug/unit_tests/infrared/infrared_test.c
Normal file
@@ -0,0 +1,521 @@
|
||||
#include <furi.h>
|
||||
#include <flipper_format.h>
|
||||
#include <infrared.h>
|
||||
#include <common/infrared_common_i.h>
|
||||
#include "../minunit.h"
|
||||
|
||||
#define IR_TEST_FILES_DIR EXT_PATH("unit_tests/infrared/")
|
||||
#define IR_TEST_FILE_PREFIX "test_"
|
||||
#define IR_TEST_FILE_SUFFIX ".irtest"
|
||||
|
||||
typedef struct {
|
||||
InfraredDecoderHandler* decoder_handler;
|
||||
InfraredEncoderHandler* encoder_handler;
|
||||
string_t file_path;
|
||||
FlipperFormat* ff;
|
||||
} InfraredTest;
|
||||
|
||||
static InfraredTest* test;
|
||||
|
||||
static void infrared_test_alloc() {
|
||||
Storage* storage = furi_record_open(RECORD_STORAGE);
|
||||
test = malloc(sizeof(InfraredTest));
|
||||
test->decoder_handler = infrared_alloc_decoder();
|
||||
test->encoder_handler = infrared_alloc_encoder();
|
||||
test->ff = flipper_format_buffered_file_alloc(storage);
|
||||
string_init(test->file_path);
|
||||
}
|
||||
|
||||
static void infrared_test_free() {
|
||||
furi_assert(test);
|
||||
infrared_free_decoder(test->decoder_handler);
|
||||
infrared_free_encoder(test->encoder_handler);
|
||||
flipper_format_free(test->ff);
|
||||
string_clear(test->file_path);
|
||||
furi_record_close(RECORD_STORAGE);
|
||||
free(test);
|
||||
test = NULL;
|
||||
}
|
||||
|
||||
static bool infrared_test_prepare_file(const char* protocol_name) {
|
||||
string_t file_type;
|
||||
string_init(file_type);
|
||||
bool success = false;
|
||||
|
||||
string_printf(
|
||||
test->file_path,
|
||||
"%s%s%s%s",
|
||||
IR_TEST_FILES_DIR,
|
||||
IR_TEST_FILE_PREFIX,
|
||||
protocol_name,
|
||||
IR_TEST_FILE_SUFFIX);
|
||||
|
||||
do {
|
||||
uint32_t format_version;
|
||||
if(!flipper_format_buffered_file_open_existing(test->ff, string_get_cstr(test->file_path)))
|
||||
break;
|
||||
if(!flipper_format_read_header(test->ff, file_type, &format_version)) break;
|
||||
if(string_cmp_str(file_type, "IR tests file") || format_version != 1) break;
|
||||
success = true;
|
||||
} while(false);
|
||||
|
||||
string_clear(file_type);
|
||||
return success;
|
||||
}
|
||||
|
||||
static bool infrared_test_load_raw_signal(
|
||||
FlipperFormat* ff,
|
||||
const char* signal_name,
|
||||
uint32_t** timings,
|
||||
uint32_t* timings_count) {
|
||||
string_t buf;
|
||||
string_init(buf);
|
||||
bool success = false;
|
||||
|
||||
do {
|
||||
bool is_name_found = false;
|
||||
for(; !is_name_found && flipper_format_read_string(ff, "name", buf);
|
||||
is_name_found = !string_cmp_str(buf, signal_name))
|
||||
;
|
||||
|
||||
if(!is_name_found) break;
|
||||
if(!flipper_format_read_string(ff, "type", buf) || string_cmp_str(buf, "raw")) break;
|
||||
if(!flipper_format_get_value_count(ff, "data", timings_count)) break;
|
||||
if(!*timings_count) break;
|
||||
|
||||
*timings = malloc(*timings_count * sizeof(uint32_t*));
|
||||
if(!flipper_format_read_uint32(ff, "data", *timings, *timings_count)) {
|
||||
free(*timings);
|
||||
break;
|
||||
}
|
||||
success = true;
|
||||
} while(false);
|
||||
|
||||
string_clear(buf);
|
||||
return success;
|
||||
}
|
||||
|
||||
static bool infrared_test_read_message(FlipperFormat* ff, InfraredMessage* message) {
|
||||
string_t buf;
|
||||
string_init(buf);
|
||||
bool success = false;
|
||||
|
||||
do {
|
||||
if(!flipper_format_read_string(ff, "protocol", buf)) break;
|
||||
message->protocol = infrared_get_protocol_by_name(string_get_cstr(buf));
|
||||
if(!infrared_is_protocol_valid(message->protocol)) break;
|
||||
if(!flipper_format_read_hex(ff, "address", (uint8_t*)&message->address, sizeof(uint32_t)))
|
||||
break;
|
||||
if(!flipper_format_read_hex(ff, "command", (uint8_t*)&message->command, sizeof(uint32_t)))
|
||||
break;
|
||||
if(!flipper_format_read_bool(ff, "repeat", &message->repeat, 1)) break;
|
||||
success = true;
|
||||
} while(false);
|
||||
|
||||
string_clear(buf);
|
||||
return success;
|
||||
}
|
||||
|
||||
static bool infrared_test_load_messages(
|
||||
FlipperFormat* ff,
|
||||
const char* signal_name,
|
||||
InfraredMessage** messages,
|
||||
uint32_t* messages_count) {
|
||||
string_t buf;
|
||||
string_init(buf);
|
||||
bool success = false;
|
||||
|
||||
do {
|
||||
bool is_name_found = false;
|
||||
for(; !is_name_found && flipper_format_read_string(ff, "name", buf);
|
||||
is_name_found = !string_cmp_str(buf, signal_name))
|
||||
;
|
||||
|
||||
if(!is_name_found) break;
|
||||
if(!flipper_format_read_string(ff, "type", buf) || string_cmp_str(buf, "parsed_array"))
|
||||
break;
|
||||
if(!flipper_format_read_uint32(ff, "count", messages_count, 1)) break;
|
||||
if(!*messages_count) break;
|
||||
|
||||
*messages = malloc(*messages_count * sizeof(InfraredMessage));
|
||||
uint32_t i;
|
||||
for(i = 0; i < *messages_count; ++i) {
|
||||
if(!infrared_test_read_message(ff, (*messages) + i)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(*messages_count != i) {
|
||||
free(*messages);
|
||||
break;
|
||||
}
|
||||
success = true;
|
||||
} while(false);
|
||||
|
||||
string_clear(buf);
|
||||
return success;
|
||||
}
|
||||
|
||||
static void infrared_test_compare_message_results(
|
||||
const InfraredMessage* message_decoded,
|
||||
const InfraredMessage* message_expected) {
|
||||
mu_check(message_decoded->protocol == message_expected->protocol);
|
||||
mu_check(message_decoded->command == message_expected->command);
|
||||
mu_check(message_decoded->address == message_expected->address);
|
||||
if((message_expected->protocol == InfraredProtocolSIRC) ||
|
||||
(message_expected->protocol == InfraredProtocolSIRC15) ||
|
||||
(message_expected->protocol == InfraredProtocolSIRC20)) {
|
||||
mu_check(message_decoded->repeat == false);
|
||||
} else {
|
||||
mu_check(message_decoded->repeat == message_expected->repeat);
|
||||
}
|
||||
}
|
||||
|
||||
/* Encodes signal and merges same levels (high+high, low+low) */
|
||||
static void infrared_test_run_encoder_fill_array(
|
||||
InfraredEncoderHandler* handler,
|
||||
uint32_t* timings,
|
||||
uint32_t* timings_len,
|
||||
bool* start_level) {
|
||||
uint32_t duration = 0;
|
||||
bool level = false;
|
||||
bool level_read;
|
||||
InfraredStatus status = InfraredStatusError;
|
||||
size_t i = 0;
|
||||
bool first = true;
|
||||
|
||||
while(1) {
|
||||
status = infrared_encode(handler, &duration, &level_read);
|
||||
if(first) {
|
||||
if(start_level) *start_level = level_read;
|
||||
first = false;
|
||||
timings[0] = 0;
|
||||
} else if(level_read != level) {
|
||||
++i;
|
||||
furi_check(i < *timings_len);
|
||||
timings[i] = 0;
|
||||
}
|
||||
level = level_read;
|
||||
timings[i] += duration;
|
||||
|
||||
furi_check((status == InfraredStatusOk) || (status == InfraredStatusDone));
|
||||
if(status == InfraredStatusDone) break;
|
||||
}
|
||||
|
||||
*timings_len = i + 1;
|
||||
}
|
||||
|
||||
// messages in input array for encoder should have one protocol
|
||||
static void infrared_test_run_encoder(InfraredProtocol protocol, uint32_t test_index) {
|
||||
uint32_t* timings;
|
||||
uint32_t timings_count = 200;
|
||||
uint32_t* expected_timings;
|
||||
uint32_t expected_timings_count;
|
||||
InfraredMessage* input_messages;
|
||||
uint32_t input_messages_count;
|
||||
|
||||
string_t buf;
|
||||
string_init(buf);
|
||||
|
||||
const char* protocol_name = infrared_get_protocol_name(protocol);
|
||||
mu_assert(infrared_test_prepare_file(protocol_name), "Failed to prepare test file");
|
||||
|
||||
string_printf(buf, "encoder_input%d", test_index);
|
||||
mu_assert(
|
||||
infrared_test_load_messages(
|
||||
test->ff, string_get_cstr(buf), &input_messages, &input_messages_count),
|
||||
"Failed to load messages from file");
|
||||
|
||||
string_printf(buf, "encoder_expected%d", test_index);
|
||||
mu_assert(
|
||||
infrared_test_load_raw_signal(
|
||||
test->ff, string_get_cstr(buf), &expected_timings, &expected_timings_count),
|
||||
"Failed to load raw signal from file");
|
||||
|
||||
flipper_format_buffered_file_close(test->ff);
|
||||
string_clear(buf);
|
||||
|
||||
uint32_t j = 0;
|
||||
timings = malloc(sizeof(uint32_t) * timings_count);
|
||||
|
||||
for(uint32_t message_counter = 0; message_counter < input_messages_count; ++message_counter) {
|
||||
const InfraredMessage* message = &input_messages[message_counter];
|
||||
if(!message->repeat) {
|
||||
infrared_reset_encoder(test->encoder_handler, message);
|
||||
}
|
||||
|
||||
timings_count = 200;
|
||||
infrared_test_run_encoder_fill_array(test->encoder_handler, timings, &timings_count, NULL);
|
||||
furi_check(timings_count <= 200);
|
||||
|
||||
for(size_t i = 0; i < timings_count; ++i, ++j) {
|
||||
mu_check(MATCH_TIMING(timings[i], expected_timings[j], 120));
|
||||
mu_assert(j < expected_timings_count, "encoded more timings than expected");
|
||||
}
|
||||
}
|
||||
|
||||
free(input_messages);
|
||||
free(expected_timings);
|
||||
free(timings);
|
||||
|
||||
mu_assert(j == expected_timings_count, "encoded less timings than expected");
|
||||
}
|
||||
|
||||
static void infrared_test_run_encoder_decoder(InfraredProtocol protocol, uint32_t test_index) {
|
||||
uint32_t* timings = 0;
|
||||
uint32_t timings_count = 200;
|
||||
InfraredMessage* input_messages;
|
||||
uint32_t input_messages_count;
|
||||
bool level = false;
|
||||
|
||||
string_t buf;
|
||||
string_init(buf);
|
||||
|
||||
timings = malloc(sizeof(uint32_t) * timings_count);
|
||||
|
||||
const char* protocol_name = infrared_get_protocol_name(protocol);
|
||||
mu_assert(infrared_test_prepare_file(protocol_name), "Failed to prepare test file");
|
||||
|
||||
string_printf(buf, "encoder_decoder_input%d", test_index);
|
||||
mu_assert(
|
||||
infrared_test_load_messages(
|
||||
test->ff, string_get_cstr(buf), &input_messages, &input_messages_count),
|
||||
"Failed to load messages from file");
|
||||
|
||||
flipper_format_buffered_file_close(test->ff);
|
||||
string_clear(buf);
|
||||
|
||||
for(uint32_t message_counter = 0; message_counter < input_messages_count; ++message_counter) {
|
||||
const InfraredMessage* message_encoded = &input_messages[message_counter];
|
||||
if(!message_encoded->repeat) {
|
||||
infrared_reset_encoder(test->encoder_handler, message_encoded);
|
||||
}
|
||||
|
||||
timings_count = 200;
|
||||
infrared_test_run_encoder_fill_array(
|
||||
test->encoder_handler, timings, &timings_count, &level);
|
||||
furi_check(timings_count <= 200);
|
||||
|
||||
const InfraredMessage* message_decoded = 0;
|
||||
for(size_t i = 0; i < timings_count; ++i) {
|
||||
message_decoded = infrared_decode(test->decoder_handler, level, timings[i]);
|
||||
if((i == timings_count - 2) && level && message_decoded) {
|
||||
/* In case we end with space timing - message can be decoded at last mark */
|
||||
break;
|
||||
} else if(i < timings_count - 1) {
|
||||
mu_check(!message_decoded);
|
||||
} else {
|
||||
if(!message_decoded) {
|
||||
message_decoded = infrared_check_decoder_ready(test->decoder_handler);
|
||||
}
|
||||
mu_check(message_decoded);
|
||||
}
|
||||
level = !level;
|
||||
}
|
||||
if(message_decoded) {
|
||||
infrared_test_compare_message_results(message_decoded, message_encoded);
|
||||
} else {
|
||||
mu_check(0);
|
||||
}
|
||||
}
|
||||
free(input_messages);
|
||||
free(timings);
|
||||
}
|
||||
|
||||
static void infrared_test_run_decoder(InfraredProtocol protocol, uint32_t test_index) {
|
||||
uint32_t* timings;
|
||||
uint32_t timings_count;
|
||||
InfraredMessage* messages;
|
||||
uint32_t messages_count;
|
||||
|
||||
string_t buf;
|
||||
string_init(buf);
|
||||
|
||||
mu_assert(
|
||||
infrared_test_prepare_file(infrared_get_protocol_name(protocol)),
|
||||
"Failed to prepare test file");
|
||||
|
||||
string_printf(buf, "decoder_input%d", test_index);
|
||||
mu_assert(
|
||||
infrared_test_load_raw_signal(test->ff, string_get_cstr(buf), &timings, &timings_count),
|
||||
"Failed to load raw signal from file");
|
||||
|
||||
string_printf(buf, "decoder_expected%d", test_index);
|
||||
mu_assert(
|
||||
infrared_test_load_messages(test->ff, string_get_cstr(buf), &messages, &messages_count),
|
||||
"Failed to load messages from file");
|
||||
|
||||
flipper_format_buffered_file_close(test->ff);
|
||||
string_clear(buf);
|
||||
|
||||
InfraredMessage message_decoded_check_local;
|
||||
bool level = 0;
|
||||
uint32_t message_counter = 0;
|
||||
const InfraredMessage* message_decoded = 0;
|
||||
|
||||
for(uint32_t i = 0; i < timings_count; ++i) {
|
||||
const InfraredMessage* message_decoded_check = 0;
|
||||
|
||||
if(timings[i] > INFRARED_RAW_RX_TIMING_DELAY_US) {
|
||||
message_decoded_check = infrared_check_decoder_ready(test->decoder_handler);
|
||||
if(message_decoded_check) {
|
||||
/* infrared_decode() can reset message, but we have to call infrared_decode() to perform real
|
||||
* simulation: infrared_check() by timeout, then infrared_decode() when meet edge */
|
||||
message_decoded_check_local = *message_decoded_check;
|
||||
message_decoded_check = &message_decoded_check_local;
|
||||
}
|
||||
}
|
||||
|
||||
message_decoded = infrared_decode(test->decoder_handler, level, timings[i]);
|
||||
|
||||
if(message_decoded_check || message_decoded) {
|
||||
mu_assert(
|
||||
!(message_decoded_check && message_decoded),
|
||||
"both messages decoded: check_ready() and infrared_decode()");
|
||||
|
||||
if(message_decoded_check) {
|
||||
message_decoded = message_decoded_check;
|
||||
}
|
||||
|
||||
mu_assert(message_counter < messages_count, "decoded more than expected");
|
||||
infrared_test_compare_message_results(message_decoded, &messages[message_counter]);
|
||||
|
||||
++message_counter;
|
||||
}
|
||||
level = !level;
|
||||
}
|
||||
|
||||
message_decoded = infrared_check_decoder_ready(test->decoder_handler);
|
||||
if(message_decoded) {
|
||||
infrared_test_compare_message_results(message_decoded, &messages[message_counter]);
|
||||
++message_counter;
|
||||
}
|
||||
|
||||
free(timings);
|
||||
free(messages);
|
||||
|
||||
mu_assert(message_counter == messages_count, "decoded less than expected");
|
||||
}
|
||||
|
||||
MU_TEST(infrared_test_decoder_samsung32) {
|
||||
infrared_test_run_decoder(InfraredProtocolSamsung32, 1);
|
||||
}
|
||||
|
||||
MU_TEST(infrared_test_decoder_mixed) {
|
||||
infrared_test_run_decoder(InfraredProtocolRC5, 2);
|
||||
infrared_test_run_decoder(InfraredProtocolSIRC, 1);
|
||||
infrared_test_run_decoder(InfraredProtocolNECext, 1);
|
||||
infrared_test_run_decoder(InfraredProtocolRC6, 2);
|
||||
infrared_test_run_decoder(InfraredProtocolSamsung32, 1);
|
||||
infrared_test_run_decoder(InfraredProtocolRC6, 1);
|
||||
infrared_test_run_decoder(InfraredProtocolSamsung32, 1);
|
||||
infrared_test_run_decoder(InfraredProtocolRC5, 1);
|
||||
infrared_test_run_decoder(InfraredProtocolSIRC, 2);
|
||||
infrared_test_run_decoder(InfraredProtocolNECext, 1);
|
||||
infrared_test_run_decoder(InfraredProtocolSIRC, 4);
|
||||
infrared_test_run_decoder(InfraredProtocolNEC, 2);
|
||||
infrared_test_run_decoder(InfraredProtocolRC6, 1);
|
||||
infrared_test_run_decoder(InfraredProtocolNECext, 1);
|
||||
infrared_test_run_decoder(InfraredProtocolSIRC, 5);
|
||||
infrared_test_run_decoder(InfraredProtocolNEC, 3);
|
||||
infrared_test_run_decoder(InfraredProtocolRC5, 5);
|
||||
infrared_test_run_decoder(InfraredProtocolSamsung32, 1);
|
||||
infrared_test_run_decoder(InfraredProtocolSIRC, 3);
|
||||
}
|
||||
|
||||
MU_TEST(infrared_test_decoder_nec) {
|
||||
infrared_test_run_decoder(InfraredProtocolNEC, 1);
|
||||
infrared_test_run_decoder(InfraredProtocolNEC, 2);
|
||||
infrared_test_run_decoder(InfraredProtocolNEC, 3);
|
||||
}
|
||||
|
||||
MU_TEST(infrared_test_decoder_unexpected_end_in_sequence) {
|
||||
infrared_test_run_decoder(InfraredProtocolNEC, 1);
|
||||
infrared_test_run_decoder(InfraredProtocolNEC, 1);
|
||||
infrared_test_run_decoder(InfraredProtocolNEC, 2);
|
||||
infrared_test_run_decoder(InfraredProtocolNEC, 2);
|
||||
}
|
||||
|
||||
MU_TEST(infrared_test_decoder_necext1) {
|
||||
infrared_test_run_decoder(InfraredProtocolNECext, 1);
|
||||
infrared_test_run_decoder(InfraredProtocolNECext, 1);
|
||||
}
|
||||
|
||||
MU_TEST(infrared_test_decoder_long_packets_with_nec_start) {
|
||||
infrared_test_run_decoder(InfraredProtocolNEC42ext, 1);
|
||||
infrared_test_run_decoder(InfraredProtocolNEC42ext, 2);
|
||||
}
|
||||
|
||||
MU_TEST(infrared_test_encoder_sirc) {
|
||||
infrared_test_run_encoder(InfraredProtocolSIRC, 1);
|
||||
infrared_test_run_encoder(InfraredProtocolSIRC, 2);
|
||||
}
|
||||
|
||||
MU_TEST(infrared_test_decoder_sirc) {
|
||||
infrared_test_run_decoder(InfraredProtocolSIRC, 3);
|
||||
infrared_test_run_decoder(InfraredProtocolSIRC, 1);
|
||||
infrared_test_run_decoder(InfraredProtocolSIRC, 2);
|
||||
infrared_test_run_decoder(InfraredProtocolSIRC, 4);
|
||||
infrared_test_run_decoder(InfraredProtocolSIRC, 5);
|
||||
}
|
||||
|
||||
MU_TEST(infrared_test_decoder_rc5) {
|
||||
infrared_test_run_decoder(InfraredProtocolRC5X, 1);
|
||||
infrared_test_run_decoder(InfraredProtocolRC5, 1);
|
||||
infrared_test_run_decoder(InfraredProtocolRC5, 2);
|
||||
infrared_test_run_decoder(InfraredProtocolRC5, 3);
|
||||
infrared_test_run_decoder(InfraredProtocolRC5, 4);
|
||||
infrared_test_run_decoder(InfraredProtocolRC5, 5);
|
||||
infrared_test_run_decoder(InfraredProtocolRC5, 6);
|
||||
infrared_test_run_decoder(InfraredProtocolRC5, 7);
|
||||
}
|
||||
|
||||
MU_TEST(infrared_test_encoder_rc5x) {
|
||||
infrared_test_run_encoder(InfraredProtocolRC5X, 1);
|
||||
}
|
||||
|
||||
MU_TEST(infrared_test_encoder_rc5) {
|
||||
infrared_test_run_encoder(InfraredProtocolRC5, 1);
|
||||
}
|
||||
|
||||
MU_TEST(infrared_test_decoder_rc6) {
|
||||
infrared_test_run_decoder(InfraredProtocolRC6, 1);
|
||||
}
|
||||
|
||||
MU_TEST(infrared_test_encoder_rc6) {
|
||||
infrared_test_run_encoder(InfraredProtocolRC6, 1);
|
||||
}
|
||||
|
||||
MU_TEST(infrared_test_encoder_decoder_all) {
|
||||
infrared_test_run_encoder_decoder(InfraredProtocolNEC, 1);
|
||||
infrared_test_run_encoder_decoder(InfraredProtocolNECext, 1);
|
||||
infrared_test_run_encoder_decoder(InfraredProtocolNEC42, 1);
|
||||
infrared_test_run_encoder_decoder(InfraredProtocolNEC42ext, 1);
|
||||
infrared_test_run_encoder_decoder(InfraredProtocolSamsung32, 1);
|
||||
infrared_test_run_encoder_decoder(InfraredProtocolRC6, 1);
|
||||
infrared_test_run_encoder_decoder(InfraredProtocolRC5, 1);
|
||||
infrared_test_run_encoder_decoder(InfraredProtocolSIRC, 1);
|
||||
}
|
||||
|
||||
MU_TEST_SUITE(infrared_test) {
|
||||
MU_SUITE_CONFIGURE(&infrared_test_alloc, &infrared_test_free);
|
||||
|
||||
MU_RUN_TEST(infrared_test_encoder_sirc);
|
||||
MU_RUN_TEST(infrared_test_decoder_sirc);
|
||||
MU_RUN_TEST(infrared_test_encoder_rc5x);
|
||||
MU_RUN_TEST(infrared_test_encoder_rc5);
|
||||
MU_RUN_TEST(infrared_test_decoder_rc5);
|
||||
MU_RUN_TEST(infrared_test_decoder_rc6);
|
||||
MU_RUN_TEST(infrared_test_encoder_rc6);
|
||||
MU_RUN_TEST(infrared_test_decoder_unexpected_end_in_sequence);
|
||||
MU_RUN_TEST(infrared_test_decoder_long_packets_with_nec_start);
|
||||
MU_RUN_TEST(infrared_test_decoder_nec);
|
||||
MU_RUN_TEST(infrared_test_decoder_samsung32);
|
||||
MU_RUN_TEST(infrared_test_decoder_necext1);
|
||||
MU_RUN_TEST(infrared_test_decoder_mixed);
|
||||
MU_RUN_TEST(infrared_test_encoder_decoder_all);
|
||||
}
|
||||
|
||||
int run_minunit_test_infrared() {
|
||||
MU_RUN_SUITE(infrared_test);
|
||||
return MU_EXIT_CODE;
|
||||
}
|
473
applications/debug/unit_tests/lfrfid/bit_lib_test.c
Normal file
473
applications/debug/unit_tests/lfrfid/bit_lib_test.c
Normal file
@@ -0,0 +1,473 @@
|
||||
#include <furi.h>
|
||||
#include "../minunit.h"
|
||||
#include <lfrfid/tools/bit_lib.h>
|
||||
|
||||
MU_TEST(test_bit_lib_increment_index) {
|
||||
uint32_t index = 0;
|
||||
|
||||
// test increment
|
||||
for(uint32_t i = 0; i < 31; ++i) {
|
||||
bit_lib_increment_index(index, 32);
|
||||
mu_assert_int_eq(i + 1, index);
|
||||
}
|
||||
|
||||
// test wrap around
|
||||
for(uint32_t i = 0; i < 512; ++i) {
|
||||
bit_lib_increment_index(index, 32);
|
||||
mu_assert_int_less_than(32, index);
|
||||
}
|
||||
}
|
||||
|
||||
MU_TEST(test_bit_lib_is_set) {
|
||||
uint32_t value = 0x0000FFFF;
|
||||
|
||||
for(uint32_t i = 0; i < 16; ++i) {
|
||||
mu_check(bit_lib_bit_is_set(value, i));
|
||||
mu_check(!bit_lib_bit_is_not_set(value, i));
|
||||
}
|
||||
|
||||
for(uint32_t i = 16; i < 32; ++i) {
|
||||
mu_check(!bit_lib_bit_is_set(value, i));
|
||||
mu_check(bit_lib_bit_is_not_set(value, i));
|
||||
}
|
||||
}
|
||||
|
||||
MU_TEST(test_bit_lib_push) {
|
||||
#define TEST_BIT_LIB_PUSH_DATA_SIZE 4
|
||||
uint8_t data[TEST_BIT_LIB_PUSH_DATA_SIZE] = {0};
|
||||
uint8_t expected_data_1[TEST_BIT_LIB_PUSH_DATA_SIZE] = {0x00, 0x00, 0x0F, 0xFF};
|
||||
uint8_t expected_data_2[TEST_BIT_LIB_PUSH_DATA_SIZE] = {0x00, 0xFF, 0xF0, 0x00};
|
||||
uint8_t expected_data_3[TEST_BIT_LIB_PUSH_DATA_SIZE] = {0xFF, 0x00, 0x00, 0xFF};
|
||||
uint8_t expected_data_4[TEST_BIT_LIB_PUSH_DATA_SIZE] = {0xFF, 0xFF, 0xFF, 0xFF};
|
||||
uint8_t expected_data_5[TEST_BIT_LIB_PUSH_DATA_SIZE] = {0x00, 0x00, 0x00, 0x00};
|
||||
uint8_t expected_data_6[TEST_BIT_LIB_PUSH_DATA_SIZE] = {0xCC, 0xCC, 0xCC, 0xCC};
|
||||
|
||||
for(uint32_t i = 0; i < 12; ++i) {
|
||||
bit_lib_push_bit(data, TEST_BIT_LIB_PUSH_DATA_SIZE, true);
|
||||
}
|
||||
mu_assert_mem_eq(expected_data_1, data, TEST_BIT_LIB_PUSH_DATA_SIZE);
|
||||
|
||||
for(uint32_t i = 0; i < 12; ++i) {
|
||||
bit_lib_push_bit(data, TEST_BIT_LIB_PUSH_DATA_SIZE, false);
|
||||
}
|
||||
mu_assert_mem_eq(expected_data_2, data, TEST_BIT_LIB_PUSH_DATA_SIZE);
|
||||
|
||||
for(uint32_t i = 0; i < 4; ++i) {
|
||||
bit_lib_push_bit(data, TEST_BIT_LIB_PUSH_DATA_SIZE, false);
|
||||
}
|
||||
for(uint32_t i = 0; i < 8; ++i) {
|
||||
bit_lib_push_bit(data, TEST_BIT_LIB_PUSH_DATA_SIZE, true);
|
||||
}
|
||||
mu_assert_mem_eq(expected_data_3, data, TEST_BIT_LIB_PUSH_DATA_SIZE);
|
||||
|
||||
for(uint32_t i = 0; i < TEST_BIT_LIB_PUSH_DATA_SIZE * 8; ++i) {
|
||||
bit_lib_push_bit(data, TEST_BIT_LIB_PUSH_DATA_SIZE, true);
|
||||
}
|
||||
mu_assert_mem_eq(expected_data_4, data, TEST_BIT_LIB_PUSH_DATA_SIZE);
|
||||
|
||||
for(uint32_t i = 0; i < TEST_BIT_LIB_PUSH_DATA_SIZE * 8; ++i) {
|
||||
bit_lib_push_bit(data, TEST_BIT_LIB_PUSH_DATA_SIZE, false);
|
||||
}
|
||||
mu_assert_mem_eq(expected_data_5, data, TEST_BIT_LIB_PUSH_DATA_SIZE);
|
||||
|
||||
for(uint32_t i = 0; i < TEST_BIT_LIB_PUSH_DATA_SIZE * 2; ++i) {
|
||||
bit_lib_push_bit(data, TEST_BIT_LIB_PUSH_DATA_SIZE, true);
|
||||
bit_lib_push_bit(data, TEST_BIT_LIB_PUSH_DATA_SIZE, true);
|
||||
bit_lib_push_bit(data, TEST_BIT_LIB_PUSH_DATA_SIZE, false);
|
||||
bit_lib_push_bit(data, TEST_BIT_LIB_PUSH_DATA_SIZE, false);
|
||||
}
|
||||
mu_assert_mem_eq(expected_data_6, data, TEST_BIT_LIB_PUSH_DATA_SIZE);
|
||||
}
|
||||
|
||||
MU_TEST(test_bit_lib_set_bit) {
|
||||
uint8_t value[2] = {0x00, 0xFF};
|
||||
bit_lib_set_bit(value, 15, false);
|
||||
mu_assert_mem_eq(value, ((uint8_t[]){0x00, 0xFE}), 2);
|
||||
bit_lib_set_bit(value, 14, false);
|
||||
mu_assert_mem_eq(value, ((uint8_t[]){0x00, 0xFC}), 2);
|
||||
bit_lib_set_bit(value, 13, false);
|
||||
mu_assert_mem_eq(value, ((uint8_t[]){0x00, 0xF8}), 2);
|
||||
bit_lib_set_bit(value, 12, false);
|
||||
mu_assert_mem_eq(value, ((uint8_t[]){0x00, 0xF0}), 2);
|
||||
bit_lib_set_bit(value, 11, false);
|
||||
mu_assert_mem_eq(value, ((uint8_t[]){0x00, 0xE0}), 2);
|
||||
bit_lib_set_bit(value, 10, false);
|
||||
mu_assert_mem_eq(value, ((uint8_t[]){0x00, 0xC0}), 2);
|
||||
bit_lib_set_bit(value, 9, false);
|
||||
mu_assert_mem_eq(value, ((uint8_t[]){0x00, 0x80}), 2);
|
||||
bit_lib_set_bit(value, 8, false);
|
||||
mu_assert_mem_eq(value, ((uint8_t[]){0x00, 0x00}), 2);
|
||||
|
||||
bit_lib_set_bit(value, 7, true);
|
||||
mu_assert_mem_eq(value, ((uint8_t[]){0x01, 0x00}), 2);
|
||||
bit_lib_set_bit(value, 6, true);
|
||||
mu_assert_mem_eq(value, ((uint8_t[]){0x03, 0x00}), 2);
|
||||
bit_lib_set_bit(value, 5, true);
|
||||
mu_assert_mem_eq(value, ((uint8_t[]){0x07, 0x00}), 2);
|
||||
bit_lib_set_bit(value, 4, true);
|
||||
mu_assert_mem_eq(value, ((uint8_t[]){0x0F, 0x00}), 2);
|
||||
bit_lib_set_bit(value, 3, true);
|
||||
mu_assert_mem_eq(value, ((uint8_t[]){0x1F, 0x00}), 2);
|
||||
bit_lib_set_bit(value, 2, true);
|
||||
mu_assert_mem_eq(value, ((uint8_t[]){0x3F, 0x00}), 2);
|
||||
bit_lib_set_bit(value, 1, true);
|
||||
mu_assert_mem_eq(value, ((uint8_t[]){0x7F, 0x00}), 2);
|
||||
bit_lib_set_bit(value, 0, true);
|
||||
mu_assert_mem_eq(value, ((uint8_t[]){0xFF, 0x00}), 2);
|
||||
}
|
||||
|
||||
MU_TEST(test_bit_lib_set_bits) {
|
||||
uint8_t value[2] = {0b00000000, 0b11111111};
|
||||
// set 4 bits to 0b0100 from 12 index
|
||||
bit_lib_set_bits(value, 12, 0b0100, 4);
|
||||
// [0100]
|
||||
mu_assert_mem_eq(value, ((uint8_t[]){0b00000000, 0b11110100}), 2);
|
||||
|
||||
// set 2 bits to 0b11 from 11 index
|
||||
bit_lib_set_bits(value, 11, 0b11, 2);
|
||||
// [11]
|
||||
mu_assert_mem_eq(value, ((uint8_t[]){0b00000000, 0b11111100}), 2);
|
||||
|
||||
// set 3 bits to 0b111 from 0 index
|
||||
bit_lib_set_bits(value, 0, 0b111, 3);
|
||||
// [111]
|
||||
mu_assert_mem_eq(value, ((uint8_t[]){0b11100000, 0b11111100}), 2);
|
||||
|
||||
// set 8 bits to 0b11111000 from 3 index
|
||||
bit_lib_set_bits(value, 3, 0b11111000, 8);
|
||||
// [11111 000]
|
||||
mu_assert_mem_eq(value, ((uint8_t[]){0b11111111, 0b00011100}), 2);
|
||||
}
|
||||
|
||||
MU_TEST(test_bit_lib_get_bit) {
|
||||
uint8_t value[2] = {0b00000000, 0b11111111};
|
||||
for(uint32_t i = 0; i < 8; ++i) {
|
||||
mu_check(bit_lib_get_bit(value, i) == false);
|
||||
}
|
||||
for(uint32_t i = 8; i < 16; ++i) {
|
||||
mu_check(bit_lib_get_bit(value, i) == true);
|
||||
}
|
||||
}
|
||||
|
||||
MU_TEST(test_bit_lib_get_bits) {
|
||||
uint8_t value[2] = {0b00000000, 0b11111111};
|
||||
mu_assert_int_eq(0b00000000, bit_lib_get_bits(value, 0, 8));
|
||||
mu_assert_int_eq(0b00000001, bit_lib_get_bits(value, 1, 8));
|
||||
mu_assert_int_eq(0b00000011, bit_lib_get_bits(value, 2, 8));
|
||||
mu_assert_int_eq(0b00000111, bit_lib_get_bits(value, 3, 8));
|
||||
mu_assert_int_eq(0b00001111, bit_lib_get_bits(value, 4, 8));
|
||||
mu_assert_int_eq(0b00011111, bit_lib_get_bits(value, 5, 8));
|
||||
mu_assert_int_eq(0b00111111, bit_lib_get_bits(value, 6, 8));
|
||||
mu_assert_int_eq(0b01111111, bit_lib_get_bits(value, 7, 8));
|
||||
mu_assert_int_eq(0b11111111, bit_lib_get_bits(value, 8, 8));
|
||||
}
|
||||
|
||||
MU_TEST(test_bit_lib_get_bits_16) {
|
||||
uint8_t value[2] = {0b00001001, 0b10110001};
|
||||
mu_assert_int_eq(0b0, bit_lib_get_bits_16(value, 0, 1));
|
||||
mu_assert_int_eq(0b00, bit_lib_get_bits_16(value, 0, 2));
|
||||
mu_assert_int_eq(0b000, bit_lib_get_bits_16(value, 0, 3));
|
||||
mu_assert_int_eq(0b0000, bit_lib_get_bits_16(value, 0, 4));
|
||||
mu_assert_int_eq(0b00001, bit_lib_get_bits_16(value, 0, 5));
|
||||
mu_assert_int_eq(0b000010, bit_lib_get_bits_16(value, 0, 6));
|
||||
mu_assert_int_eq(0b0000100, bit_lib_get_bits_16(value, 0, 7));
|
||||
mu_assert_int_eq(0b00001001, bit_lib_get_bits_16(value, 0, 8));
|
||||
mu_assert_int_eq(0b000010011, bit_lib_get_bits_16(value, 0, 9));
|
||||
mu_assert_int_eq(0b0000100110, bit_lib_get_bits_16(value, 0, 10));
|
||||
mu_assert_int_eq(0b00001001101, bit_lib_get_bits_16(value, 0, 11));
|
||||
mu_assert_int_eq(0b000010011011, bit_lib_get_bits_16(value, 0, 12));
|
||||
mu_assert_int_eq(0b0000100110110, bit_lib_get_bits_16(value, 0, 13));
|
||||
mu_assert_int_eq(0b00001001101100, bit_lib_get_bits_16(value, 0, 14));
|
||||
mu_assert_int_eq(0b000010011011000, bit_lib_get_bits_16(value, 0, 15));
|
||||
mu_assert_int_eq(0b0000100110110001, bit_lib_get_bits_16(value, 0, 16));
|
||||
}
|
||||
|
||||
MU_TEST(test_bit_lib_get_bits_32) {
|
||||
uint8_t value[4] = {0b00001001, 0b10110001, 0b10001100, 0b01100010};
|
||||
mu_assert_int_eq(0b0, bit_lib_get_bits_32(value, 0, 1));
|
||||
mu_assert_int_eq(0b00, bit_lib_get_bits_32(value, 0, 2));
|
||||
mu_assert_int_eq(0b000, bit_lib_get_bits_32(value, 0, 3));
|
||||
mu_assert_int_eq(0b0000, bit_lib_get_bits_32(value, 0, 4));
|
||||
mu_assert_int_eq(0b00001, bit_lib_get_bits_32(value, 0, 5));
|
||||
mu_assert_int_eq(0b000010, bit_lib_get_bits_32(value, 0, 6));
|
||||
mu_assert_int_eq(0b0000100, bit_lib_get_bits_32(value, 0, 7));
|
||||
mu_assert_int_eq(0b00001001, bit_lib_get_bits_32(value, 0, 8));
|
||||
mu_assert_int_eq(0b000010011, bit_lib_get_bits_32(value, 0, 9));
|
||||
mu_assert_int_eq(0b0000100110, bit_lib_get_bits_32(value, 0, 10));
|
||||
mu_assert_int_eq(0b00001001101, bit_lib_get_bits_32(value, 0, 11));
|
||||
mu_assert_int_eq(0b000010011011, bit_lib_get_bits_32(value, 0, 12));
|
||||
mu_assert_int_eq(0b0000100110110, bit_lib_get_bits_32(value, 0, 13));
|
||||
mu_assert_int_eq(0b00001001101100, bit_lib_get_bits_32(value, 0, 14));
|
||||
mu_assert_int_eq(0b000010011011000, bit_lib_get_bits_32(value, 0, 15));
|
||||
mu_assert_int_eq(0b0000100110110001, bit_lib_get_bits_32(value, 0, 16));
|
||||
mu_assert_int_eq(0b00001001101100011, bit_lib_get_bits_32(value, 0, 17));
|
||||
mu_assert_int_eq(0b000010011011000110, bit_lib_get_bits_32(value, 0, 18));
|
||||
mu_assert_int_eq(0b0000100110110001100, bit_lib_get_bits_32(value, 0, 19));
|
||||
mu_assert_int_eq(0b00001001101100011000, bit_lib_get_bits_32(value, 0, 20));
|
||||
mu_assert_int_eq(0b000010011011000110001, bit_lib_get_bits_32(value, 0, 21));
|
||||
mu_assert_int_eq(0b0000100110110001100011, bit_lib_get_bits_32(value, 0, 22));
|
||||
mu_assert_int_eq(0b00001001101100011000110, bit_lib_get_bits_32(value, 0, 23));
|
||||
mu_assert_int_eq(0b000010011011000110001100, bit_lib_get_bits_32(value, 0, 24));
|
||||
mu_assert_int_eq(0b0000100110110001100011000, bit_lib_get_bits_32(value, 0, 25));
|
||||
mu_assert_int_eq(0b00001001101100011000110001, bit_lib_get_bits_32(value, 0, 26));
|
||||
mu_assert_int_eq(0b000010011011000110001100011, bit_lib_get_bits_32(value, 0, 27));
|
||||
mu_assert_int_eq(0b0000100110110001100011000110, bit_lib_get_bits_32(value, 0, 28));
|
||||
mu_assert_int_eq(0b00001001101100011000110001100, bit_lib_get_bits_32(value, 0, 29));
|
||||
mu_assert_int_eq(0b000010011011000110001100011000, bit_lib_get_bits_32(value, 0, 30));
|
||||
mu_assert_int_eq(0b0000100110110001100011000110001, bit_lib_get_bits_32(value, 0, 31));
|
||||
mu_assert_int_eq(0b00001001101100011000110001100010, bit_lib_get_bits_32(value, 0, 32));
|
||||
}
|
||||
|
||||
MU_TEST(test_bit_lib_test_parity_u32) {
|
||||
// test even parity
|
||||
mu_assert_int_eq(bit_lib_test_parity_32(0b00000000, BitLibParityEven), 0);
|
||||
mu_assert_int_eq(bit_lib_test_parity_32(0b00000001, BitLibParityEven), 1);
|
||||
mu_assert_int_eq(bit_lib_test_parity_32(0b00000010, BitLibParityEven), 1);
|
||||
mu_assert_int_eq(bit_lib_test_parity_32(0b00000011, BitLibParityEven), 0);
|
||||
mu_assert_int_eq(bit_lib_test_parity_32(0b00000100, BitLibParityEven), 1);
|
||||
mu_assert_int_eq(bit_lib_test_parity_32(0b00000101, BitLibParityEven), 0);
|
||||
mu_assert_int_eq(bit_lib_test_parity_32(0b00000110, BitLibParityEven), 0);
|
||||
mu_assert_int_eq(bit_lib_test_parity_32(0b00000111, BitLibParityEven), 1);
|
||||
mu_assert_int_eq(bit_lib_test_parity_32(0b00001000, BitLibParityEven), 1);
|
||||
mu_assert_int_eq(bit_lib_test_parity_32(0b00001001, BitLibParityEven), 0);
|
||||
mu_assert_int_eq(bit_lib_test_parity_32(0b00001010, BitLibParityEven), 0);
|
||||
mu_assert_int_eq(bit_lib_test_parity_32(0b00001011, BitLibParityEven), 1);
|
||||
mu_assert_int_eq(bit_lib_test_parity_32(0b00001100, BitLibParityEven), 0);
|
||||
mu_assert_int_eq(bit_lib_test_parity_32(0b00001101, BitLibParityEven), 1);
|
||||
mu_assert_int_eq(bit_lib_test_parity_32(0b00001110, BitLibParityEven), 1);
|
||||
mu_assert_int_eq(bit_lib_test_parity_32(0b00001111, BitLibParityEven), 0);
|
||||
mu_assert_int_eq(bit_lib_test_parity_32(0b00010000, BitLibParityEven), 1);
|
||||
|
||||
// test odd parity
|
||||
mu_assert_int_eq(bit_lib_test_parity_32(0b00000000, BitLibParityOdd), 1);
|
||||
mu_assert_int_eq(bit_lib_test_parity_32(0b00000001, BitLibParityOdd), 0);
|
||||
mu_assert_int_eq(bit_lib_test_parity_32(0b00000010, BitLibParityOdd), 0);
|
||||
mu_assert_int_eq(bit_lib_test_parity_32(0b00000011, BitLibParityOdd), 1);
|
||||
mu_assert_int_eq(bit_lib_test_parity_32(0b00000100, BitLibParityOdd), 0);
|
||||
mu_assert_int_eq(bit_lib_test_parity_32(0b00000101, BitLibParityOdd), 1);
|
||||
mu_assert_int_eq(bit_lib_test_parity_32(0b00000110, BitLibParityOdd), 1);
|
||||
mu_assert_int_eq(bit_lib_test_parity_32(0b00000111, BitLibParityOdd), 0);
|
||||
mu_assert_int_eq(bit_lib_test_parity_32(0b00001000, BitLibParityOdd), 0);
|
||||
mu_assert_int_eq(bit_lib_test_parity_32(0b00001001, BitLibParityOdd), 1);
|
||||
mu_assert_int_eq(bit_lib_test_parity_32(0b00001010, BitLibParityOdd), 1);
|
||||
mu_assert_int_eq(bit_lib_test_parity_32(0b00001011, BitLibParityOdd), 0);
|
||||
mu_assert_int_eq(bit_lib_test_parity_32(0b00001100, BitLibParityOdd), 1);
|
||||
mu_assert_int_eq(bit_lib_test_parity_32(0b00001101, BitLibParityOdd), 0);
|
||||
mu_assert_int_eq(bit_lib_test_parity_32(0b00001110, BitLibParityOdd), 0);
|
||||
mu_assert_int_eq(bit_lib_test_parity_32(0b00001111, BitLibParityOdd), 1);
|
||||
mu_assert_int_eq(bit_lib_test_parity_32(0b00010000, BitLibParityOdd), 0);
|
||||
}
|
||||
|
||||
MU_TEST(test_bit_lib_test_parity) {
|
||||
// next data contains valid parity for 1-3 nibble and invalid for 4 nibble
|
||||
uint8_t data_always_0_parity[2] = {0b11101110, 0b11101111};
|
||||
uint8_t data_always_1_parity[2] = {0b00010001, 0b00010000};
|
||||
uint8_t data_always_odd_parity[2] = {0b00000011, 0b11110111};
|
||||
uint8_t data_always_even_parity[2] = {0b00010111, 0b10110011};
|
||||
|
||||
// test alawys 0 parity
|
||||
mu_check(bit_lib_test_parity(data_always_0_parity, 0, 12, BitLibParityAlways0, 4));
|
||||
mu_check(bit_lib_test_parity(data_always_0_parity, 4, 8, BitLibParityAlways0, 4));
|
||||
mu_check(bit_lib_test_parity(data_always_0_parity, 8, 4, BitLibParityAlways0, 4));
|
||||
mu_check(bit_lib_test_parity(data_always_1_parity, 12, 4, BitLibParityAlways0, 4));
|
||||
|
||||
mu_check(!bit_lib_test_parity(data_always_0_parity, 0, 16, BitLibParityAlways0, 4));
|
||||
mu_check(!bit_lib_test_parity(data_always_0_parity, 4, 12, BitLibParityAlways0, 4));
|
||||
mu_check(!bit_lib_test_parity(data_always_0_parity, 8, 8, BitLibParityAlways0, 4));
|
||||
mu_check(!bit_lib_test_parity(data_always_0_parity, 12, 4, BitLibParityAlways0, 4));
|
||||
|
||||
// test alawys 1 parity
|
||||
mu_check(bit_lib_test_parity(data_always_1_parity, 0, 12, BitLibParityAlways1, 4));
|
||||
mu_check(bit_lib_test_parity(data_always_1_parity, 4, 8, BitLibParityAlways1, 4));
|
||||
mu_check(bit_lib_test_parity(data_always_1_parity, 8, 4, BitLibParityAlways1, 4));
|
||||
mu_check(bit_lib_test_parity(data_always_0_parity, 12, 4, BitLibParityAlways1, 4));
|
||||
|
||||
mu_check(!bit_lib_test_parity(data_always_1_parity, 0, 16, BitLibParityAlways1, 4));
|
||||
mu_check(!bit_lib_test_parity(data_always_1_parity, 4, 12, BitLibParityAlways1, 4));
|
||||
mu_check(!bit_lib_test_parity(data_always_1_parity, 8, 8, BitLibParityAlways1, 4));
|
||||
mu_check(!bit_lib_test_parity(data_always_1_parity, 12, 4, BitLibParityAlways1, 4));
|
||||
|
||||
// test odd parity
|
||||
mu_check(bit_lib_test_parity(data_always_odd_parity, 0, 12, BitLibParityOdd, 4));
|
||||
mu_check(bit_lib_test_parity(data_always_odd_parity, 4, 8, BitLibParityOdd, 4));
|
||||
mu_check(bit_lib_test_parity(data_always_odd_parity, 8, 4, BitLibParityOdd, 4));
|
||||
mu_check(bit_lib_test_parity(data_always_even_parity, 12, 4, BitLibParityOdd, 4));
|
||||
|
||||
mu_check(!bit_lib_test_parity(data_always_odd_parity, 0, 16, BitLibParityOdd, 4));
|
||||
mu_check(!bit_lib_test_parity(data_always_odd_parity, 4, 12, BitLibParityOdd, 4));
|
||||
mu_check(!bit_lib_test_parity(data_always_odd_parity, 8, 8, BitLibParityOdd, 4));
|
||||
mu_check(!bit_lib_test_parity(data_always_odd_parity, 12, 4, BitLibParityOdd, 4));
|
||||
|
||||
// test even parity
|
||||
mu_check(bit_lib_test_parity(data_always_even_parity, 0, 12, BitLibParityEven, 4));
|
||||
mu_check(bit_lib_test_parity(data_always_even_parity, 4, 8, BitLibParityEven, 4));
|
||||
mu_check(bit_lib_test_parity(data_always_even_parity, 8, 4, BitLibParityEven, 4));
|
||||
mu_check(bit_lib_test_parity(data_always_odd_parity, 12, 4, BitLibParityEven, 4));
|
||||
|
||||
mu_check(!bit_lib_test_parity(data_always_even_parity, 0, 16, BitLibParityEven, 4));
|
||||
mu_check(!bit_lib_test_parity(data_always_even_parity, 4, 12, BitLibParityEven, 4));
|
||||
mu_check(!bit_lib_test_parity(data_always_even_parity, 8, 8, BitLibParityEven, 4));
|
||||
mu_check(!bit_lib_test_parity(data_always_even_parity, 12, 4, BitLibParityEven, 4));
|
||||
}
|
||||
|
||||
MU_TEST(test_bit_lib_remove_bit_every_nth) {
|
||||
// TODO: more tests
|
||||
uint8_t data_i[1] = {0b00001111};
|
||||
uint8_t data_o[1] = {0b00011111};
|
||||
size_t length;
|
||||
|
||||
length = bit_lib_remove_bit_every_nth(data_i, 0, 8, 3);
|
||||
mu_assert_int_eq(6, length);
|
||||
mu_assert_mem_eq(data_o, data_i, 1);
|
||||
}
|
||||
|
||||
MU_TEST(test_bit_lib_reverse_bits) {
|
||||
uint8_t data_1_i[2] = {0b11001010, 0b00011111};
|
||||
uint8_t data_1_o[2] = {0b11111000, 0b01010011};
|
||||
|
||||
// reverse bits [0..15]
|
||||
bit_lib_reverse_bits(data_1_i, 0, 16);
|
||||
mu_assert_mem_eq(data_1_o, data_1_i, 2);
|
||||
|
||||
uint8_t data_2_i[2] = {0b11001010, 0b00011111};
|
||||
uint8_t data_2_o[2] = {0b11001000, 0b01011111};
|
||||
|
||||
// reverse bits [4..11]
|
||||
bit_lib_reverse_bits(data_2_i, 4, 8);
|
||||
mu_assert_mem_eq(data_2_o, data_2_i, 2);
|
||||
}
|
||||
|
||||
MU_TEST(test_bit_lib_copy_bits) {
|
||||
uint8_t data_1_i[2] = {0b11001010, 0b00011111};
|
||||
uint8_t data_1_o[2] = {0};
|
||||
|
||||
// data_1_o[0..15] = data_1_i[0..15]
|
||||
bit_lib_copy_bits(data_1_o, 0, 16, data_1_i, 0);
|
||||
mu_assert_mem_eq(data_1_i, data_1_o, 2);
|
||||
|
||||
memset(data_1_o, 0, 2);
|
||||
// data_1_o[4..11] = data_1_i[0..7]
|
||||
bit_lib_copy_bits(data_1_o, 4, 8, data_1_i, 0);
|
||||
mu_assert_mem_eq(((uint8_t[]){0b00001100, 0b10100000}), data_1_o, 2);
|
||||
}
|
||||
|
||||
MU_TEST(test_bit_lib_get_bit_count) {
|
||||
mu_assert_int_eq(0, bit_lib_get_bit_count(0));
|
||||
mu_assert_int_eq(1, bit_lib_get_bit_count(0b1));
|
||||
mu_assert_int_eq(1, bit_lib_get_bit_count(0b10));
|
||||
mu_assert_int_eq(2, bit_lib_get_bit_count(0b11));
|
||||
mu_assert_int_eq(4, bit_lib_get_bit_count(0b11000011));
|
||||
mu_assert_int_eq(6, bit_lib_get_bit_count(0b11000011000011));
|
||||
mu_assert_int_eq(8, bit_lib_get_bit_count(0b11111111));
|
||||
mu_assert_int_eq(16, bit_lib_get_bit_count(0b11111110000000000000000111111111));
|
||||
mu_assert_int_eq(32, bit_lib_get_bit_count(0b11111111111111111111111111111111));
|
||||
}
|
||||
|
||||
MU_TEST(test_bit_lib_reverse_16_fast) {
|
||||
mu_assert_int_eq(0b0000000000000000, bit_lib_reverse_16_fast(0b0000000000000000));
|
||||
mu_assert_int_eq(0b1000000000000000, bit_lib_reverse_16_fast(0b0000000000000001));
|
||||
mu_assert_int_eq(0b1100000000000000, bit_lib_reverse_16_fast(0b0000000000000011));
|
||||
mu_assert_int_eq(0b0000100000001001, bit_lib_reverse_16_fast(0b1001000000010000));
|
||||
}
|
||||
|
||||
MU_TEST(test_bit_lib_crc16) {
|
||||
uint8_t data[9] = {'1', '2', '3', '4', '5', '6', '7', '8', '9'};
|
||||
uint8_t data_size = 9;
|
||||
|
||||
// Algorithm
|
||||
// Check Poly Init RefIn RefOut XorOut
|
||||
// CRC-16/CCITT-FALSE
|
||||
// 0x29B1 0x1021 0xFFFF false false 0x0000
|
||||
mu_assert_int_eq(0x29B1, bit_lib_crc16(data, data_size, 0x1021, 0xFFFF, false, false, 0x0000));
|
||||
// CRC-16/ARC
|
||||
// 0xBB3D 0x8005 0x0000 true true 0x0000
|
||||
mu_assert_int_eq(0xBB3D, bit_lib_crc16(data, data_size, 0x8005, 0x0000, true, true, 0x0000));
|
||||
// CRC-16/AUG-CCITT
|
||||
// 0xE5CC 0x1021 0x1D0F false false 0x0000
|
||||
mu_assert_int_eq(0xE5CC, bit_lib_crc16(data, data_size, 0x1021, 0x1D0F, false, false, 0x0000));
|
||||
// CRC-16/BUYPASS
|
||||
// 0xFEE8 0x8005 0x0000 false false 0x0000
|
||||
mu_assert_int_eq(0xFEE8, bit_lib_crc16(data, data_size, 0x8005, 0x0000, false, false, 0x0000));
|
||||
// CRC-16/CDMA2000
|
||||
// 0x4C06 0xC867 0xFFFF false false 0x0000
|
||||
mu_assert_int_eq(0x4C06, bit_lib_crc16(data, data_size, 0xC867, 0xFFFF, false, false, 0x0000));
|
||||
// CRC-16/DDS-110
|
||||
// 0x9ECF 0x8005 0x800D false false 0x0000
|
||||
mu_assert_int_eq(0x9ECF, bit_lib_crc16(data, data_size, 0x8005, 0x800D, false, false, 0x0000));
|
||||
// CRC-16/DECT-R
|
||||
// 0x007E 0x0589 0x0000 false false 0x0001
|
||||
mu_assert_int_eq(0x007E, bit_lib_crc16(data, data_size, 0x0589, 0x0000, false, false, 0x0001));
|
||||
// CRC-16/DECT-X
|
||||
// 0x007F 0x0589 0x0000 false false 0x0000
|
||||
mu_assert_int_eq(0x007F, bit_lib_crc16(data, data_size, 0x0589, 0x0000, false, false, 0x0000));
|
||||
// CRC-16/DNP
|
||||
// 0xEA82 0x3D65 0x0000 true true 0xFFFF
|
||||
mu_assert_int_eq(0xEA82, bit_lib_crc16(data, data_size, 0x3D65, 0x0000, true, true, 0xFFFF));
|
||||
// CRC-16/EN-13757
|
||||
// 0xC2B7 0x3D65 0x0000 false false 0xFFFF
|
||||
mu_assert_int_eq(0xC2B7, bit_lib_crc16(data, data_size, 0x3D65, 0x0000, false, false, 0xFFFF));
|
||||
// CRC-16/GENIBUS
|
||||
// 0xD64E 0x1021 0xFFFF false false 0xFFFF
|
||||
mu_assert_int_eq(0xD64E, bit_lib_crc16(data, data_size, 0x1021, 0xFFFF, false, false, 0xFFFF));
|
||||
// CRC-16/MAXIM
|
||||
// 0x44C2 0x8005 0x0000 true true 0xFFFF
|
||||
mu_assert_int_eq(0x44C2, bit_lib_crc16(data, data_size, 0x8005, 0x0000, true, true, 0xFFFF));
|
||||
// CRC-16/MCRF4XX
|
||||
// 0x6F91 0x1021 0xFFFF true true 0x0000
|
||||
mu_assert_int_eq(0x6F91, bit_lib_crc16(data, data_size, 0x1021, 0xFFFF, true, true, 0x0000));
|
||||
// CRC-16/RIELLO
|
||||
// 0x63D0 0x1021 0xB2AA true true 0x0000
|
||||
mu_assert_int_eq(0x63D0, bit_lib_crc16(data, data_size, 0x1021, 0xB2AA, true, true, 0x0000));
|
||||
// CRC-16/T10-DIF
|
||||
// 0xD0DB 0x8BB7 0x0000 false false 0x0000
|
||||
mu_assert_int_eq(0xD0DB, bit_lib_crc16(data, data_size, 0x8BB7, 0x0000, false, false, 0x0000));
|
||||
// CRC-16/TELEDISK
|
||||
// 0x0FB3 0xA097 0x0000 false false 0x0000
|
||||
mu_assert_int_eq(0x0FB3, bit_lib_crc16(data, data_size, 0xA097, 0x0000, false, false, 0x0000));
|
||||
// CRC-16/TMS37157
|
||||
// 0x26B1 0x1021 0x89EC true true 0x0000
|
||||
mu_assert_int_eq(0x26B1, bit_lib_crc16(data, data_size, 0x1021, 0x89EC, true, true, 0x0000));
|
||||
// CRC-16/USB
|
||||
// 0xB4C8 0x8005 0xFFFF true true 0xFFFF
|
||||
mu_assert_int_eq(0xB4C8, bit_lib_crc16(data, data_size, 0x8005, 0xFFFF, true, true, 0xFFFF));
|
||||
// CRC-A
|
||||
// 0xBF05 0x1021 0xC6C6 true true 0x0000
|
||||
mu_assert_int_eq(0xBF05, bit_lib_crc16(data, data_size, 0x1021, 0xC6C6, true, true, 0x0000));
|
||||
// CRC-16/KERMIT
|
||||
// 0x2189 0x1021 0x0000 true true 0x0000
|
||||
mu_assert_int_eq(0x2189, bit_lib_crc16(data, data_size, 0x1021, 0x0000, true, true, 0x0000));
|
||||
// CRC-16/MODBUS
|
||||
// 0x4B37 0x8005 0xFFFF true true 0x0000
|
||||
mu_assert_int_eq(0x4B37, bit_lib_crc16(data, data_size, 0x8005, 0xFFFF, true, true, 0x0000));
|
||||
// CRC-16/X-25
|
||||
// 0x906E 0x1021 0xFFFF true true 0xFFFF
|
||||
mu_assert_int_eq(0x906E, bit_lib_crc16(data, data_size, 0x1021, 0xFFFF, true, true, 0xFFFF));
|
||||
// CRC-16/XMODEM
|
||||
// 0x31C3 0x1021 0x0000 false false 0x0000
|
||||
mu_assert_int_eq(0x31C3, bit_lib_crc16(data, data_size, 0x1021, 0x0000, false, false, 0x0000));
|
||||
}
|
||||
|
||||
MU_TEST_SUITE(test_bit_lib) {
|
||||
MU_RUN_TEST(test_bit_lib_increment_index);
|
||||
MU_RUN_TEST(test_bit_lib_is_set);
|
||||
MU_RUN_TEST(test_bit_lib_push);
|
||||
MU_RUN_TEST(test_bit_lib_set_bit);
|
||||
MU_RUN_TEST(test_bit_lib_set_bits);
|
||||
MU_RUN_TEST(test_bit_lib_get_bit);
|
||||
MU_RUN_TEST(test_bit_lib_get_bits);
|
||||
MU_RUN_TEST(test_bit_lib_get_bits_16);
|
||||
MU_RUN_TEST(test_bit_lib_get_bits_32);
|
||||
MU_RUN_TEST(test_bit_lib_test_parity_u32);
|
||||
MU_RUN_TEST(test_bit_lib_test_parity);
|
||||
MU_RUN_TEST(test_bit_lib_remove_bit_every_nth);
|
||||
MU_RUN_TEST(test_bit_lib_copy_bits);
|
||||
MU_RUN_TEST(test_bit_lib_reverse_bits);
|
||||
MU_RUN_TEST(test_bit_lib_get_bit_count);
|
||||
MU_RUN_TEST(test_bit_lib_reverse_16_fast);
|
||||
MU_RUN_TEST(test_bit_lib_crc16);
|
||||
}
|
||||
|
||||
int run_minunit_test_bit_lib() {
|
||||
MU_RUN_SUITE(test_bit_lib);
|
||||
return MU_EXIT_CODE;
|
||||
}
|
464
applications/debug/unit_tests/lfrfid/lfrfid_protocols.c
Normal file
464
applications/debug/unit_tests/lfrfid/lfrfid_protocols.c
Normal file
@@ -0,0 +1,464 @@
|
||||
#include <furi.h>
|
||||
#include "../minunit.h"
|
||||
#include <toolbox/protocols/protocol_dict.h>
|
||||
#include <lfrfid/protocols/lfrfid_protocols.h>
|
||||
#include <toolbox/pulse_protocols/pulse_glue.h>
|
||||
|
||||
#define LF_RFID_READ_TIMING_MULTIPLIER 8
|
||||
|
||||
#define EM_TEST_DATA \
|
||||
{ 0x58, 0x00, 0x85, 0x64, 0x02 }
|
||||
#define EM_TEST_DATA_SIZE 5
|
||||
#define EM_TEST_EMULATION_TIMINGS_COUNT (64 * 2)
|
||||
|
||||
const int8_t em_test_timings[EM_TEST_EMULATION_TIMINGS_COUNT] = {
|
||||
32, -32, 32, -32, 32, -32, 32, -32, 32, -32, 32, -32, 32, -32, 32, -32, 32, -32, -32,
|
||||
32, 32, -32, -32, 32, 32, -32, -32, 32, 32, -32, -32, 32, -32, 32, -32, 32, 32, -32,
|
||||
-32, 32, -32, 32, -32, 32, -32, 32, -32, 32, -32, 32, -32, 32, -32, 32, -32, 32, -32,
|
||||
32, 32, -32, -32, 32, -32, 32, -32, 32, 32, -32, -32, 32, 32, -32, -32, 32, 32, -32,
|
||||
-32, 32, -32, 32, 32, -32, 32, -32, -32, 32, -32, 32, -32, 32, 32, -32, -32, 32, -32,
|
||||
32, 32, -32, -32, 32, -32, 32, -32, 32, -32, 32, -32, 32, -32, 32, -32, 32, 32, -32,
|
||||
-32, 32, 32, -32, -32, 32, -32, 32, -32, 32, -32, 32, -32, 32,
|
||||
};
|
||||
|
||||
#define HID10301_TEST_DATA \
|
||||
{ 0x8D, 0x48, 0xA8 }
|
||||
#define HID10301_TEST_DATA_SIZE 3
|
||||
#define HID10301_TEST_EMULATION_TIMINGS_COUNT (541 * 2)
|
||||
|
||||
const int8_t hid10301_test_timings[HID10301_TEST_EMULATION_TIMINGS_COUNT] = {
|
||||
4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4,
|
||||
4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 5, -5, 5, -5, 5, -5, 5, -5, 5, -5, 5, -5, 5, -5,
|
||||
5, -5, 5, -5, 5, -5, 5, -5, 5, -5, 5, -5, 5, -5, 5, -5, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4,
|
||||
4, -4, 4, -4, 5, -5, 5, -5, 5, -5, 5, -5, 5, -5, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4,
|
||||
5, -5, 5, -5, 5, -5, 5, -5, 5, -5, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 5, -5, 5, -5,
|
||||
5, -5, 5, -5, 5, -5, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 5, -5, 5, -5, 5, -5, 5, -5,
|
||||
5, -5, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 5, -5, 5, -5, 5, -5, 5, -5, 5, -5,
|
||||
4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 5, -5, 5, -5, 5, -5, 5, -5, 5, -5, 4, -4, 4, -4,
|
||||
4, -4, 4, -4, 4, -4, 4, -4, 5, -5, 5, -5, 5, -5, 5, -5, 5, -5, 5, -5, 5, -5, 5, -5, 5, -5,
|
||||
5, -5, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4,
|
||||
4, -4, 5, -5, 5, -5, 5, -5, 5, -5, 5, -5, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 5, -5,
|
||||
5, -5, 5, -5, 5, -5, 5, -5, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 5, -5, 5, -5, 5, -5,
|
||||
5, -5, 5, -5, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 5, -5, 5, -5, 5, -5, 5, -5, 5, -5,
|
||||
4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 5, -5, 5, -5, 5, -5, 5, -5, 5, -5, 4, -4,
|
||||
4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 5, -5, 5, -5, 5, -5, 5, -5, 5, -5, 4, -4, 4, -4, 4, -4,
|
||||
4, -4, 4, -4, 4, -4, 5, -5, 5, -5, 5, -5, 5, -5, 5, -5, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4,
|
||||
4, -4, 5, -5, 5, -5, 5, -5, 5, -5, 5, -5, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4,
|
||||
5, -5, 5, -5, 5, -5, 5, -5, 5, -5, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 5, -5, 5, -5,
|
||||
5, -5, 5, -5, 5, -5, 5, -5, 5, -5, 5, -5, 5, -5, 5, -5, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4,
|
||||
4, -4, 5, -5, 5, -5, 5, -5, 5, -5, 5, -5, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 5, -5,
|
||||
5, -5, 5, -5, 5, -5, 5, -5, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4,
|
||||
4, -4, 4, -4, 4, -4, 4, -4, 5, -5, 5, -5, 5, -5, 5, -5, 5, -5, 4, -4, 4, -4, 4, -4, 4, -4,
|
||||
4, -4, 4, -4, 5, -5, 5, -5, 5, -5, 5, -5, 5, -5, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4,
|
||||
5, -5, 5, -5, 5, -5, 5, -5, 5, -5, 5, -5, 5, -5, 5, -5, 5, -5, 5, -5, 4, -4, 4, -4, 4, -4,
|
||||
4, -4, 4, -4, 4, -4, 4, -4, 5, -5, 5, -5, 5, -5, 5, -5, 5, -5, 4, -4, 4, -4, 4, -4, 4, -4,
|
||||
4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 5, -5, 5, -5, 5, -5, 5, -5, 5, -5,
|
||||
5, -5, 5, -5, 5, -5, 5, -5, 5, -5, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4,
|
||||
4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 5, -5, 5, -5, 5, -5, 5, -5, 5, -5, 5, -5, 5, -5, 5, -5,
|
||||
5, -5, 5, -5, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4,
|
||||
4, -4, 5, -5, 5, -5, 5, -5, 5, -5, 5, -5, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 5, -5,
|
||||
5, -5, 5, -5, 5, -5, 5, -5, 5, -5, 5, -5, 5, -5, 5, -5, 5, -5, 4, -4, 4, -4, 4, -4, 4, -4,
|
||||
4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 5, -5, 5, -5, 5, -5, 5, -5,
|
||||
5, -5, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 5, -5, 5, -5, 5, -5, 5, -5, 5, -5, 4, -4,
|
||||
4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 5, -5, 5, -5, 5, -5, 5, -5, 5, -5, 5, -5, 5, -5, 5, -5,
|
||||
5, -5, 5, -5, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4,
|
||||
4, -4, 4, -4, 5, -5, 5, -5, 5, -5, 5, -5, 5, -5, 5, -5, 5, -5, 5, -5, 5, -5, 5, -5, 4, -4,
|
||||
4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 5, -5, 5, -5,
|
||||
5, -5, 5, -5, 5, -5, 5, -5, 5, -5, 5, -5, 5, -5, 5, -5, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4,
|
||||
4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 5, -5, 5, -5, 5, -5, 5, -5, 5, -5,
|
||||
4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 5, -5, 5, -5, 5, -5, 5, -5, 5, -5, 4, -4, 4, -4,
|
||||
4, -4, 4, -4, 4, -4, 4, -4, 5, -5, 5, -5, 5, -5, 5, -5, 5, -5, 5, -5, 5, -5, 5, -5, 5, -5,
|
||||
5, -5, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4,
|
||||
};
|
||||
|
||||
#define IOPROX_XSF_TEST_DATA \
|
||||
{ 0x65, 0x01, 0x05, 0x39 }
|
||||
#define IOPROX_XSF_TEST_DATA_SIZE 4
|
||||
#define IOPROX_XSF_TEST_EMULATION_TIMINGS_COUNT (468 * 2)
|
||||
|
||||
const int8_t ioprox_xsf_test_timings[IOPROX_XSF_TEST_EMULATION_TIMINGS_COUNT] = {
|
||||
4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4,
|
||||
4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4,
|
||||
4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4,
|
||||
4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4,
|
||||
4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4,
|
||||
4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 5, -5, 5, -5, 5, -5, 5, -5, 5, -5,
|
||||
5, -5, 5, -5, 5, -5, 5, -5, 5, -5, 5, -5, 5, -5, 5, -5, 5, -5, 5, -5, 5, -5, 5, -5, 5, -5,
|
||||
5, -5, 5, -5, 5, -5, 5, -5, 5, -5, 5, -5, 5, -5, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4,
|
||||
4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4,
|
||||
4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4,
|
||||
5, -5, 5, -5, 5, -5, 5, -5, 5, -5, 5, -5, 5, -5, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4,
|
||||
4, -4, 4, -4, 5, -5, 5, -5, 5, -5, 5, -5, 5, -5, 5, -5, 5, -5, 5, -5, 5, -5, 5, -5, 5, -5,
|
||||
5, -5, 5, -5, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4,
|
||||
4, -4, 4, -4, 4, -4, 4, -4, 5, -5, 5, -5, 5, -5, 5, -5, 5, -5, 5, -5, 5, -5, 4, -4, 4, -4,
|
||||
4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 5, -5, 5, -5, 5, -5, 5, -5, 5, -5, 5, -5, 5, -5,
|
||||
5, -5, 5, -5, 5, -5, 5, -5, 5, -5, 5, -5, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4,
|
||||
4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4,
|
||||
4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4,
|
||||
4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4,
|
||||
4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 5, -5, 5, -5, 5, -5, 5, -5,
|
||||
5, -5, 5, -5, 5, -5, 5, -5, 5, -5, 5, -5, 5, -5, 5, -5, 5, -5, 4, -4, 4, -4, 4, -4, 4, -4,
|
||||
4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4,
|
||||
4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4,
|
||||
4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 5, -5, 5, -5, 5, -5,
|
||||
5, -5, 5, -5, 5, -5, 5, -5, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 5, -5, 5, -5,
|
||||
5, -5, 5, -5, 5, -5, 5, -5, 5, -5, 5, -5, 5, -5, 5, -5, 5, -5, 5, -5, 5, -5, 4, -4, 4, -4,
|
||||
4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4,
|
||||
4, -4, 5, -5, 5, -5, 5, -5, 5, -5, 5, -5, 5, -5, 5, -5, 5, -5, 5, -5, 5, -5, 5, -5, 5, -5,
|
||||
5, -5, 5, -5, 5, -5, 5, -5, 5, -5, 5, -5, 5, -5, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4,
|
||||
4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 5, -5, 5, -5, 5, -5,
|
||||
5, -5, 5, -5, 5, -5, 5, -5, 5, -5, 5, -5, 5, -5, 5, -5, 5, -5, 5, -5, 4, -4, 4, -4, 4, -4,
|
||||
4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 5, -5, 5, -5, 5, -5, 5, -5, 5, -5, 5, -5, 5, -5, 5, -5,
|
||||
5, -5, 5, -5, 5, -5, 5, -5, 5, -5, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4,
|
||||
5, -5, 5, -5, 5, -5, 5, -5, 5, -5, 5, -5, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4,
|
||||
4, -4, 5, -5, 5, -5, 5, -5, 5, -5, 5, -5, 5, -5, 5, -5, 5, -5, 5, -5, 5, -5, 5, -5, 5, -5,
|
||||
5, -5, 5, -5, 5, -5, 5, -5, 5, -5, 5, -5, 5, -5, 5, -5, 5, -5, 5, -5, 5, -5, 5, -5, 5, -5,
|
||||
};
|
||||
|
||||
#define INDALA26_EMULATION_TIMINGS_COUNT (1024 * 2)
|
||||
#define INDALA26_TEST_DATA \
|
||||
{ 0x3B, 0x73, 0x64, 0xA8 }
|
||||
#define INDALA26_TEST_DATA_SIZE 4
|
||||
|
||||
const int8_t indala26_test_timings[INDALA26_EMULATION_TIMINGS_COUNT] = {
|
||||
1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1,
|
||||
1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1,
|
||||
1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, -1, 1, -1, 1, -1, 1, -1, 1,
|
||||
-1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1,
|
||||
1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1,
|
||||
1, -1, 1, -1, 1, -1, 1, -1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1,
|
||||
-1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1,
|
||||
-1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1,
|
||||
-1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1,
|
||||
-1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1,
|
||||
-1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1,
|
||||
-1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1,
|
||||
-1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1,
|
||||
-1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1,
|
||||
-1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1,
|
||||
-1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1,
|
||||
-1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1,
|
||||
-1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1,
|
||||
-1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1,
|
||||
-1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1,
|
||||
-1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1,
|
||||
-1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1,
|
||||
-1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1,
|
||||
-1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1,
|
||||
-1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1,
|
||||
-1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1,
|
||||
-1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1,
|
||||
-1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1,
|
||||
-1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1,
|
||||
-1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1,
|
||||
-1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1,
|
||||
-1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1,
|
||||
-1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1,
|
||||
-1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1,
|
||||
-1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1,
|
||||
-1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1,
|
||||
-1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1,
|
||||
-1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1,
|
||||
-1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1,
|
||||
-1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1,
|
||||
-1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1,
|
||||
-1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1,
|
||||
-1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1,
|
||||
-1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1,
|
||||
1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1,
|
||||
1, -1, 1, -1, 1, -1, 1, -1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1,
|
||||
-1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1,
|
||||
-1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1,
|
||||
1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1,
|
||||
1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1,
|
||||
1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1,
|
||||
1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1,
|
||||
-1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1,
|
||||
-1, 1, -1, 1, -1, 1, -1, 1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1,
|
||||
1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1,
|
||||
1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1,
|
||||
-1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1,
|
||||
-1, 1, -1, 1, -1, 1, -1, 1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1,
|
||||
1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1,
|
||||
1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1,
|
||||
1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1,
|
||||
1, -1, 1, -1, 1, -1, 1, -1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1,
|
||||
-1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1,
|
||||
-1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1,
|
||||
1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1,
|
||||
1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1,
|
||||
1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, -1, 1, -1, 1, -1, 1, -1, 1,
|
||||
-1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1,
|
||||
1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1,
|
||||
1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1,
|
||||
1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, -1, 1, -1, 1, -1, 1, -1, 1,
|
||||
-1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1,
|
||||
-1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1,
|
||||
-1, 1, -1, 1, -1, 1, -1, 1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1,
|
||||
1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, -1, 1, -1, 1, -1, 1, -1, 1,
|
||||
-1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1,
|
||||
-1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1,
|
||||
-1, 1, -1, 1, -1, 1, -1, 1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1,
|
||||
1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, -1, 1, -1, 1, -1, 1, -1, 1,
|
||||
-1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1,
|
||||
1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1,
|
||||
1, -1, 1, -1, 1, -1, 1, -1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1,
|
||||
-1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1,
|
||||
-1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1,
|
||||
-1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1,
|
||||
-1, 1, -1, 1, -1, 1, -1, 1,
|
||||
};
|
||||
|
||||
MU_TEST(test_lfrfid_protocol_em_read_simple) {
|
||||
ProtocolDict* dict = protocol_dict_alloc(lfrfid_protocols, LFRFIDProtocolMax);
|
||||
mu_assert_int_eq(EM_TEST_DATA_SIZE, protocol_dict_get_data_size(dict, LFRFIDProtocolEM4100));
|
||||
mu_assert_string_eq("EM4100", protocol_dict_get_name(dict, LFRFIDProtocolEM4100));
|
||||
mu_assert_string_eq("EM-Micro", protocol_dict_get_manufacturer(dict, LFRFIDProtocolEM4100));
|
||||
|
||||
const uint8_t data[EM_TEST_DATA_SIZE] = EM_TEST_DATA;
|
||||
|
||||
protocol_dict_decoders_start(dict);
|
||||
|
||||
ProtocolId protocol = PROTOCOL_NO;
|
||||
PulseGlue* pulse_glue = pulse_glue_alloc();
|
||||
|
||||
for(size_t i = 0; i < EM_TEST_EMULATION_TIMINGS_COUNT * 10; i++) {
|
||||
bool pulse_pop = pulse_glue_push(
|
||||
pulse_glue,
|
||||
em_test_timings[i % EM_TEST_EMULATION_TIMINGS_COUNT] >= 0,
|
||||
abs(em_test_timings[i % EM_TEST_EMULATION_TIMINGS_COUNT]) *
|
||||
LF_RFID_READ_TIMING_MULTIPLIER);
|
||||
|
||||
if(pulse_pop) {
|
||||
uint32_t length, period;
|
||||
pulse_glue_pop(pulse_glue, &length, &period);
|
||||
|
||||
protocol = protocol_dict_decoders_feed(dict, true, period);
|
||||
if(protocol != PROTOCOL_NO) break;
|
||||
|
||||
protocol = protocol_dict_decoders_feed(dict, false, length - period);
|
||||
if(protocol != PROTOCOL_NO) break;
|
||||
}
|
||||
}
|
||||
|
||||
pulse_glue_free(pulse_glue);
|
||||
|
||||
mu_assert_int_eq(LFRFIDProtocolEM4100, protocol);
|
||||
uint8_t received_data[EM_TEST_DATA_SIZE] = {0};
|
||||
protocol_dict_get_data(dict, protocol, received_data, EM_TEST_DATA_SIZE);
|
||||
|
||||
mu_assert_mem_eq(data, received_data, EM_TEST_DATA_SIZE);
|
||||
|
||||
protocol_dict_free(dict);
|
||||
}
|
||||
|
||||
MU_TEST(test_lfrfid_protocol_em_emulate_simple) {
|
||||
ProtocolDict* dict = protocol_dict_alloc(lfrfid_protocols, LFRFIDProtocolMax);
|
||||
mu_assert_int_eq(EM_TEST_DATA_SIZE, protocol_dict_get_data_size(dict, LFRFIDProtocolEM4100));
|
||||
mu_assert_string_eq("EM4100", protocol_dict_get_name(dict, LFRFIDProtocolEM4100));
|
||||
mu_assert_string_eq("EM-Micro", protocol_dict_get_manufacturer(dict, LFRFIDProtocolEM4100));
|
||||
|
||||
const uint8_t data[EM_TEST_DATA_SIZE] = EM_TEST_DATA;
|
||||
|
||||
protocol_dict_set_data(dict, LFRFIDProtocolEM4100, data, EM_TEST_DATA_SIZE);
|
||||
mu_check(protocol_dict_encoder_start(dict, LFRFIDProtocolEM4100));
|
||||
|
||||
for(size_t i = 0; i < EM_TEST_EMULATION_TIMINGS_COUNT; i++) {
|
||||
LevelDuration level_duration = protocol_dict_encoder_yield(dict, LFRFIDProtocolEM4100);
|
||||
|
||||
if(level_duration_get_level(level_duration)) {
|
||||
mu_assert_int_eq(em_test_timings[i], level_duration_get_duration(level_duration));
|
||||
} else {
|
||||
mu_assert_int_eq(em_test_timings[i], -level_duration_get_duration(level_duration));
|
||||
}
|
||||
}
|
||||
|
||||
protocol_dict_free(dict);
|
||||
}
|
||||
|
||||
MU_TEST(test_lfrfid_protocol_h10301_read_simple) {
|
||||
ProtocolDict* dict = protocol_dict_alloc(lfrfid_protocols, LFRFIDProtocolMax);
|
||||
mu_assert_int_eq(
|
||||
HID10301_TEST_DATA_SIZE, protocol_dict_get_data_size(dict, LFRFIDProtocolH10301));
|
||||
mu_assert_string_eq("H10301", protocol_dict_get_name(dict, LFRFIDProtocolH10301));
|
||||
mu_assert_string_eq("HID", protocol_dict_get_manufacturer(dict, LFRFIDProtocolH10301));
|
||||
|
||||
const uint8_t data[HID10301_TEST_DATA_SIZE] = HID10301_TEST_DATA;
|
||||
|
||||
protocol_dict_decoders_start(dict);
|
||||
|
||||
ProtocolId protocol = PROTOCOL_NO;
|
||||
PulseGlue* pulse_glue = pulse_glue_alloc();
|
||||
|
||||
for(size_t i = 0; i < HID10301_TEST_EMULATION_TIMINGS_COUNT * 10; i++) {
|
||||
bool pulse_pop = pulse_glue_push(
|
||||
pulse_glue,
|
||||
hid10301_test_timings[i % HID10301_TEST_EMULATION_TIMINGS_COUNT] >= 0,
|
||||
abs(hid10301_test_timings[i % HID10301_TEST_EMULATION_TIMINGS_COUNT]) *
|
||||
LF_RFID_READ_TIMING_MULTIPLIER);
|
||||
|
||||
if(pulse_pop) {
|
||||
uint32_t length, period;
|
||||
pulse_glue_pop(pulse_glue, &length, &period);
|
||||
|
||||
protocol = protocol_dict_decoders_feed(dict, true, period);
|
||||
if(protocol != PROTOCOL_NO) break;
|
||||
|
||||
protocol = protocol_dict_decoders_feed(dict, false, length - period);
|
||||
if(protocol != PROTOCOL_NO) break;
|
||||
}
|
||||
}
|
||||
|
||||
pulse_glue_free(pulse_glue);
|
||||
|
||||
mu_assert_int_eq(LFRFIDProtocolH10301, protocol);
|
||||
uint8_t received_data[HID10301_TEST_DATA_SIZE] = {0};
|
||||
protocol_dict_get_data(dict, protocol, received_data, HID10301_TEST_DATA_SIZE);
|
||||
|
||||
mu_assert_mem_eq(data, received_data, HID10301_TEST_DATA_SIZE);
|
||||
|
||||
protocol_dict_free(dict);
|
||||
}
|
||||
|
||||
MU_TEST(test_lfrfid_protocol_h10301_emulate_simple) {
|
||||
ProtocolDict* dict = protocol_dict_alloc(lfrfid_protocols, LFRFIDProtocolMax);
|
||||
mu_assert_int_eq(
|
||||
HID10301_TEST_DATA_SIZE, protocol_dict_get_data_size(dict, LFRFIDProtocolH10301));
|
||||
mu_assert_string_eq("H10301", protocol_dict_get_name(dict, LFRFIDProtocolH10301));
|
||||
mu_assert_string_eq("HID", protocol_dict_get_manufacturer(dict, LFRFIDProtocolH10301));
|
||||
|
||||
const uint8_t data[HID10301_TEST_DATA_SIZE] = HID10301_TEST_DATA;
|
||||
|
||||
protocol_dict_set_data(dict, LFRFIDProtocolH10301, data, HID10301_TEST_DATA_SIZE);
|
||||
mu_check(protocol_dict_encoder_start(dict, LFRFIDProtocolH10301));
|
||||
|
||||
for(size_t i = 0; i < HID10301_TEST_EMULATION_TIMINGS_COUNT; i++) {
|
||||
LevelDuration level_duration = protocol_dict_encoder_yield(dict, LFRFIDProtocolH10301);
|
||||
|
||||
if(level_duration_get_level(level_duration)) {
|
||||
mu_assert_int_eq(
|
||||
hid10301_test_timings[i], level_duration_get_duration(level_duration));
|
||||
} else {
|
||||
mu_assert_int_eq(
|
||||
hid10301_test_timings[i], -level_duration_get_duration(level_duration));
|
||||
}
|
||||
}
|
||||
|
||||
protocol_dict_free(dict);
|
||||
}
|
||||
|
||||
MU_TEST(test_lfrfid_protocol_ioprox_xsf_read_simple) {
|
||||
ProtocolDict* dict = protocol_dict_alloc(lfrfid_protocols, LFRFIDProtocolMax);
|
||||
mu_assert_int_eq(
|
||||
IOPROX_XSF_TEST_DATA_SIZE, protocol_dict_get_data_size(dict, LFRFIDProtocolIOProxXSF));
|
||||
mu_assert_string_eq("IoProxXSF", protocol_dict_get_name(dict, LFRFIDProtocolIOProxXSF));
|
||||
mu_assert_string_eq("Kantech", protocol_dict_get_manufacturer(dict, LFRFIDProtocolIOProxXSF));
|
||||
|
||||
const uint8_t data[IOPROX_XSF_TEST_DATA_SIZE] = IOPROX_XSF_TEST_DATA;
|
||||
|
||||
protocol_dict_decoders_start(dict);
|
||||
|
||||
ProtocolId protocol = PROTOCOL_NO;
|
||||
PulseGlue* pulse_glue = pulse_glue_alloc();
|
||||
|
||||
for(size_t i = 0; i < IOPROX_XSF_TEST_EMULATION_TIMINGS_COUNT * 10; i++) {
|
||||
bool pulse_pop = pulse_glue_push(
|
||||
pulse_glue,
|
||||
ioprox_xsf_test_timings[i % IOPROX_XSF_TEST_EMULATION_TIMINGS_COUNT] >= 0,
|
||||
abs(ioprox_xsf_test_timings[i % IOPROX_XSF_TEST_EMULATION_TIMINGS_COUNT]) *
|
||||
LF_RFID_READ_TIMING_MULTIPLIER);
|
||||
|
||||
if(pulse_pop) {
|
||||
uint32_t length, period;
|
||||
pulse_glue_pop(pulse_glue, &length, &period);
|
||||
|
||||
protocol = protocol_dict_decoders_feed(dict, true, period);
|
||||
if(protocol != PROTOCOL_NO) break;
|
||||
|
||||
protocol = protocol_dict_decoders_feed(dict, false, length - period);
|
||||
if(protocol != PROTOCOL_NO) break;
|
||||
}
|
||||
}
|
||||
|
||||
pulse_glue_free(pulse_glue);
|
||||
|
||||
mu_assert_int_eq(LFRFIDProtocolIOProxXSF, protocol);
|
||||
uint8_t received_data[IOPROX_XSF_TEST_DATA_SIZE] = {0};
|
||||
protocol_dict_get_data(dict, protocol, received_data, IOPROX_XSF_TEST_DATA_SIZE);
|
||||
|
||||
mu_assert_mem_eq(data, received_data, IOPROX_XSF_TEST_DATA_SIZE);
|
||||
|
||||
protocol_dict_free(dict);
|
||||
}
|
||||
|
||||
MU_TEST(test_lfrfid_protocol_ioprox_xsf_emulate_simple) {
|
||||
ProtocolDict* dict = protocol_dict_alloc(lfrfid_protocols, LFRFIDProtocolMax);
|
||||
mu_assert_int_eq(
|
||||
IOPROX_XSF_TEST_DATA_SIZE, protocol_dict_get_data_size(dict, LFRFIDProtocolIOProxXSF));
|
||||
mu_assert_string_eq("IoProxXSF", protocol_dict_get_name(dict, LFRFIDProtocolIOProxXSF));
|
||||
mu_assert_string_eq("Kantech", protocol_dict_get_manufacturer(dict, LFRFIDProtocolIOProxXSF));
|
||||
|
||||
const uint8_t data[IOPROX_XSF_TEST_DATA_SIZE] = IOPROX_XSF_TEST_DATA;
|
||||
|
||||
protocol_dict_set_data(dict, LFRFIDProtocolIOProxXSF, data, IOPROX_XSF_TEST_DATA_SIZE);
|
||||
mu_check(protocol_dict_encoder_start(dict, LFRFIDProtocolIOProxXSF));
|
||||
|
||||
for(size_t i = 0; i < IOPROX_XSF_TEST_EMULATION_TIMINGS_COUNT; i++) {
|
||||
LevelDuration level_duration = protocol_dict_encoder_yield(dict, LFRFIDProtocolIOProxXSF);
|
||||
|
||||
if(level_duration_get_level(level_duration)) {
|
||||
mu_assert_int_eq(
|
||||
ioprox_xsf_test_timings[i], level_duration_get_duration(level_duration));
|
||||
} else {
|
||||
mu_assert_int_eq(
|
||||
ioprox_xsf_test_timings[i], -level_duration_get_duration(level_duration));
|
||||
}
|
||||
}
|
||||
|
||||
protocol_dict_free(dict);
|
||||
}
|
||||
|
||||
MU_TEST(test_lfrfid_protocol_inadala26_emulate_simple) {
|
||||
ProtocolDict* dict = protocol_dict_alloc(lfrfid_protocols, LFRFIDProtocolMax);
|
||||
mu_assert_int_eq(
|
||||
INDALA26_TEST_DATA_SIZE, protocol_dict_get_data_size(dict, LFRFIDProtocolIndala26));
|
||||
mu_assert_string_eq("Indala26", protocol_dict_get_name(dict, LFRFIDProtocolIndala26));
|
||||
mu_assert_string_eq("Motorola", protocol_dict_get_manufacturer(dict, LFRFIDProtocolIndala26));
|
||||
|
||||
const uint8_t data[INDALA26_TEST_DATA_SIZE] = INDALA26_TEST_DATA;
|
||||
|
||||
protocol_dict_set_data(dict, LFRFIDProtocolIndala26, data, INDALA26_TEST_DATA_SIZE);
|
||||
mu_check(protocol_dict_encoder_start(dict, LFRFIDProtocolIndala26));
|
||||
|
||||
for(size_t i = 0; i < INDALA26_EMULATION_TIMINGS_COUNT; i++) {
|
||||
LevelDuration level_duration = protocol_dict_encoder_yield(dict, LFRFIDProtocolIndala26);
|
||||
|
||||
if(level_duration_get_level(level_duration)) {
|
||||
mu_assert_int_eq(
|
||||
indala26_test_timings[i], level_duration_get_duration(level_duration));
|
||||
} else {
|
||||
mu_assert_int_eq(
|
||||
indala26_test_timings[i], -level_duration_get_duration(level_duration));
|
||||
}
|
||||
}
|
||||
|
||||
protocol_dict_free(dict);
|
||||
}
|
||||
|
||||
MU_TEST_SUITE(test_lfrfid_protocols_suite) {
|
||||
MU_RUN_TEST(test_lfrfid_protocol_em_read_simple);
|
||||
MU_RUN_TEST(test_lfrfid_protocol_em_emulate_simple);
|
||||
|
||||
MU_RUN_TEST(test_lfrfid_protocol_h10301_read_simple);
|
||||
MU_RUN_TEST(test_lfrfid_protocol_h10301_emulate_simple);
|
||||
|
||||
MU_RUN_TEST(test_lfrfid_protocol_ioprox_xsf_read_simple);
|
||||
MU_RUN_TEST(test_lfrfid_protocol_ioprox_xsf_emulate_simple);
|
||||
|
||||
MU_RUN_TEST(test_lfrfid_protocol_inadala26_emulate_simple);
|
||||
}
|
||||
|
||||
int run_minunit_test_lfrfid_protocols() {
|
||||
MU_RUN_SUITE(test_lfrfid_protocols_suite);
|
||||
return MU_EXIT_CODE;
|
||||
}
|
656
applications/debug/unit_tests/minunit.h
Normal file
656
applications/debug/unit_tests/minunit.h
Normal file
@@ -0,0 +1,656 @@
|
||||
/*
|
||||
* Copyright (c) 2012 David Siñuela Pastor, siu.4coders@gmail.com
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
#ifndef MINUNIT_MINUNIT_H
|
||||
#define MINUNIT_MINUNIT_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#if defined(_WIN32)
|
||||
#include <Windows.h>
|
||||
#if defined(_MSC_VER) && _MSC_VER < 1900
|
||||
#define snprintf _snprintf
|
||||
#define __func__ __FUNCTION__
|
||||
#endif
|
||||
|
||||
#elif defined(__unix__) || defined(__unix) || defined(unix) || \
|
||||
(defined(__APPLE__) && defined(__MACH__))
|
||||
|
||||
/* Change POSIX C SOURCE version for pure c99 compilers */
|
||||
#if !defined(_POSIX_C_SOURCE) || _POSIX_C_SOURCE < 200112L
|
||||
#undef _POSIX_C_SOURCE
|
||||
#define _POSIX_C_SOURCE 200112L
|
||||
#endif
|
||||
|
||||
#include <unistd.h> /* POSIX flags */
|
||||
#include <time.h> /* clock_gettime(), time() */
|
||||
#include <sys/time.h> /* gethrtime(), gettimeofday() */
|
||||
#include <sys/resource.h>
|
||||
#include <sys/times.h>
|
||||
#include <string.h>
|
||||
|
||||
#if defined(__MACH__) && defined(__APPLE__)
|
||||
#include <mach/mach.h>
|
||||
#include <mach/mach_time.h>
|
||||
#endif
|
||||
|
||||
#if __GNUC__ >= 5 && !defined(__STDC_VERSION__)
|
||||
#define __func__ __extension__ __FUNCTION__
|
||||
#endif
|
||||
|
||||
#else
|
||||
|
||||
// #error "Unable to define timers for an unknown OS."
|
||||
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
|
||||
/* Maximum length of last message */
|
||||
#define MINUNIT_MESSAGE_LEN 1024
|
||||
/* Accuracy with which floats are compared */
|
||||
#define MINUNIT_EPSILON 1E-12
|
||||
|
||||
#include "minunit_vars_ex.h"
|
||||
|
||||
/* Test setup and teardown function pointers */
|
||||
__attribute__((unused)) static void (*minunit_setup)(void) = NULL;
|
||||
__attribute__((unused)) static void (*minunit_teardown)(void) = NULL;
|
||||
|
||||
void minunit_print_progress(void);
|
||||
void minunit_print_fail(const char* error);
|
||||
|
||||
/* Definitions */
|
||||
#define MU_TEST(method_name) static void method_name(void)
|
||||
#define MU_TEST_1(method_name, arg_1) static void method_name(arg_1)
|
||||
#define MU_TEST_SUITE(suite_name) static void suite_name(void)
|
||||
|
||||
#define MU__SAFE_BLOCK(block) \
|
||||
do { \
|
||||
block \
|
||||
} while(0)
|
||||
|
||||
/* Run test suite and unset setup and teardown functions */
|
||||
#define MU_RUN_SUITE(suite_name) \
|
||||
MU__SAFE_BLOCK(suite_name(); minunit_setup = NULL; minunit_teardown = NULL;)
|
||||
|
||||
/* Configure setup and teardown functions */
|
||||
#define MU_SUITE_CONFIGURE(setup_fun, teardown_fun) \
|
||||
MU__SAFE_BLOCK(minunit_setup = setup_fun; minunit_teardown = teardown_fun;)
|
||||
|
||||
/* Test runner */
|
||||
#define MU_RUN_TEST(test) \
|
||||
MU__SAFE_BLOCK( \
|
||||
if(minunit_real_timer == 0 && minunit_proc_timer == 0) { \
|
||||
minunit_real_timer = mu_timer_real(); \
|
||||
minunit_proc_timer = mu_timer_cpu(); \
|
||||
} if(minunit_setup) (*minunit_setup)(); \
|
||||
minunit_status = 0; \
|
||||
printf(#test "()\r\n"); \
|
||||
test(); \
|
||||
minunit_run++; \
|
||||
if(minunit_status) { \
|
||||
minunit_fail++; \
|
||||
minunit_print_fail(minunit_last_message); \
|
||||
minunit_status = 0; \
|
||||
} fflush(stdout); \
|
||||
if(minunit_teardown)(*minunit_teardown)();)
|
||||
|
||||
#define MU_RUN_TEST_1(test, arg_1) \
|
||||
MU__SAFE_BLOCK( \
|
||||
if(minunit_real_timer == 0 && minunit_proc_timer == 0) { \
|
||||
minunit_real_timer = mu_timer_real(); \
|
||||
minunit_proc_timer = mu_timer_cpu(); \
|
||||
} if(minunit_setup) (*minunit_setup)(); \
|
||||
minunit_status = 0; \
|
||||
printf(#test "(" #arg_1 ")\r\n"); \
|
||||
test(arg_1); \
|
||||
minunit_run++; \
|
||||
if(minunit_status) { \
|
||||
minunit_fail++; \
|
||||
minunit_print_fail(minunit_last_message); \
|
||||
minunit_status = 0; \
|
||||
} fflush(stdout); \
|
||||
if(minunit_teardown)(*minunit_teardown)();)
|
||||
|
||||
/* Report */
|
||||
#define MU_REPORT() \
|
||||
MU__SAFE_BLOCK(double minunit_end_real_timer; double minunit_end_proc_timer; printf( \
|
||||
"\n\n%d tests, %d assertions, %d failures\n", \
|
||||
minunit_run, \
|
||||
minunit_assert, \
|
||||
minunit_fail); \
|
||||
minunit_end_real_timer = mu_timer_real(); \
|
||||
minunit_end_proc_timer = mu_timer_cpu(); \
|
||||
printf( \
|
||||
"\nFinished in %.8f seconds (real) %.8f seconds (proc)\n\n", \
|
||||
minunit_end_real_timer - minunit_real_timer, \
|
||||
minunit_end_proc_timer - minunit_proc_timer);)
|
||||
#define MU_EXIT_CODE minunit_fail
|
||||
|
||||
/* Assertions */
|
||||
#define mu_check(test) \
|
||||
MU__SAFE_BLOCK( \
|
||||
minunit_assert++; if(!(test)) { \
|
||||
snprintf( \
|
||||
minunit_last_message, \
|
||||
MINUNIT_MESSAGE_LEN, \
|
||||
"%s failed:\r\n\t%s:%d: %s", \
|
||||
__func__, \
|
||||
__FILE__, \
|
||||
__LINE__, \
|
||||
#test); \
|
||||
minunit_status = 1; \
|
||||
return; \
|
||||
} else { minunit_print_progress(); })
|
||||
|
||||
#define mu_fail(message) \
|
||||
MU__SAFE_BLOCK(minunit_assert++; snprintf( \
|
||||
minunit_last_message, \
|
||||
MINUNIT_MESSAGE_LEN, \
|
||||
"%s failed:\r\n\t%s:%d: %s", \
|
||||
__func__, \
|
||||
__FILE__, \
|
||||
__LINE__, \
|
||||
message); \
|
||||
minunit_status = 1; \
|
||||
return;)
|
||||
|
||||
#define mu_assert(test, message) \
|
||||
MU__SAFE_BLOCK( \
|
||||
minunit_assert++; if(!(test)) { \
|
||||
snprintf( \
|
||||
minunit_last_message, \
|
||||
MINUNIT_MESSAGE_LEN, \
|
||||
"%s failed:\r\n\t%s:%d: %s", \
|
||||
__func__, \
|
||||
__FILE__, \
|
||||
__LINE__, \
|
||||
message); \
|
||||
minunit_status = 1; \
|
||||
return; \
|
||||
} else { minunit_print_progress(); })
|
||||
|
||||
#define mu_assert_int_eq(expected, result) \
|
||||
MU__SAFE_BLOCK( \
|
||||
int minunit_tmp_e; int minunit_tmp_r; minunit_assert++; minunit_tmp_e = (expected); \
|
||||
minunit_tmp_r = (result); \
|
||||
if(minunit_tmp_e != minunit_tmp_r) { \
|
||||
snprintf( \
|
||||
minunit_last_message, \
|
||||
MINUNIT_MESSAGE_LEN, \
|
||||
"%s failed:\r\n\t%s:%d: %d expected but was %d", \
|
||||
__func__, \
|
||||
__FILE__, \
|
||||
__LINE__, \
|
||||
minunit_tmp_e, \
|
||||
minunit_tmp_r); \
|
||||
minunit_status = 1; \
|
||||
return; \
|
||||
} else { minunit_print_progress(); })
|
||||
|
||||
#define mu_assert_int_not_eq(expected, result) \
|
||||
MU__SAFE_BLOCK( \
|
||||
int minunit_tmp_e; int minunit_tmp_r; minunit_assert++; minunit_tmp_e = (expected); \
|
||||
minunit_tmp_r = (result); \
|
||||
if(minunit_tmp_e == minunit_tmp_r) { \
|
||||
snprintf( \
|
||||
minunit_last_message, \
|
||||
MINUNIT_MESSAGE_LEN, \
|
||||
"%s failed:\r\n\t%s:%d: expected different results but both were %d", \
|
||||
__func__, \
|
||||
__FILE__, \
|
||||
__LINE__, \
|
||||
minunit_tmp_e); \
|
||||
minunit_status = 1; \
|
||||
return; \
|
||||
} else { minunit_print_progress(); })
|
||||
|
||||
#define mu_assert_int_greater_than(val, result) \
|
||||
MU__SAFE_BLOCK( \
|
||||
int minunit_tmp_e; int minunit_tmp_r; minunit_assert++; minunit_tmp_e = (val); \
|
||||
minunit_tmp_r = (result); \
|
||||
if(val >= minunit_tmp_r) { \
|
||||
snprintf( \
|
||||
minunit_last_message, \
|
||||
MINUNIT_MESSAGE_LEN, \
|
||||
"%s failed:\r\n\t%s:%d: %d <= %d", \
|
||||
__func__, \
|
||||
__FILE__, \
|
||||
__LINE__, \
|
||||
minunit_tmp_r, \
|
||||
minunit_tmp_e); \
|
||||
minunit_status = 1; \
|
||||
return; \
|
||||
} else { minunit_print_progress(); })
|
||||
|
||||
#define mu_assert_int_less_than(val, result) \
|
||||
MU__SAFE_BLOCK( \
|
||||
int minunit_tmp_e; int minunit_tmp_r; minunit_assert++; minunit_tmp_e = (val); \
|
||||
minunit_tmp_r = (result); \
|
||||
if(val <= minunit_tmp_r) { \
|
||||
snprintf( \
|
||||
minunit_last_message, \
|
||||
MINUNIT_MESSAGE_LEN, \
|
||||
"%s failed:\r\n\t%s:%d: %d >= %d", \
|
||||
__func__, \
|
||||
__FILE__, \
|
||||
__LINE__, \
|
||||
minunit_tmp_r, \
|
||||
minunit_tmp_e); \
|
||||
minunit_status = 1; \
|
||||
return; \
|
||||
} else { minunit_print_progress(); })
|
||||
|
||||
#define mu_assert_int_between(expected_lower, expected_upper, result) \
|
||||
MU__SAFE_BLOCK( \
|
||||
int minunit_tmp_e; int minunit_tmp_m; int minunit_tmp_r; minunit_assert++; \
|
||||
minunit_tmp_e = (expected_lower); \
|
||||
minunit_tmp_m = (expected_upper); \
|
||||
minunit_tmp_r = (result); \
|
||||
if(result < minunit_tmp_e || result > minunit_tmp_m) { \
|
||||
snprintf( \
|
||||
minunit_last_message, \
|
||||
MINUNIT_MESSAGE_LEN, \
|
||||
"%s failed:\r\n\t%s:%d: %d was not between (inclusive) %d and %d", \
|
||||
__func__, \
|
||||
__FILE__, \
|
||||
__LINE__, \
|
||||
minunit_tmp_e, \
|
||||
minunit_tmp_r, \
|
||||
minunit_tmp_m); \
|
||||
minunit_status = 1; \
|
||||
return; \
|
||||
} else { minunit_print_progress(); })
|
||||
|
||||
#define mu_assert_int_in(expected, array_length, result) \
|
||||
MU__SAFE_BLOCK( \
|
||||
int minunit_tmp_r; minunit_assert++; minunit_tmp_r = (result); int t = 0; int i; \
|
||||
for(i = 0; i < array_length; i++) { \
|
||||
if(expected[i] == minunit_tmp_r) t = 1; \
|
||||
} if(t == 0) { \
|
||||
char tmp[500] = {0}; \
|
||||
tmp[0] = '['; \
|
||||
for(i = 0; i < array_length; i++) { \
|
||||
sprintf(tmp + strlen(tmp), "%d, ", expected[i]); \
|
||||
} \
|
||||
int len = strlen(tmp); \
|
||||
tmp[len - 2] = ']'; \
|
||||
tmp[len - 1] = '\0'; \
|
||||
snprintf( \
|
||||
minunit_last_message, \
|
||||
MINUNIT_MESSAGE_LEN, \
|
||||
"%s failed:\r\n\t%s:%d: expected to be one of %s but was %d", \
|
||||
__func__, \
|
||||
__FILE__, \
|
||||
__LINE__, \
|
||||
tmp, \
|
||||
minunit_tmp_r); \
|
||||
minunit_status = 1; \
|
||||
return; \
|
||||
} else { minunit_print_progress(); })
|
||||
|
||||
#define mu_assert_double_eq(expected, result) \
|
||||
MU__SAFE_BLOCK( \
|
||||
double minunit_tmp_e; double minunit_tmp_r; minunit_assert++; minunit_tmp_e = (expected); \
|
||||
minunit_tmp_r = (result); \
|
||||
if(fabs(minunit_tmp_e - minunit_tmp_r) > MINUNIT_EPSILON) { \
|
||||
int minunit_significant_figures = 1 - log10(MINUNIT_EPSILON); \
|
||||
snprintf( \
|
||||
minunit_last_message, \
|
||||
MINUNIT_MESSAGE_LEN, \
|
||||
"%s failed:\r\n\t%s:%d: %.*g expected but was %.*g", \
|
||||
__func__, \
|
||||
__FILE__, \
|
||||
__LINE__, \
|
||||
minunit_significant_figures, \
|
||||
minunit_tmp_e, \
|
||||
minunit_significant_figures, \
|
||||
minunit_tmp_r); \
|
||||
minunit_status = 1; \
|
||||
return; \
|
||||
} else { minunit_print_progress(); })
|
||||
|
||||
#define mu_assert_double_greater_than(val, result) \
|
||||
MU__SAFE_BLOCK( \
|
||||
double minunit_tmp_e; double minunit_tmp_r; minunit_assert++; minunit_tmp_e = (val); \
|
||||
minunit_tmp_r = (result); \
|
||||
if(val >= minunit_tmp_r) { \
|
||||
snprintf( \
|
||||
minunit_last_message, \
|
||||
MINUNIT_MESSAGE_LEN, \
|
||||
"%s failed:\r\n\t%s:%d: %f <= %f", \
|
||||
__func__, \
|
||||
__FILE__, \
|
||||
__LINE__, \
|
||||
minunit_tmp_r, \
|
||||
minunit_tmp_e); \
|
||||
minunit_status = 1; \
|
||||
return; \
|
||||
} else { minunit_print_progress(); })
|
||||
|
||||
#define mu_assert_double_less_than(val, result) \
|
||||
MU__SAFE_BLOCK( \
|
||||
double minunit_tmp_e; double minunit_tmp_r; minunit_assert++; minunit_tmp_e = (val); \
|
||||
minunit_tmp_r = (result); \
|
||||
if(val <= minunit_tmp_r) { \
|
||||
snprintf( \
|
||||
minunit_last_message, \
|
||||
MINUNIT_MESSAGE_LEN, \
|
||||
"%s failed:\r\n\t%s:%d: %f >= %f", \
|
||||
__func__, \
|
||||
__FILE__, \
|
||||
__LINE__, \
|
||||
minunit_tmp_r, \
|
||||
minunit_tmp_e); \
|
||||
minunit_status = 1; \
|
||||
return; \
|
||||
} else { minunit_print_progress(); })
|
||||
|
||||
#define mu_assert_double_between(expected_lower, expected_upper, result) \
|
||||
MU__SAFE_BLOCK( \
|
||||
double minunit_tmp_e; double minunit_tmp_m; double minunit_tmp_r; minunit_assert++; \
|
||||
minunit_tmp_e = (expected_lower); \
|
||||
minunit_tmp_m = (expected_upper); \
|
||||
minunit_tmp_r = (result); \
|
||||
if(result < minunit_tmp_e || result > minunit_tmp_m) { \
|
||||
snprintf( \
|
||||
minunit_last_message, \
|
||||
MINUNIT_MESSAGE_LEN, \
|
||||
"%s failed:\r\n\t%s:%d: %f was not between (inclusive) %f and %f", \
|
||||
__func__, \
|
||||
__FILE__, \
|
||||
__LINE__, \
|
||||
minunit_tmp_e, \
|
||||
minunit_tmp_r, \
|
||||
minunit_tmp_m); \
|
||||
minunit_status = 1; \
|
||||
return; \
|
||||
} else { minunit_print_progress(); })
|
||||
|
||||
#define mu_assert_string_eq(expected, result) \
|
||||
MU__SAFE_BLOCK( \
|
||||
const char* minunit_tmp_e = expected; const char* minunit_tmp_r = result; \
|
||||
minunit_assert++; \
|
||||
if(!minunit_tmp_e) { minunit_tmp_e = "<null pointer>"; } if(!minunit_tmp_r) { \
|
||||
minunit_tmp_r = "<null pointer>"; \
|
||||
} if(strcmp(minunit_tmp_e, minunit_tmp_r)) { \
|
||||
snprintf( \
|
||||
minunit_last_message, \
|
||||
MINUNIT_MESSAGE_LEN, \
|
||||
"%s failed:\r\n\t%s:%d: '%s' expected but was '%s'", \
|
||||
__func__, \
|
||||
__FILE__, \
|
||||
__LINE__, \
|
||||
minunit_tmp_e, \
|
||||
minunit_tmp_r); \
|
||||
minunit_status = 1; \
|
||||
return; \
|
||||
} else { minunit_print_progress(); })
|
||||
|
||||
#define mu_assert_mem_eq(expected, result, size) \
|
||||
MU__SAFE_BLOCK( \
|
||||
const void* minunit_tmp_e = expected; const void* minunit_tmp_r = result; \
|
||||
minunit_assert++; \
|
||||
if(memcmp(minunit_tmp_e, minunit_tmp_r, size)) { \
|
||||
snprintf( \
|
||||
minunit_last_message, \
|
||||
MINUNIT_MESSAGE_LEN, \
|
||||
"%s failed:\r\n\t%s:%d: mem not equal\r\n\tEXP RES", \
|
||||
__func__, \
|
||||
__FILE__, \
|
||||
__LINE__); \
|
||||
for(size_t __index = 0; __index < size; __index++) { \
|
||||
if(strlen(minunit_last_message) > MINUNIT_MESSAGE_LEN - 20) break; \
|
||||
uint8_t __e = ((uint8_t*)minunit_tmp_e)[__index]; \
|
||||
uint8_t __r = ((uint8_t*)minunit_tmp_r)[__index]; \
|
||||
snprintf( \
|
||||
minunit_last_message + strlen(minunit_last_message), \
|
||||
MINUNIT_MESSAGE_LEN - strlen(minunit_last_message), \
|
||||
"\r\n\t%02X %s %02X", \
|
||||
__e, \
|
||||
((__e == __r) ? ".." : "!="), \
|
||||
__r); \
|
||||
} \
|
||||
minunit_status = 1; \
|
||||
return; \
|
||||
} else { minunit_print_progress(); })
|
||||
|
||||
#define mu_assert_null(result) \
|
||||
MU__SAFE_BLOCK( \
|
||||
minunit_assert++; if(result == NULL) { minunit_print_progress(); } else { \
|
||||
snprintf( \
|
||||
minunit_last_message, \
|
||||
MINUNIT_MESSAGE_LEN, \
|
||||
"%s failed:\r\n\t%s:%d: Expected result was not NULL", \
|
||||
__func__, \
|
||||
__FILE__, \
|
||||
__LINE__); \
|
||||
minunit_status = 1; \
|
||||
return; \
|
||||
})
|
||||
|
||||
#define mu_assert_not_null(result) \
|
||||
MU__SAFE_BLOCK( \
|
||||
minunit_assert++; if(result != NULL) { minunit_print_progress(); } else { \
|
||||
snprintf( \
|
||||
minunit_last_message, \
|
||||
MINUNIT_MESSAGE_LEN, \
|
||||
"%s failed:\r\n\t%s:%d: Expected result was not NULL", \
|
||||
__func__, \
|
||||
__FILE__, \
|
||||
__LINE__); \
|
||||
minunit_status = 1; \
|
||||
return; \
|
||||
})
|
||||
|
||||
#define mu_assert_pointers_eq(pointer1, pointer2) \
|
||||
MU__SAFE_BLOCK( \
|
||||
minunit_assert++; if(pointer1 == pointer2) { minunit_print_progress(); } else { \
|
||||
snprintf( \
|
||||
minunit_last_message, \
|
||||
MINUNIT_MESSAGE_LEN, \
|
||||
"%s failed:\r\n\t%s:%d: Expected the pointers to point to the same memory location", \
|
||||
__func__, \
|
||||
__FILE__, \
|
||||
__LINE__); \
|
||||
minunit_status = 1; \
|
||||
return; \
|
||||
})
|
||||
|
||||
#define mu_assert_pointers_not_eq(pointer1, pointer2) \
|
||||
MU__SAFE_BLOCK( \
|
||||
minunit_assert++; if(pointer1 != pointer2) { minunit_print_progress(); } else { \
|
||||
snprintf( \
|
||||
minunit_last_message, \
|
||||
MINUNIT_MESSAGE_LEN, \
|
||||
"%s failed:\r\n\t%s:%d: Expected the pointers to point to the same memory location", \
|
||||
__func__, \
|
||||
__FILE__, \
|
||||
__LINE__); \
|
||||
minunit_status = 1; \
|
||||
return; \
|
||||
})
|
||||
|
||||
/*
|
||||
* The following two functions were written by David Robert Nadeau
|
||||
* from http://NadeauSoftware.com/ and distributed under the
|
||||
* Creative Commons Attribution 3.0 Unported License
|
||||
*/
|
||||
|
||||
/**
|
||||
* Returns the real time, in seconds, or -1.0 if an error occurred.
|
||||
*
|
||||
* Time is measured since an arbitrary and OS-dependent start time.
|
||||
* The returned real time is only useful for computing an elapsed time
|
||||
* between two calls to this function.
|
||||
*/
|
||||
__attribute__((unused)) static double mu_timer_real(void) {
|
||||
#if defined(_WIN32)
|
||||
/* Windows 2000 and later. ---------------------------------- */
|
||||
LARGE_INTEGER Time;
|
||||
LARGE_INTEGER Frequency;
|
||||
|
||||
QueryPerformanceFrequency(&Frequency);
|
||||
QueryPerformanceCounter(&Time);
|
||||
|
||||
Time.QuadPart *= 1000000;
|
||||
Time.QuadPart /= Frequency.QuadPart;
|
||||
|
||||
return (double)Time.QuadPart / 1000000.0;
|
||||
|
||||
#elif(defined(__hpux) || defined(hpux)) || \
|
||||
((defined(__sun__) || defined(__sun) || defined(sun)) && \
|
||||
(defined(__SVR4) || defined(__svr4__)))
|
||||
/* HP-UX, Solaris. ------------------------------------------ */
|
||||
return (double)gethrtime() / 1000000000.0;
|
||||
|
||||
#elif defined(__MACH__) && defined(__APPLE__)
|
||||
/* OSX. ----------------------------------------------------- */
|
||||
static double timeConvert = 0.0;
|
||||
if(timeConvert == 0.0) {
|
||||
mach_timebase_info_data_t timeBase;
|
||||
(void)mach_timebase_info(&timeBase);
|
||||
timeConvert = (double)timeBase.numer / (double)timeBase.denom / 1000000000.0;
|
||||
}
|
||||
return (double)mach_absolute_time() * timeConvert;
|
||||
|
||||
#elif defined(_POSIX_VERSION)
|
||||
/* POSIX. --------------------------------------------------- */
|
||||
struct timeval tm;
|
||||
#if defined(_POSIX_TIMERS) && (_POSIX_TIMERS > 0)
|
||||
{
|
||||
struct timespec ts;
|
||||
#if defined(CLOCK_MONOTONIC_PRECISE)
|
||||
/* BSD. --------------------------------------------- */
|
||||
const clockid_t id = CLOCK_MONOTONIC_PRECISE;
|
||||
#elif defined(CLOCK_MONOTONIC_RAW)
|
||||
/* Linux. ------------------------------------------- */
|
||||
const clockid_t id = CLOCK_MONOTONIC_RAW;
|
||||
#elif defined(CLOCK_HIGHRES)
|
||||
/* Solaris. ----------------------------------------- */
|
||||
const clockid_t id = CLOCK_HIGHRES;
|
||||
#elif defined(CLOCK_MONOTONIC)
|
||||
/* AIX, BSD, Linux, POSIX, Solaris. ----------------- */
|
||||
const clockid_t id = CLOCK_MONOTONIC;
|
||||
#elif defined(CLOCK_REALTIME)
|
||||
/* AIX, BSD, HP-UX, Linux, POSIX. ------------------- */
|
||||
const clockid_t id = CLOCK_REALTIME;
|
||||
#else
|
||||
const clockid_t id = (clockid_t)-1; /* Unknown. */
|
||||
#endif /* CLOCK_* */
|
||||
if(id != (clockid_t)-1 && clock_gettime(id, &ts) != -1)
|
||||
return (double)ts.tv_sec + (double)ts.tv_nsec / 1000000000.0;
|
||||
/* Fall thru. */
|
||||
}
|
||||
#endif /* _POSIX_TIMERS */
|
||||
|
||||
/* AIX, BSD, Cygwin, HP-UX, Linux, OSX, POSIX, Solaris. ----- */
|
||||
gettimeofday(&tm, NULL);
|
||||
return (double)tm.tv_sec + (double)tm.tv_usec / 1000000.0;
|
||||
#else
|
||||
return -1.0; /* Failed. */
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the amount of CPU time used by the current process,
|
||||
* in seconds, or -1.0 if an error occurred.
|
||||
*/
|
||||
__attribute__((unused)) static double mu_timer_cpu(void) {
|
||||
#if defined(_WIN32)
|
||||
/* Windows -------------------------------------------------- */
|
||||
FILETIME createTime;
|
||||
FILETIME exitTime;
|
||||
FILETIME kernelTime;
|
||||
FILETIME userTime;
|
||||
|
||||
/* This approach has a resolution of 1/64 second. Unfortunately, Windows' API does not offer better */
|
||||
if(GetProcessTimes(GetCurrentProcess(), &createTime, &exitTime, &kernelTime, &userTime) != 0) {
|
||||
ULARGE_INTEGER userSystemTime;
|
||||
memcpy(&userSystemTime, &userTime, sizeof(ULARGE_INTEGER));
|
||||
return (double)userSystemTime.QuadPart / 10000000.0;
|
||||
}
|
||||
|
||||
#elif defined(__unix__) || defined(__unix) || defined(unix) || \
|
||||
(defined(__APPLE__) && defined(__MACH__))
|
||||
/* AIX, BSD, Cygwin, HP-UX, Linux, OSX, and Solaris --------- */
|
||||
|
||||
#if defined(_POSIX_TIMERS) && (_POSIX_TIMERS > 0)
|
||||
/* Prefer high-res POSIX timers, when available. */
|
||||
{
|
||||
clockid_t id;
|
||||
struct timespec ts;
|
||||
#if _POSIX_CPUTIME > 0
|
||||
/* Clock ids vary by OS. Query the id, if possible. */
|
||||
if(clock_getcpuclockid(0, &id) == -1)
|
||||
#endif
|
||||
#if defined(CLOCK_PROCESS_CPUTIME_ID)
|
||||
/* Use known clock id for AIX, Linux, or Solaris. */
|
||||
id = CLOCK_PROCESS_CPUTIME_ID;
|
||||
#elif defined(CLOCK_VIRTUAL)
|
||||
/* Use known clock id for BSD or HP-UX. */
|
||||
id = CLOCK_VIRTUAL;
|
||||
#else
|
||||
id = (clockid_t)-1;
|
||||
#endif
|
||||
if(id != (clockid_t)-1 && clock_gettime(id, &ts) != -1)
|
||||
return (double)ts.tv_sec + (double)ts.tv_nsec / 1000000000.0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(RUSAGE_SELF)
|
||||
{
|
||||
struct rusage rusage;
|
||||
if(getrusage(RUSAGE_SELF, &rusage) != -1)
|
||||
return (double)rusage.ru_utime.tv_sec + (double)rusage.ru_utime.tv_usec / 1000000.0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(_SC_CLK_TCK)
|
||||
{
|
||||
const double ticks = (double)sysconf(_SC_CLK_TCK);
|
||||
struct tms tms;
|
||||
if(times(&tms) != (clock_t)-1) return (double)tms.tms_utime / ticks;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(CLOCKS_PER_SEC)
|
||||
{
|
||||
clock_t cl = clock();
|
||||
if(cl != (clock_t)-1) return (double)cl / (double)CLOCKS_PER_SEC;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
return -1; /* Failed. */
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* MINUNIT_MINUNIT_H */
|
15
applications/debug/unit_tests/minunit_vars.h
Normal file
15
applications/debug/unit_tests/minunit_vars.h
Normal file
@@ -0,0 +1,15 @@
|
||||
#pragma once
|
||||
#include "minunit.h"
|
||||
|
||||
/* Misc. counters */
|
||||
int minunit_run = 0;
|
||||
int minunit_assert = 0;
|
||||
int minunit_fail = 0;
|
||||
int minunit_status = 0;
|
||||
|
||||
/* Timers */
|
||||
double minunit_real_timer = 0;
|
||||
double minunit_proc_timer = 0;
|
||||
|
||||
/* Last message */
|
||||
char minunit_last_message[MINUNIT_MESSAGE_LEN];
|
15
applications/debug/unit_tests/minunit_vars_ex.h
Normal file
15
applications/debug/unit_tests/minunit_vars_ex.h
Normal file
@@ -0,0 +1,15 @@
|
||||
#pragma once
|
||||
#include "minunit.h"
|
||||
|
||||
/* Misc. counters */
|
||||
extern int minunit_run;
|
||||
extern int minunit_assert;
|
||||
extern int minunit_fail;
|
||||
extern int minunit_status;
|
||||
|
||||
/* Timers */
|
||||
extern double minunit_real_timer;
|
||||
extern double minunit_proc_timer;
|
||||
|
||||
/* Last message */
|
||||
extern char minunit_last_message[MINUNIT_MESSAGE_LEN];
|
184
applications/debug/unit_tests/nfc/nfc_test.c
Normal file
184
applications/debug/unit_tests/nfc/nfc_test.c
Normal file
@@ -0,0 +1,184 @@
|
||||
#include <furi.h>
|
||||
#include <furi_hal.h>
|
||||
#include <storage/storage.h>
|
||||
#include <lib/flipper_format/flipper_format.h>
|
||||
#include <lib/nfc/protocols/nfca.h>
|
||||
#include <lib/digital_signal/digital_signal.h>
|
||||
|
||||
#include <lib/flipper_format/flipper_format_i.h>
|
||||
#include <lib/toolbox/stream/file_stream.h>
|
||||
|
||||
#include "../minunit.h"
|
||||
|
||||
#define TAG "NfcTest"
|
||||
|
||||
#define NFC_TEST_RESOURCES_DIR EXT_PATH("unit_tests/nfc/")
|
||||
#define NFC_TEST_SIGNAL_SHORT_FILE "nfc_nfca_signal_short.nfc"
|
||||
#define NFC_TEST_SIGNAL_LONG_FILE "nfc_nfca_signal_long.nfc"
|
||||
|
||||
static const char* nfc_test_file_type = "Flipper NFC test";
|
||||
static const uint32_t nfc_test_file_version = 1;
|
||||
|
||||
#define NFC_TEST_DATA_MAX_LEN 18
|
||||
#define NFC_TETS_TIMINGS_MAX_LEN 1350
|
||||
|
||||
typedef struct {
|
||||
Storage* storage;
|
||||
NfcaSignal* signal;
|
||||
uint32_t test_data_len;
|
||||
uint8_t test_data[NFC_TEST_DATA_MAX_LEN];
|
||||
uint32_t test_timings_len;
|
||||
uint32_t test_timings[NFC_TETS_TIMINGS_MAX_LEN];
|
||||
} NfcTest;
|
||||
|
||||
static NfcTest* nfc_test = NULL;
|
||||
|
||||
static void nfc_test_alloc() {
|
||||
nfc_test = malloc(sizeof(NfcTest));
|
||||
nfc_test->signal = nfca_signal_alloc();
|
||||
nfc_test->storage = furi_record_open(RECORD_STORAGE);
|
||||
}
|
||||
|
||||
static void nfc_test_free() {
|
||||
furi_assert(nfc_test);
|
||||
|
||||
furi_record_close(RECORD_STORAGE);
|
||||
nfca_signal_free(nfc_test->signal);
|
||||
free(nfc_test);
|
||||
nfc_test = NULL;
|
||||
}
|
||||
|
||||
static bool nfc_test_read_signal_from_file(const char* file_name) {
|
||||
bool success = false;
|
||||
|
||||
FlipperFormat* file = flipper_format_file_alloc(nfc_test->storage);
|
||||
string_t file_type;
|
||||
string_init(file_type);
|
||||
uint32_t file_version = 0;
|
||||
|
||||
do {
|
||||
if(!flipper_format_file_open_existing(file, file_name)) break;
|
||||
if(!flipper_format_read_header(file, file_type, &file_version)) break;
|
||||
if(string_cmp_str(file_type, nfc_test_file_type) || file_version != nfc_test_file_version)
|
||||
break;
|
||||
if(!flipper_format_read_uint32(file, "Data length", &nfc_test->test_data_len, 1)) break;
|
||||
if(nfc_test->test_data_len > NFC_TEST_DATA_MAX_LEN) break;
|
||||
if(!flipper_format_read_hex(
|
||||
file, "Plain data", nfc_test->test_data, nfc_test->test_data_len))
|
||||
break;
|
||||
if(!flipper_format_read_uint32(file, "Timings length", &nfc_test->test_timings_len, 1))
|
||||
break;
|
||||
if(nfc_test->test_timings_len > NFC_TETS_TIMINGS_MAX_LEN) break;
|
||||
if(!flipper_format_read_uint32(
|
||||
file, "Timings", nfc_test->test_timings, nfc_test->test_timings_len))
|
||||
break;
|
||||
success = true;
|
||||
} while(false);
|
||||
|
||||
string_clear(file_type);
|
||||
flipper_format_free(file);
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
static bool nfc_test_digital_signal_test_encode(
|
||||
const char* file_name,
|
||||
uint32_t encode_max_time,
|
||||
uint32_t timing_tolerance,
|
||||
uint32_t timings_sum_tolerance) {
|
||||
furi_assert(nfc_test);
|
||||
|
||||
bool success = false;
|
||||
uint32_t time = 0;
|
||||
uint32_t dut_timings_sum = 0;
|
||||
uint32_t ref_timings_sum = 0;
|
||||
uint8_t parity[10] = {};
|
||||
|
||||
do {
|
||||
// Read test data
|
||||
if(!nfc_test_read_signal_from_file(file_name)) break;
|
||||
|
||||
// Encode signal
|
||||
FURI_CRITICAL_ENTER();
|
||||
time = DWT->CYCCNT;
|
||||
nfca_signal_encode(
|
||||
nfc_test->signal, nfc_test->test_data, nfc_test->test_data_len * 8, parity);
|
||||
digital_signal_prepare_arr(nfc_test->signal->tx_signal);
|
||||
time = (DWT->CYCCNT - time) / furi_hal_cortex_instructions_per_microsecond();
|
||||
FURI_CRITICAL_EXIT();
|
||||
|
||||
// Check timings
|
||||
if(time > encode_max_time) {
|
||||
FURI_LOG_E(
|
||||
TAG, "Encoding time: %d us while accepted value: %d us", time, encode_max_time);
|
||||
break;
|
||||
}
|
||||
|
||||
// Check data
|
||||
if(nfc_test->signal->tx_signal->edge_cnt != nfc_test->test_timings_len) {
|
||||
FURI_LOG_E(TAG, "Not equal timings buffers length");
|
||||
break;
|
||||
}
|
||||
|
||||
uint32_t timings_diff = 0;
|
||||
uint32_t* ref = nfc_test->test_timings;
|
||||
uint32_t* dut = nfc_test->signal->tx_signal->reload_reg_buff;
|
||||
bool timing_check_success = true;
|
||||
for(size_t i = 0; i < nfc_test->test_timings_len; i++) {
|
||||
timings_diff = dut[i] > ref[i] ? dut[i] - ref[i] : ref[i] - dut[i];
|
||||
dut_timings_sum += dut[i];
|
||||
ref_timings_sum += ref[i];
|
||||
if(timings_diff > timing_tolerance) {
|
||||
FURI_LOG_E(
|
||||
TAG, "Too big differece in %d timings. Ref: %d, DUT: %d", i, ref[i], dut[i]);
|
||||
timing_check_success = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(!timing_check_success) break;
|
||||
uint32_t sum_diff = dut_timings_sum > ref_timings_sum ? dut_timings_sum - ref_timings_sum :
|
||||
ref_timings_sum - dut_timings_sum;
|
||||
if(sum_diff > timings_sum_tolerance) {
|
||||
FURI_LOG_E(
|
||||
TAG,
|
||||
"Too big difference in timings sum. Ref: %d, DUT: %d",
|
||||
ref_timings_sum,
|
||||
dut_timings_sum);
|
||||
break;
|
||||
}
|
||||
|
||||
FURI_LOG_I(TAG, "Encoding time: %d us. Acceptable time: %d us", time, encode_max_time);
|
||||
FURI_LOG_I(
|
||||
TAG,
|
||||
"Timings sum difference: %d [1/64MHZ]. Acceptable difference: %d [1/64MHz]",
|
||||
sum_diff,
|
||||
timings_sum_tolerance);
|
||||
success = true;
|
||||
} while(false);
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
MU_TEST(nfc_digital_signal_test) {
|
||||
mu_assert(
|
||||
nfc_test_digital_signal_test_encode(
|
||||
NFC_TEST_RESOURCES_DIR NFC_TEST_SIGNAL_SHORT_FILE, 500, 1, 37),
|
||||
"NFC short digital signal test failed\r\n");
|
||||
mu_assert(
|
||||
nfc_test_digital_signal_test_encode(
|
||||
NFC_TEST_RESOURCES_DIR NFC_TEST_SIGNAL_LONG_FILE, 2000, 1, 37),
|
||||
"NFC long digital signal test failed\r\n");
|
||||
}
|
||||
|
||||
MU_TEST_SUITE(nfc) {
|
||||
nfc_test_alloc();
|
||||
|
||||
MU_RUN_TEST(nfc_digital_signal_test);
|
||||
|
||||
nfc_test_free();
|
||||
}
|
||||
|
||||
int run_minunit_test_nfc() {
|
||||
MU_RUN_SUITE(nfc);
|
||||
return MU_EXIT_CODE;
|
||||
}
|
222
applications/debug/unit_tests/protocol_dict/protocol_dict_test.c
Normal file
222
applications/debug/unit_tests/protocol_dict/protocol_dict_test.c
Normal file
@@ -0,0 +1,222 @@
|
||||
#include <furi.h>
|
||||
#include "../minunit.h"
|
||||
#include <toolbox/protocols/protocol_dict.h>
|
||||
|
||||
typedef enum {
|
||||
TestDictProtocol0,
|
||||
TestDictProtocol1,
|
||||
|
||||
TestDictProtocolMax,
|
||||
} TestDictProtocols;
|
||||
|
||||
/*********************** PROTOCOL 0 START ***********************/
|
||||
|
||||
typedef struct {
|
||||
uint32_t data;
|
||||
size_t encoder_counter;
|
||||
} Protocol0Data;
|
||||
|
||||
static const uint32_t protocol_0_decoder_result = 0xDEADBEEF;
|
||||
|
||||
static void* protocol_0_alloc() {
|
||||
void* data = malloc(sizeof(Protocol0Data));
|
||||
return data;
|
||||
}
|
||||
|
||||
static void protocol_0_free(Protocol0Data* data) {
|
||||
free(data);
|
||||
}
|
||||
|
||||
static uint8_t* protocol_0_get_data(Protocol0Data* data) {
|
||||
return (uint8_t*)&data->data;
|
||||
}
|
||||
|
||||
static void protocol_0_decoder_start(Protocol0Data* data) {
|
||||
data->data = 0;
|
||||
}
|
||||
|
||||
static bool protocol_0_decoder_feed(Protocol0Data* data, bool level, uint32_t duration) {
|
||||
if(level && duration == 666) {
|
||||
data->data = protocol_0_decoder_result;
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static bool protocol_0_encoder_start(Protocol0Data* data) {
|
||||
data->encoder_counter = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
static LevelDuration protocol_0_encoder_yield(Protocol0Data* data) {
|
||||
data->encoder_counter++;
|
||||
return level_duration_make(data->encoder_counter % 2, data->data);
|
||||
}
|
||||
|
||||
/*********************** PROTOCOL 1 START ***********************/
|
||||
|
||||
typedef struct {
|
||||
uint64_t data;
|
||||
size_t encoder_counter;
|
||||
} Protocol1Data;
|
||||
|
||||
static const uint64_t protocol_1_decoder_result = 0x1234567890ABCDEF;
|
||||
|
||||
static void* protocol_1_alloc() {
|
||||
void* data = malloc(sizeof(Protocol1Data));
|
||||
return data;
|
||||
}
|
||||
|
||||
static void protocol_1_free(Protocol1Data* data) {
|
||||
free(data);
|
||||
}
|
||||
|
||||
static uint8_t* protocol_1_get_data(Protocol1Data* data) {
|
||||
return (uint8_t*)&data->data;
|
||||
}
|
||||
|
||||
static void protocol_1_decoder_start(Protocol1Data* data) {
|
||||
data->data = 0;
|
||||
}
|
||||
|
||||
static bool protocol_1_decoder_feed(Protocol1Data* data, bool level, uint32_t duration) {
|
||||
if(level && duration == 543) {
|
||||
data->data = 0x1234567890ABCDEF;
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static bool protocol_1_encoder_start(Protocol1Data* data) {
|
||||
data->encoder_counter = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
static LevelDuration protocol_1_encoder_yield(Protocol1Data* data) {
|
||||
data->encoder_counter++;
|
||||
return level_duration_make(!(data->encoder_counter % 2), 100);
|
||||
}
|
||||
|
||||
/*********************** PROTOCOLS DESCRIPTION ***********************/
|
||||
static const ProtocolBase protocol_0 = {
|
||||
.name = "Protocol 0",
|
||||
.manufacturer = "Manufacturer 0",
|
||||
.data_size = 4,
|
||||
.alloc = (ProtocolAlloc)protocol_0_alloc,
|
||||
.free = (ProtocolFree)protocol_0_free,
|
||||
.get_data = (ProtocolGetData)protocol_0_get_data,
|
||||
.decoder =
|
||||
{
|
||||
.start = (ProtocolDecoderStart)protocol_0_decoder_start,
|
||||
.feed = (ProtocolDecoderFeed)protocol_0_decoder_feed,
|
||||
},
|
||||
.encoder =
|
||||
{
|
||||
.start = (ProtocolEncoderStart)protocol_0_encoder_start,
|
||||
.yield = (ProtocolEncoderYield)protocol_0_encoder_yield,
|
||||
},
|
||||
};
|
||||
|
||||
static const ProtocolBase protocol_1 = {
|
||||
.name = "Protocol 1",
|
||||
.manufacturer = "Manufacturer 1",
|
||||
.data_size = 8,
|
||||
.alloc = (ProtocolAlloc)protocol_1_alloc,
|
||||
.free = (ProtocolFree)protocol_1_free,
|
||||
.get_data = (ProtocolGetData)protocol_1_get_data,
|
||||
.decoder =
|
||||
{
|
||||
.start = (ProtocolDecoderStart)protocol_1_decoder_start,
|
||||
.feed = (ProtocolDecoderFeed)protocol_1_decoder_feed,
|
||||
},
|
||||
.encoder =
|
||||
{
|
||||
.start = (ProtocolEncoderStart)protocol_1_encoder_start,
|
||||
.yield = (ProtocolEncoderYield)protocol_1_encoder_yield,
|
||||
},
|
||||
};
|
||||
|
||||
static const ProtocolBase* test_protocols_base[] = {
|
||||
[TestDictProtocol0] = &protocol_0,
|
||||
[TestDictProtocol1] = &protocol_1,
|
||||
};
|
||||
|
||||
MU_TEST(test_protocol_dict) {
|
||||
ProtocolDict* dict = protocol_dict_alloc(test_protocols_base, TestDictProtocolMax);
|
||||
size_t max_data_size = protocol_dict_get_max_data_size(dict);
|
||||
mu_assert_int_eq(8, max_data_size);
|
||||
uint8_t* data = malloc(max_data_size);
|
||||
|
||||
protocol_dict_decoders_start(dict);
|
||||
ProtocolId protocol_id = PROTOCOL_NO;
|
||||
|
||||
for(size_t i = 0; i < 100; i++) {
|
||||
protocol_id = protocol_dict_decoders_feed(dict, i % 2, 100);
|
||||
mu_assert_int_eq(PROTOCOL_NO, protocol_id);
|
||||
}
|
||||
|
||||
// trigger protocol 1
|
||||
protocol_id = protocol_dict_decoders_feed(dict, true, 543);
|
||||
mu_assert_int_eq(TestDictProtocol1, protocol_id);
|
||||
|
||||
mu_assert_string_eq("Protocol 1", protocol_dict_get_name(dict, protocol_id));
|
||||
mu_assert_string_eq("Manufacturer 1", protocol_dict_get_manufacturer(dict, protocol_id));
|
||||
|
||||
size_t data_size = protocol_dict_get_data_size(dict, protocol_id);
|
||||
mu_assert_int_eq(8, data_size);
|
||||
|
||||
protocol_dict_get_data(dict, protocol_id, data, data_size);
|
||||
mu_assert_mem_eq(&protocol_1_decoder_result, data, data_size);
|
||||
|
||||
// trigger protocol 0
|
||||
protocol_id = protocol_dict_decoders_feed(dict, true, 666);
|
||||
mu_assert_int_eq(TestDictProtocol0, protocol_id);
|
||||
|
||||
mu_assert_string_eq("Protocol 0", protocol_dict_get_name(dict, protocol_id));
|
||||
mu_assert_string_eq("Manufacturer 0", protocol_dict_get_manufacturer(dict, protocol_id));
|
||||
|
||||
data_size = protocol_dict_get_data_size(dict, protocol_id);
|
||||
mu_assert_int_eq(4, data_size);
|
||||
|
||||
protocol_dict_get_data(dict, protocol_id, data, data_size);
|
||||
mu_assert_mem_eq(&protocol_0_decoder_result, data, data_size);
|
||||
|
||||
protocol_dict_decoders_start(dict);
|
||||
|
||||
protocol_id = TestDictProtocol0;
|
||||
|
||||
const uint8_t protocol_0_test_data[4] = {100, 0, 0, 0};
|
||||
protocol_dict_set_data(dict, protocol_id, protocol_0_test_data, 4);
|
||||
|
||||
mu_check(protocol_dict_encoder_start(dict, protocol_id));
|
||||
|
||||
LevelDuration level;
|
||||
level = protocol_dict_encoder_yield(dict, protocol_id);
|
||||
mu_assert_int_eq(true, level_duration_get_level(level));
|
||||
mu_assert_int_eq(100, level_duration_get_duration(level));
|
||||
level = protocol_dict_encoder_yield(dict, protocol_id);
|
||||
mu_assert_int_eq(false, level_duration_get_level(level));
|
||||
mu_assert_int_eq(100, level_duration_get_duration(level));
|
||||
level = protocol_dict_encoder_yield(dict, protocol_id);
|
||||
mu_assert_int_eq(true, level_duration_get_level(level));
|
||||
mu_assert_int_eq(100, level_duration_get_duration(level));
|
||||
|
||||
mu_check(protocol_dict_encoder_start(dict, protocol_id));
|
||||
level = protocol_dict_encoder_yield(dict, protocol_id);
|
||||
mu_assert_int_eq(true, level_duration_get_level(level));
|
||||
mu_assert_int_eq(100, level_duration_get_duration(level));
|
||||
|
||||
protocol_dict_free(dict);
|
||||
free(data);
|
||||
}
|
||||
|
||||
MU_TEST_SUITE(test_protocol_dict_suite) {
|
||||
MU_RUN_TEST(test_protocol_dict);
|
||||
}
|
||||
|
||||
int run_minunit_test_protocol_dict() {
|
||||
MU_RUN_SUITE(test_protocol_dict_suite);
|
||||
return MU_EXIT_CODE;
|
||||
}
|
1803
applications/debug/unit_tests/rpc/rpc_test.c
Normal file
1803
applications/debug/unit_tests/rpc/rpc_test.c
Normal file
File diff suppressed because it is too large
Load Diff
272
applications/debug/unit_tests/storage/dirwalk_test.c
Normal file
272
applications/debug/unit_tests/storage/dirwalk_test.c
Normal file
@@ -0,0 +1,272 @@
|
||||
#include "../minunit.h"
|
||||
#include <furi.h>
|
||||
#include <m-dict.h>
|
||||
#include <toolbox/dir_walk.h>
|
||||
|
||||
static const char* const storage_test_dirwalk_paths[] = {
|
||||
"1",
|
||||
"11",
|
||||
"111",
|
||||
"1/2",
|
||||
"1/22",
|
||||
"1/222",
|
||||
"11/2",
|
||||
"111/2",
|
||||
"111/22",
|
||||
"111/22/33",
|
||||
};
|
||||
|
||||
static const char* const storage_test_dirwalk_files[] = {
|
||||
"file1.test",
|
||||
"file2.test",
|
||||
"file3.ext_test",
|
||||
"1/file1.test",
|
||||
"111/22/33/file1.test",
|
||||
"111/22/33/file2.test",
|
||||
"111/22/33/file3.ext_test",
|
||||
"111/22/33/file4.ext_test",
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
const char* const path;
|
||||
bool is_dir;
|
||||
} StorageTestPathDesc;
|
||||
|
||||
const StorageTestPathDesc storage_test_dirwalk_full[] = {
|
||||
{.path = "1", .is_dir = true},
|
||||
{.path = "11", .is_dir = true},
|
||||
{.path = "111", .is_dir = true},
|
||||
{.path = "1/2", .is_dir = true},
|
||||
{.path = "1/22", .is_dir = true},
|
||||
{.path = "1/222", .is_dir = true},
|
||||
{.path = "11/2", .is_dir = true},
|
||||
{.path = "111/2", .is_dir = true},
|
||||
{.path = "111/22", .is_dir = true},
|
||||
{.path = "111/22/33", .is_dir = true},
|
||||
{.path = "file1.test", .is_dir = false},
|
||||
{.path = "file2.test", .is_dir = false},
|
||||
{.path = "file3.ext_test", .is_dir = false},
|
||||
{.path = "1/file1.test", .is_dir = false},
|
||||
{.path = "111/22/33/file1.test", .is_dir = false},
|
||||
{.path = "111/22/33/file2.test", .is_dir = false},
|
||||
{.path = "111/22/33/file3.ext_test", .is_dir = false},
|
||||
{.path = "111/22/33/file4.ext_test", .is_dir = false},
|
||||
};
|
||||
|
||||
const StorageTestPathDesc storage_test_dirwalk_no_recursive[] = {
|
||||
{.path = "1", .is_dir = true},
|
||||
{.path = "11", .is_dir = true},
|
||||
{.path = "111", .is_dir = true},
|
||||
{.path = "file1.test", .is_dir = false},
|
||||
{.path = "file2.test", .is_dir = false},
|
||||
{.path = "file3.ext_test", .is_dir = false},
|
||||
};
|
||||
|
||||
const StorageTestPathDesc storage_test_dirwalk_filter[] = {
|
||||
{.path = "file1.test", .is_dir = false},
|
||||
{.path = "file2.test", .is_dir = false},
|
||||
{.path = "1/file1.test", .is_dir = false},
|
||||
{.path = "111/22/33/file1.test", .is_dir = false},
|
||||
{.path = "111/22/33/file2.test", .is_dir = false},
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
bool is_dir;
|
||||
bool visited;
|
||||
} StorageTestPath;
|
||||
|
||||
DICT_DEF2(StorageTestPathDict, string_t, STRING_OPLIST, StorageTestPath, M_POD_OPLIST)
|
||||
|
||||
static StorageTestPathDict_t*
|
||||
storage_test_paths_alloc(const StorageTestPathDesc paths[], size_t paths_count) {
|
||||
StorageTestPathDict_t* data = malloc(sizeof(StorageTestPathDict_t));
|
||||
StorageTestPathDict_init(*data);
|
||||
|
||||
for(size_t i = 0; i < paths_count; i++) {
|
||||
string_t key;
|
||||
string_init_set(key, paths[i].path);
|
||||
StorageTestPath value = {
|
||||
.is_dir = paths[i].is_dir,
|
||||
.visited = false,
|
||||
};
|
||||
|
||||
StorageTestPathDict_set_at(*data, key, value);
|
||||
string_clear(key);
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
static void storage_test_paths_free(StorageTestPathDict_t* data) {
|
||||
StorageTestPathDict_clear(*data);
|
||||
free(data);
|
||||
}
|
||||
|
||||
static bool storage_test_paths_mark(StorageTestPathDict_t* data, string_t path, bool is_dir) {
|
||||
bool found = false;
|
||||
|
||||
StorageTestPath* record = StorageTestPathDict_get(*data, path);
|
||||
if(record) {
|
||||
if(is_dir == record->is_dir) {
|
||||
if(record->visited == false) {
|
||||
record->visited = true;
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return found;
|
||||
}
|
||||
|
||||
static bool storage_test_paths_check(StorageTestPathDict_t* data) {
|
||||
bool error = false;
|
||||
|
||||
StorageTestPathDict_it_t it;
|
||||
for(StorageTestPathDict_it(it, *data); !StorageTestPathDict_end_p(it);
|
||||
StorageTestPathDict_next(it)) {
|
||||
const StorageTestPathDict_itref_t* itref = StorageTestPathDict_cref(it);
|
||||
|
||||
if(itref->value.visited == false) {
|
||||
error = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
static bool write_file_13DA(Storage* storage, const char* path) {
|
||||
File* file = storage_file_alloc(storage);
|
||||
bool result = false;
|
||||
if(storage_file_open(file, path, FSAM_WRITE, FSOM_CREATE_ALWAYS)) {
|
||||
result = storage_file_write(file, "13DA", 4) == 4;
|
||||
}
|
||||
storage_file_close(file);
|
||||
storage_file_free(file);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static void storage_dirs_create(Storage* storage, const char* base) {
|
||||
string_t path;
|
||||
string_init(path);
|
||||
|
||||
storage_common_mkdir(storage, base);
|
||||
|
||||
for(size_t i = 0; i < COUNT_OF(storage_test_dirwalk_paths); i++) {
|
||||
string_printf(path, "%s/%s", base, storage_test_dirwalk_paths[i]);
|
||||
storage_common_mkdir(storage, string_get_cstr(path));
|
||||
}
|
||||
|
||||
for(size_t i = 0; i < COUNT_OF(storage_test_dirwalk_files); i++) {
|
||||
string_printf(path, "%s/%s", base, storage_test_dirwalk_files[i]);
|
||||
write_file_13DA(storage, string_get_cstr(path));
|
||||
}
|
||||
|
||||
string_clear(path);
|
||||
}
|
||||
|
||||
MU_TEST_1(test_dirwalk_full, Storage* storage) {
|
||||
string_t path;
|
||||
string_init(path);
|
||||
FileInfo fileinfo;
|
||||
|
||||
StorageTestPathDict_t* paths =
|
||||
storage_test_paths_alloc(storage_test_dirwalk_full, COUNT_OF(storage_test_dirwalk_full));
|
||||
|
||||
DirWalk* dir_walk = dir_walk_alloc(storage);
|
||||
mu_check(dir_walk_open(dir_walk, EXT_PATH("dirwalk")));
|
||||
|
||||
while(dir_walk_read(dir_walk, path, &fileinfo) == DirWalkOK) {
|
||||
string_right(path, strlen(EXT_PATH("dirwalk/")));
|
||||
mu_check(storage_test_paths_mark(paths, path, (fileinfo.flags & FSF_DIRECTORY)));
|
||||
}
|
||||
|
||||
dir_walk_free(dir_walk);
|
||||
string_clear(path);
|
||||
|
||||
mu_check(storage_test_paths_check(paths) == false);
|
||||
|
||||
storage_test_paths_free(paths);
|
||||
}
|
||||
|
||||
MU_TEST_1(test_dirwalk_no_recursive, Storage* storage) {
|
||||
string_t path;
|
||||
string_init(path);
|
||||
FileInfo fileinfo;
|
||||
|
||||
StorageTestPathDict_t* paths = storage_test_paths_alloc(
|
||||
storage_test_dirwalk_no_recursive, COUNT_OF(storage_test_dirwalk_no_recursive));
|
||||
|
||||
DirWalk* dir_walk = dir_walk_alloc(storage);
|
||||
dir_walk_set_recursive(dir_walk, false);
|
||||
mu_check(dir_walk_open(dir_walk, EXT_PATH("dirwalk")));
|
||||
|
||||
while(dir_walk_read(dir_walk, path, &fileinfo) == DirWalkOK) {
|
||||
string_right(path, strlen(EXT_PATH("dirwalk/")));
|
||||
mu_check(storage_test_paths_mark(paths, path, (fileinfo.flags & FSF_DIRECTORY)));
|
||||
}
|
||||
|
||||
dir_walk_free(dir_walk);
|
||||
string_clear(path);
|
||||
|
||||
mu_check(storage_test_paths_check(paths) == false);
|
||||
|
||||
storage_test_paths_free(paths);
|
||||
}
|
||||
|
||||
static bool test_dirwalk_filter_no_folder_ext(const char* name, FileInfo* fileinfo, void* ctx) {
|
||||
UNUSED(ctx);
|
||||
|
||||
// only files
|
||||
if(!(fileinfo->flags & FSF_DIRECTORY)) {
|
||||
// with ".test" in name
|
||||
if(strstr(name, ".test") != NULL) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
MU_TEST_1(test_dirwalk_filter, Storage* storage) {
|
||||
string_t path;
|
||||
string_init(path);
|
||||
FileInfo fileinfo;
|
||||
|
||||
StorageTestPathDict_t* paths = storage_test_paths_alloc(
|
||||
storage_test_dirwalk_filter, COUNT_OF(storage_test_dirwalk_filter));
|
||||
|
||||
DirWalk* dir_walk = dir_walk_alloc(storage);
|
||||
dir_walk_set_filter_cb(dir_walk, test_dirwalk_filter_no_folder_ext, NULL);
|
||||
mu_check(dir_walk_open(dir_walk, EXT_PATH("dirwalk")));
|
||||
|
||||
while(dir_walk_read(dir_walk, path, &fileinfo) == DirWalkOK) {
|
||||
string_right(path, strlen(EXT_PATH("dirwalk/")));
|
||||
mu_check(storage_test_paths_mark(paths, path, (fileinfo.flags & FSF_DIRECTORY)));
|
||||
}
|
||||
|
||||
dir_walk_free(dir_walk);
|
||||
string_clear(path);
|
||||
|
||||
mu_check(storage_test_paths_check(paths) == false);
|
||||
|
||||
storage_test_paths_free(paths);
|
||||
}
|
||||
|
||||
MU_TEST_SUITE(test_dirwalk_suite) {
|
||||
Storage* storage = furi_record_open(RECORD_STORAGE);
|
||||
storage_dirs_create(storage, EXT_PATH("dirwalk"));
|
||||
|
||||
MU_RUN_TEST_1(test_dirwalk_full, storage);
|
||||
MU_RUN_TEST_1(test_dirwalk_no_recursive, storage);
|
||||
MU_RUN_TEST_1(test_dirwalk_filter, storage);
|
||||
|
||||
storage_simply_remove_recursive(storage, EXT_PATH("dirwalk"));
|
||||
furi_record_close(RECORD_STORAGE);
|
||||
}
|
||||
|
||||
int run_minunit_test_dirwalk() {
|
||||
MU_RUN_SUITE(test_dirwalk_suite);
|
||||
return MU_EXIT_CODE;
|
||||
}
|
317
applications/debug/unit_tests/storage/storage_test.c
Normal file
317
applications/debug/unit_tests/storage/storage_test.c
Normal file
@@ -0,0 +1,317 @@
|
||||
#include "../minunit.h"
|
||||
#include <furi.h>
|
||||
#include <storage/storage.h>
|
||||
|
||||
#define STORAGE_LOCKED_FILE EXT_PATH("locked_file.test")
|
||||
#define STORAGE_LOCKED_DIR STORAGE_INT_PATH_PREFIX
|
||||
|
||||
static void storage_file_open_lock_setup() {
|
||||
Storage* storage = furi_record_open(RECORD_STORAGE);
|
||||
File* file = storage_file_alloc(storage);
|
||||
storage_simply_remove(storage, STORAGE_LOCKED_FILE);
|
||||
mu_check(storage_file_open(file, STORAGE_LOCKED_FILE, FSAM_WRITE, FSOM_CREATE_NEW));
|
||||
mu_check(storage_file_write(file, "0123", 4) == 4);
|
||||
mu_check(storage_file_close(file));
|
||||
storage_file_free(file);
|
||||
furi_record_close(RECORD_STORAGE);
|
||||
}
|
||||
|
||||
static void storage_file_open_lock_teardown() {
|
||||
Storage* storage = furi_record_open(RECORD_STORAGE);
|
||||
mu_check(storage_simply_remove(storage, STORAGE_LOCKED_FILE));
|
||||
furi_record_close(RECORD_STORAGE);
|
||||
}
|
||||
|
||||
static int32_t storage_file_locker(void* ctx) {
|
||||
Storage* storage = furi_record_open(RECORD_STORAGE);
|
||||
FuriSemaphore* semaphore = ctx;
|
||||
File* file = storage_file_alloc(storage);
|
||||
furi_check(storage_file_open(file, STORAGE_LOCKED_FILE, FSAM_READ_WRITE, FSOM_OPEN_EXISTING));
|
||||
furi_semaphore_release(semaphore);
|
||||
furi_delay_ms(1000);
|
||||
|
||||
furi_check(storage_file_close(file));
|
||||
furi_record_close(RECORD_STORAGE);
|
||||
storage_file_free(file);
|
||||
return 0;
|
||||
}
|
||||
|
||||
MU_TEST(storage_file_open_lock) {
|
||||
Storage* storage = furi_record_open(RECORD_STORAGE);
|
||||
bool result = false;
|
||||
FuriSemaphore* semaphore = furi_semaphore_alloc(1, 0);
|
||||
File* file = storage_file_alloc(storage);
|
||||
|
||||
// file_locker thread start
|
||||
FuriThread* locker_thread = furi_thread_alloc();
|
||||
furi_thread_set_name(locker_thread, "StorageFileLocker");
|
||||
furi_thread_set_stack_size(locker_thread, 2048);
|
||||
furi_thread_set_context(locker_thread, semaphore);
|
||||
furi_thread_set_callback(locker_thread, storage_file_locker);
|
||||
furi_thread_start(locker_thread);
|
||||
|
||||
// wait for file lock
|
||||
furi_semaphore_acquire(semaphore, FuriWaitForever);
|
||||
furi_semaphore_free(semaphore);
|
||||
|
||||
result = storage_file_open(file, STORAGE_LOCKED_FILE, FSAM_READ_WRITE, FSOM_OPEN_EXISTING);
|
||||
storage_file_close(file);
|
||||
|
||||
// file_locker thread stop
|
||||
mu_check(furi_thread_join(locker_thread) == FuriStatusOk);
|
||||
furi_thread_free(locker_thread);
|
||||
|
||||
// clean data
|
||||
storage_file_free(file);
|
||||
furi_record_close(RECORD_STORAGE);
|
||||
|
||||
mu_assert(result, "cannot open locked file");
|
||||
}
|
||||
|
||||
MU_TEST(storage_file_open_close) {
|
||||
Storage* storage = furi_record_open(RECORD_STORAGE);
|
||||
File* file;
|
||||
|
||||
file = storage_file_alloc(storage);
|
||||
mu_check(storage_file_open(file, STORAGE_LOCKED_FILE, FSAM_READ_WRITE, FSOM_OPEN_EXISTING));
|
||||
storage_file_close(file);
|
||||
storage_file_free(file);
|
||||
|
||||
for(size_t i = 0; i < 10; i++) {
|
||||
file = storage_file_alloc(storage);
|
||||
mu_check(
|
||||
storage_file_open(file, STORAGE_LOCKED_FILE, FSAM_READ_WRITE, FSOM_OPEN_EXISTING));
|
||||
storage_file_free(file);
|
||||
}
|
||||
|
||||
furi_record_close(RECORD_STORAGE);
|
||||
}
|
||||
|
||||
MU_TEST_SUITE(storage_file) {
|
||||
storage_file_open_lock_setup();
|
||||
MU_RUN_TEST(storage_file_open_close);
|
||||
MU_RUN_TEST(storage_file_open_lock);
|
||||
storage_file_open_lock_teardown();
|
||||
}
|
||||
|
||||
MU_TEST(storage_dir_open_close) {
|
||||
Storage* storage = furi_record_open(RECORD_STORAGE);
|
||||
File* file;
|
||||
|
||||
file = storage_file_alloc(storage);
|
||||
mu_check(storage_dir_open(file, STORAGE_LOCKED_DIR));
|
||||
storage_dir_close(file);
|
||||
storage_file_free(file);
|
||||
|
||||
for(size_t i = 0; i < 10; i++) {
|
||||
file = storage_file_alloc(storage);
|
||||
mu_check(storage_dir_open(file, STORAGE_LOCKED_DIR));
|
||||
storage_file_free(file);
|
||||
}
|
||||
|
||||
furi_record_close(RECORD_STORAGE);
|
||||
}
|
||||
|
||||
static int32_t storage_dir_locker(void* ctx) {
|
||||
Storage* storage = furi_record_open(RECORD_STORAGE);
|
||||
FuriSemaphore* semaphore = ctx;
|
||||
File* file = storage_file_alloc(storage);
|
||||
furi_check(storage_dir_open(file, STORAGE_LOCKED_DIR));
|
||||
furi_semaphore_release(semaphore);
|
||||
furi_delay_ms(1000);
|
||||
|
||||
furi_check(storage_dir_close(file));
|
||||
furi_record_close(RECORD_STORAGE);
|
||||
storage_file_free(file);
|
||||
return 0;
|
||||
}
|
||||
|
||||
MU_TEST(storage_dir_open_lock) {
|
||||
Storage* storage = furi_record_open(RECORD_STORAGE);
|
||||
bool result = false;
|
||||
FuriSemaphore* semaphore = furi_semaphore_alloc(1, 0);
|
||||
File* file = storage_file_alloc(storage);
|
||||
|
||||
// file_locker thread start
|
||||
FuriThread* locker_thread = furi_thread_alloc();
|
||||
furi_thread_set_name(locker_thread, "StorageDirLocker");
|
||||
furi_thread_set_stack_size(locker_thread, 2048);
|
||||
furi_thread_set_context(locker_thread, semaphore);
|
||||
furi_thread_set_callback(locker_thread, storage_dir_locker);
|
||||
furi_thread_start(locker_thread);
|
||||
|
||||
// wait for dir lock
|
||||
furi_semaphore_acquire(semaphore, FuriWaitForever);
|
||||
furi_semaphore_free(semaphore);
|
||||
|
||||
result = storage_dir_open(file, STORAGE_LOCKED_DIR);
|
||||
storage_dir_close(file);
|
||||
|
||||
// file_locker thread stop
|
||||
mu_check(furi_thread_join(locker_thread) == FuriStatusOk);
|
||||
furi_thread_free(locker_thread);
|
||||
|
||||
// clean data
|
||||
storage_file_free(file);
|
||||
furi_record_close(RECORD_STORAGE);
|
||||
|
||||
mu_assert(result, "cannot open locked dir");
|
||||
}
|
||||
|
||||
MU_TEST_SUITE(storage_dir) {
|
||||
MU_RUN_TEST(storage_dir_open_close);
|
||||
MU_RUN_TEST(storage_dir_open_lock);
|
||||
}
|
||||
|
||||
static const char* const storage_copy_test_paths[] = {
|
||||
"1",
|
||||
"11",
|
||||
"111",
|
||||
"1/2",
|
||||
"1/22",
|
||||
"1/222",
|
||||
"11/1",
|
||||
"111/2",
|
||||
"111/22",
|
||||
"111/22/33",
|
||||
};
|
||||
|
||||
static const char* const storage_copy_test_files[] = {
|
||||
"file.test",
|
||||
"1/file.test",
|
||||
"111/22/33/file.test",
|
||||
};
|
||||
|
||||
static bool write_file_13DA(Storage* storage, const char* path) {
|
||||
File* file = storage_file_alloc(storage);
|
||||
bool result = false;
|
||||
if(storage_file_open(file, path, FSAM_WRITE, FSOM_CREATE_ALWAYS)) {
|
||||
result = storage_file_write(file, "13DA", 4) == 4;
|
||||
}
|
||||
storage_file_close(file);
|
||||
storage_file_free(file);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static bool check_file_13DA(Storage* storage, const char* path) {
|
||||
File* file = storage_file_alloc(storage);
|
||||
bool result = false;
|
||||
if(storage_file_open(file, path, FSAM_READ, FSOM_OPEN_EXISTING)) {
|
||||
char data[10] = {0};
|
||||
result = storage_file_read(file, data, 4) == 4;
|
||||
if(result) {
|
||||
result = memcmp(data, "13DA", 4) == 0;
|
||||
}
|
||||
}
|
||||
storage_file_close(file);
|
||||
storage_file_free(file);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static void storage_dir_create(Storage* storage, const char* base) {
|
||||
string_t path;
|
||||
string_init(path);
|
||||
|
||||
storage_common_mkdir(storage, base);
|
||||
|
||||
for(size_t i = 0; i < COUNT_OF(storage_copy_test_paths); i++) {
|
||||
string_printf(path, "%s/%s", base, storage_copy_test_paths[i]);
|
||||
storage_common_mkdir(storage, string_get_cstr(path));
|
||||
}
|
||||
|
||||
for(size_t i = 0; i < COUNT_OF(storage_copy_test_files); i++) {
|
||||
string_printf(path, "%s/%s", base, storage_copy_test_files[i]);
|
||||
write_file_13DA(storage, string_get_cstr(path));
|
||||
}
|
||||
|
||||
string_clear(path);
|
||||
}
|
||||
|
||||
static void storage_dir_remove(Storage* storage, const char* base) {
|
||||
storage_simply_remove_recursive(storage, base);
|
||||
}
|
||||
|
||||
static bool storage_dir_rename_check(Storage* storage, const char* base) {
|
||||
bool result = false;
|
||||
string_t path;
|
||||
string_init(path);
|
||||
|
||||
result = (storage_common_stat(storage, base, NULL) == FSE_OK);
|
||||
|
||||
if(result) {
|
||||
for(size_t i = 0; i < COUNT_OF(storage_copy_test_paths); i++) {
|
||||
string_printf(path, "%s/%s", base, storage_copy_test_paths[i]);
|
||||
result = (storage_common_stat(storage, string_get_cstr(path), NULL) == FSE_OK);
|
||||
if(!result) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(result) {
|
||||
for(size_t i = 0; i < COUNT_OF(storage_copy_test_files); i++) {
|
||||
string_printf(path, "%s/%s", base, storage_copy_test_files[i]);
|
||||
result = check_file_13DA(storage, string_get_cstr(path));
|
||||
if(!result) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
string_clear(path);
|
||||
return result;
|
||||
}
|
||||
|
||||
MU_TEST(storage_file_rename) {
|
||||
Storage* storage = furi_record_open(RECORD_STORAGE);
|
||||
File* file = storage_file_alloc(storage);
|
||||
|
||||
mu_check(write_file_13DA(storage, EXT_PATH("file.old")));
|
||||
mu_check(check_file_13DA(storage, EXT_PATH("file.old")));
|
||||
mu_assert_int_eq(
|
||||
FSE_OK, storage_common_rename(storage, EXT_PATH("file.old"), EXT_PATH("file.new")));
|
||||
mu_assert_int_eq(FSE_NOT_EXIST, storage_common_stat(storage, EXT_PATH("file.old"), NULL));
|
||||
mu_assert_int_eq(FSE_OK, storage_common_stat(storage, EXT_PATH("file.new"), NULL));
|
||||
mu_check(check_file_13DA(storage, EXT_PATH("file.new")));
|
||||
mu_assert_int_eq(FSE_OK, storage_common_remove(storage, EXT_PATH("file.new")));
|
||||
|
||||
storage_file_free(file);
|
||||
furi_record_close(RECORD_STORAGE);
|
||||
}
|
||||
|
||||
MU_TEST(storage_dir_rename) {
|
||||
Storage* storage = furi_record_open(RECORD_STORAGE);
|
||||
|
||||
storage_dir_create(storage, EXT_PATH("dir.old"));
|
||||
|
||||
mu_check(storage_dir_rename_check(storage, EXT_PATH("dir.old")));
|
||||
|
||||
mu_assert_int_eq(
|
||||
FSE_OK, storage_common_rename(storage, EXT_PATH("dir.old"), EXT_PATH("dir.new")));
|
||||
mu_assert_int_eq(FSE_NOT_EXIST, storage_common_stat(storage, EXT_PATH("dir.old"), NULL));
|
||||
mu_check(storage_dir_rename_check(storage, EXT_PATH("dir.new")));
|
||||
|
||||
storage_dir_remove(storage, EXT_PATH("dir.new"));
|
||||
mu_assert_int_eq(FSE_NOT_EXIST, storage_common_stat(storage, EXT_PATH("dir.new"), NULL));
|
||||
|
||||
furi_record_close(RECORD_STORAGE);
|
||||
}
|
||||
|
||||
MU_TEST_SUITE(storage_rename) {
|
||||
MU_RUN_TEST(storage_file_rename);
|
||||
MU_RUN_TEST(storage_dir_rename);
|
||||
|
||||
Storage* storage = furi_record_open(RECORD_STORAGE);
|
||||
storage_dir_remove(storage, EXT_PATH("dir.old"));
|
||||
storage_dir_remove(storage, EXT_PATH("dir.new"));
|
||||
furi_record_close(RECORD_STORAGE);
|
||||
}
|
||||
|
||||
int run_minunit_test_storage() {
|
||||
MU_RUN_SUITE(storage_file);
|
||||
MU_RUN_SUITE(storage_dir);
|
||||
MU_RUN_SUITE(storage_rename);
|
||||
return MU_EXIT_CODE;
|
||||
}
|
508
applications/debug/unit_tests/stream/stream_test.c
Normal file
508
applications/debug/unit_tests/stream/stream_test.c
Normal file
@@ -0,0 +1,508 @@
|
||||
#include <furi.h>
|
||||
#include <toolbox/stream/stream.h>
|
||||
#include <toolbox/stream/string_stream.h>
|
||||
#include <toolbox/stream/file_stream.h>
|
||||
#include <toolbox/stream/buffered_file_stream.h>
|
||||
#include <storage/storage.h>
|
||||
#include "../minunit.h"
|
||||
|
||||
static const char* stream_test_data = "I write differently from what I speak, "
|
||||
"I speak differently from what I think, "
|
||||
"I think differently from the way I ought to think, "
|
||||
"and so it all proceeds into deepest darkness.";
|
||||
|
||||
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.";
|
||||
|
||||
MU_TEST_1(stream_composite_subtest, Stream* stream) {
|
||||
const size_t data_size = 128;
|
||||
uint8_t data[data_size];
|
||||
string_t string_lee;
|
||||
string_init_set(string_lee, "lee");
|
||||
|
||||
// test that stream is empty
|
||||
// "" -> ""
|
||||
mu_check(stream_size(stream) == 0);
|
||||
mu_check(stream_eof(stream));
|
||||
mu_check(stream_tell(stream) == 0);
|
||||
mu_check(stream_read(stream, data, data_size) == 0);
|
||||
mu_check(stream_eof(stream));
|
||||
mu_check(stream_tell(stream) == 0);
|
||||
|
||||
// write char
|
||||
// "" -> "2"
|
||||
mu_check(stream_write_char(stream, '2') == 1);
|
||||
mu_check(stream_size(stream) == 1);
|
||||
mu_check(stream_tell(stream) == 1);
|
||||
mu_check(stream_eof(stream));
|
||||
|
||||
// test rewind and eof
|
||||
stream_rewind(stream);
|
||||
mu_check(stream_size(stream) == 1);
|
||||
mu_check(stream_tell(stream) == 0);
|
||||
mu_check(!stream_eof(stream));
|
||||
|
||||
// add another char with replacement
|
||||
// "2" -> "1"
|
||||
mu_check(stream_write_char(stream, '1') == 1);
|
||||
mu_check(stream_size(stream) == 1);
|
||||
mu_check(stream_tell(stream) == 1);
|
||||
mu_check(stream_eof(stream));
|
||||
|
||||
// write string
|
||||
// "1" -> "1337_69"
|
||||
mu_check(stream_write_cstring(stream, "337_69") == 6);
|
||||
mu_check(stream_size(stream) == 7);
|
||||
mu_check(stream_tell(stream) == 7);
|
||||
mu_check(stream_eof(stream));
|
||||
|
||||
// read data
|
||||
memset(data, 0, data_size);
|
||||
stream_rewind(stream);
|
||||
mu_check(stream_read(stream, data, data_size) == 7);
|
||||
mu_check(strcmp((char*)data, "1337_69") == 0);
|
||||
|
||||
// test misc seeks
|
||||
mu_check(stream_seek(stream, 2, StreamOffsetFromStart));
|
||||
mu_check(stream_tell(stream) == 2);
|
||||
mu_check(!stream_seek(stream, 9000, StreamOffsetFromStart));
|
||||
mu_check(stream_tell(stream) == 7);
|
||||
mu_check(stream_eof(stream));
|
||||
mu_check(stream_seek(stream, -3, StreamOffsetFromEnd));
|
||||
mu_check(stream_tell(stream) == 4);
|
||||
|
||||
// write string with replacemet
|
||||
// "1337_69" -> "1337lee"
|
||||
mu_check(stream_write_string(stream, string_lee) == 3);
|
||||
mu_check(stream_size(stream) == 7);
|
||||
mu_check(stream_tell(stream) == 7);
|
||||
mu_check(stream_eof(stream));
|
||||
|
||||
// append char
|
||||
// "1337lee" -> "1337leet"
|
||||
mu_check(stream_write(stream, (uint8_t*)"t", 1) == 1);
|
||||
mu_check(stream_size(stream) == 8);
|
||||
mu_check(stream_tell(stream) == 8);
|
||||
mu_check(stream_eof(stream));
|
||||
|
||||
// read data
|
||||
memset(data, 0, data_size);
|
||||
stream_rewind(stream);
|
||||
mu_check(stream_read(stream, data, data_size) == 8);
|
||||
mu_check(strcmp((char*)data, "1337leet") == 0);
|
||||
mu_check(stream_tell(stream) == 8);
|
||||
mu_check(stream_eof(stream));
|
||||
|
||||
// negative seek from current position -> clamp to 0
|
||||
mu_check(!stream_seek(stream, -9000, StreamOffsetFromCurrent));
|
||||
mu_check(stream_tell(stream) == 0);
|
||||
|
||||
// negative seek from start position -> clamp to 0
|
||||
stream_rewind(stream);
|
||||
mu_check(!stream_seek(stream, -3, StreamOffsetFromStart));
|
||||
mu_check(stream_tell(stream) == 0);
|
||||
|
||||
// zero seek from current position -> clamp to stream size
|
||||
mu_check(stream_seek(stream, 0, StreamOffsetFromEnd));
|
||||
mu_check(stream_tell(stream) == 8);
|
||||
|
||||
// negative seek from end position -> clamp to 0
|
||||
mu_check(!stream_seek(stream, -9000, StreamOffsetFromEnd));
|
||||
mu_check(stream_tell(stream) == 0);
|
||||
|
||||
// clean stream
|
||||
stream_clean(stream);
|
||||
mu_check(stream_size(stream) == 0);
|
||||
mu_check(stream_eof(stream));
|
||||
mu_check(stream_tell(stream) == 0);
|
||||
|
||||
// write format
|
||||
// "" -> "dio666"
|
||||
mu_check(stream_write_format(stream, "%s%d", "dio", 666) == 6);
|
||||
mu_check(stream_size(stream) == 6);
|
||||
mu_check(stream_eof(stream));
|
||||
mu_check(stream_tell(stream) == 6);
|
||||
|
||||
// read data
|
||||
memset(data, 0, data_size);
|
||||
stream_rewind(stream);
|
||||
mu_check(stream_read(stream, data, data_size) == 6);
|
||||
mu_check(strcmp((char*)data, "dio666") == 0);
|
||||
|
||||
// clean and write cstring
|
||||
// "dio666" -> "" -> "1234567890"
|
||||
stream_clean(stream);
|
||||
mu_check(stream_write_cstring(stream, "1234567890") == 10);
|
||||
|
||||
// delete 4 bytes from 1 pos
|
||||
// "1xxxx67890" -> "167890"
|
||||
mu_check(stream_seek(stream, 1, StreamOffsetFromStart));
|
||||
mu_check(stream_delete(stream, 4));
|
||||
mu_assert_int_eq(6, stream_size(stream));
|
||||
|
||||
// read data
|
||||
memset(data, 0, data_size);
|
||||
stream_rewind(stream);
|
||||
mu_assert_int_eq(6, stream_read(stream, data, data_size));
|
||||
mu_check(strcmp((char*)data, "167890") == 0);
|
||||
|
||||
// write cstring
|
||||
// "167890" -> "167890It Was Me, Dio!"
|
||||
mu_check(stream_write_cstring(stream, "It Was Me, Dio!") == 15);
|
||||
|
||||
// delete 1337 bytes from 1 pos
|
||||
// and check that we can delete only 20 bytes
|
||||
// "1xxxxxxxxxxxxxxxxxxxx" -> "1"
|
||||
mu_check(stream_seek(stream, 1, StreamOffsetFromStart));
|
||||
mu_check(stream_delete(stream, 1337));
|
||||
mu_assert_int_eq(1, stream_size(stream));
|
||||
|
||||
// read data
|
||||
memset(data, 0, data_size);
|
||||
stream_rewind(stream);
|
||||
mu_check(stream_read(stream, data, data_size) == 1);
|
||||
mu_check(strcmp((char*)data, "1") == 0);
|
||||
|
||||
// write cstring from 0 pos, replacing 1 byte
|
||||
// "1" -> "Oh? You're roaching me?"
|
||||
mu_check(stream_rewind(stream));
|
||||
mu_assert_int_eq(23, stream_write_cstring(stream, "Oh? You're roaching me?"));
|
||||
|
||||
// insert 11 bytes to 0 pos
|
||||
// "Oh? You're roaching me?" -> "Za Warudo! Oh? You're roaching me?"
|
||||
mu_check(stream_rewind(stream));
|
||||
mu_check(stream_insert(stream, (uint8_t*)"Za Warudo! ", 11));
|
||||
mu_assert_int_eq(34, stream_size(stream));
|
||||
|
||||
// read data
|
||||
memset(data, 0, data_size);
|
||||
stream_rewind(stream);
|
||||
mu_assert_int_eq(34, stream_read(stream, data, data_size));
|
||||
mu_assert_string_eq("Za Warudo! Oh? You're roaching me?", (char*)data);
|
||||
|
||||
// insert cstring to 22 pos
|
||||
// "Za Warudo! Oh? You're roaching me?" -> "Za Warudo! Oh? You're approaching me?"
|
||||
mu_check(stream_seek(stream, 22, StreamOffsetFromStart));
|
||||
mu_check(stream_insert_cstring(stream, "app"));
|
||||
mu_assert_int_eq(37, stream_size(stream));
|
||||
|
||||
// read data
|
||||
memset(data, 0, data_size);
|
||||
stream_rewind(stream);
|
||||
mu_assert_int_eq(37, stream_read(stream, data, data_size));
|
||||
mu_assert_string_eq("Za Warudo! Oh? You're approaching me?", (char*)data);
|
||||
|
||||
// insert cstring to the end of the stream
|
||||
// "Za Warudo! Oh? You're approaching me?" -> "Za Warudo! Oh? You're approaching me? It was me, Dio!"
|
||||
mu_check(stream_seek(stream, 0, StreamOffsetFromEnd));
|
||||
mu_check(stream_insert_cstring(stream, " It was me, Dio!"));
|
||||
mu_assert_int_eq(53, stream_size(stream));
|
||||
|
||||
// read data
|
||||
memset(data, 0, data_size);
|
||||
stream_rewind(stream);
|
||||
mu_assert_int_eq(53, stream_read(stream, data, data_size));
|
||||
mu_assert_string_eq("Za Warudo! Oh? You're approaching me? It was me, Dio!", (char*)data);
|
||||
|
||||
// delete 168430090 bytes from stream
|
||||
// and test that we can delete only 53
|
||||
mu_check(stream_rewind(stream));
|
||||
mu_check(stream_delete(stream, 0x0A0A0A0A));
|
||||
mu_assert_int_eq(0, stream_size(stream));
|
||||
mu_check(stream_eof(stream));
|
||||
mu_assert_int_eq(0, stream_tell(stream));
|
||||
|
||||
// clean stream
|
||||
stream_clean(stream);
|
||||
mu_assert_int_eq(0, stream_size(stream));
|
||||
mu_check(stream_eof(stream));
|
||||
mu_assert_int_eq(0, stream_tell(stream));
|
||||
|
||||
// insert formated string at the end of stream
|
||||
// "" -> "dio666"
|
||||
mu_check(stream_insert_format(stream, "%s%d", "dio", 666));
|
||||
mu_assert_int_eq(6, stream_size(stream));
|
||||
mu_check(stream_eof(stream));
|
||||
mu_assert_int_eq(6, stream_tell(stream));
|
||||
|
||||
// insert formated string at the end of stream
|
||||
// "dio666" -> "dio666zlo555"
|
||||
mu_check(stream_insert_format(stream, "%s%d", "zlo", 555));
|
||||
mu_assert_int_eq(12, stream_size(stream));
|
||||
mu_check(stream_eof(stream));
|
||||
mu_assert_int_eq(12, stream_tell(stream));
|
||||
|
||||
// insert formated string at the 6 pos
|
||||
// "dio666" -> "dio666baba13zlo555"
|
||||
mu_check(stream_seek(stream, 6, StreamOffsetFromStart));
|
||||
mu_check(stream_insert_format(stream, "%s%d", "baba", 13));
|
||||
mu_assert_int_eq(18, stream_size(stream));
|
||||
mu_assert_int_eq(12, stream_tell(stream));
|
||||
|
||||
// read data
|
||||
memset(data, 0, data_size);
|
||||
stream_rewind(stream);
|
||||
mu_assert_int_eq(18, stream_read(stream, data, data_size));
|
||||
mu_assert_string_eq("dio666baba13zlo555", (char*)data);
|
||||
|
||||
// delete 6 chars from pos 6 and insert 1 chars
|
||||
// "dio666baba13zlo555" -> "dio666xzlo555"
|
||||
mu_check(stream_seek(stream, 6, StreamOffsetFromStart));
|
||||
mu_check(stream_delete_and_insert_char(stream, 6, 'x'));
|
||||
mu_assert_int_eq(13, stream_size(stream));
|
||||
mu_assert_int_eq(7, stream_tell(stream));
|
||||
|
||||
// read data
|
||||
memset(data, 0, data_size);
|
||||
stream_rewind(stream);
|
||||
mu_check(stream_read(stream, data, data_size) == 13);
|
||||
mu_assert_string_eq("dio666xzlo555", (char*)data);
|
||||
|
||||
// delete 9000 chars from pos 6 and insert 3 chars from string
|
||||
// "dio666xzlo555" -> "dio666777"
|
||||
mu_check(stream_seek(stream, 6, StreamOffsetFromStart));
|
||||
mu_check(stream_delete_and_insert_cstring(stream, 9000, "777"));
|
||||
mu_assert_int_eq(9, stream_size(stream));
|
||||
mu_assert_int_eq(9, stream_tell(stream));
|
||||
mu_check(stream_eof(stream));
|
||||
|
||||
string_clear(string_lee);
|
||||
}
|
||||
|
||||
MU_TEST(stream_composite_test) {
|
||||
// test string stream
|
||||
Stream* stream;
|
||||
stream = string_stream_alloc();
|
||||
MU_RUN_TEST_1(stream_composite_subtest, stream);
|
||||
stream_free(stream);
|
||||
|
||||
// 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_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_RUN_TEST_1(stream_composite_subtest, stream);
|
||||
stream_free(stream);
|
||||
furi_record_close(RECORD_STORAGE);
|
||||
}
|
||||
|
||||
MU_TEST_1(stream_write_subtest, Stream* stream) {
|
||||
mu_assert_int_eq(strlen(stream_test_data), stream_write_cstring(stream, stream_test_data));
|
||||
}
|
||||
|
||||
MU_TEST_1(stream_read_subtest, Stream* stream) {
|
||||
uint8_t data[256] = {0};
|
||||
mu_check(stream_rewind(stream));
|
||||
mu_assert_int_eq(strlen(stream_test_data), stream_read(stream, data, 256));
|
||||
mu_assert_string_eq(stream_test_data, (const char*)data);
|
||||
}
|
||||
|
||||
MU_TEST(stream_write_read_save_load_test) {
|
||||
Stream* stream_orig = string_stream_alloc();
|
||||
Stream* stream_copy = string_stream_alloc();
|
||||
Storage* storage = furi_record_open(RECORD_STORAGE);
|
||||
|
||||
// write, read
|
||||
MU_RUN_TEST_1(stream_write_subtest, stream_orig);
|
||||
MU_RUN_TEST_1(stream_read_subtest, stream_orig);
|
||||
|
||||
// copy, read
|
||||
mu_assert_int_eq(strlen(stream_test_data), stream_copy_full(stream_orig, stream_copy));
|
||||
MU_RUN_TEST_1(stream_read_subtest, stream_orig);
|
||||
|
||||
// save to file
|
||||
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_free(stream_copy);
|
||||
stream_free(stream_orig);
|
||||
|
||||
// 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")));
|
||||
MU_RUN_TEST_1(stream_read_subtest, stream_new);
|
||||
stream_free(stream_new);
|
||||
|
||||
furi_record_close(RECORD_STORAGE);
|
||||
}
|
||||
|
||||
MU_TEST_1(stream_split_subtest, Stream* stream) {
|
||||
stream_clean(stream);
|
||||
stream_write_cstring(stream, stream_test_left_data);
|
||||
stream_write_cstring(stream, stream_test_right_data);
|
||||
|
||||
Stream* stream_left = string_stream_alloc();
|
||||
Stream* stream_right = string_stream_alloc();
|
||||
|
||||
mu_check(stream_seek(stream, strlen(stream_test_left_data), StreamOffsetFromStart));
|
||||
mu_check(stream_split(stream, stream_left, stream_right));
|
||||
|
||||
uint8_t data[256] = {0};
|
||||
mu_check(stream_rewind(stream_left));
|
||||
mu_assert_int_eq(strlen(stream_test_left_data), stream_read(stream_left, data, 256));
|
||||
mu_assert_string_eq(stream_test_left_data, (const char*)data);
|
||||
|
||||
mu_check(stream_rewind(stream_right));
|
||||
mu_assert_int_eq(strlen(stream_test_right_data), stream_read(stream_right, data, 256));
|
||||
mu_assert_string_eq(stream_test_right_data, (const char*)data);
|
||||
|
||||
stream_free(stream_right);
|
||||
stream_free(stream_left);
|
||||
}
|
||||
|
||||
MU_TEST(stream_split_test) {
|
||||
// test string stream
|
||||
Stream* stream;
|
||||
stream = string_stream_alloc();
|
||||
MU_RUN_TEST_1(stream_split_subtest, stream);
|
||||
stream_free(stream);
|
||||
|
||||
// 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_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_RUN_TEST_1(stream_split_subtest, stream);
|
||||
stream_free(stream);
|
||||
|
||||
furi_record_close(RECORD_STORAGE);
|
||||
}
|
||||
|
||||
MU_TEST(stream_buffered_write_after_read_test) {
|
||||
const char* prefix = "I write ";
|
||||
const char* substr = "Hello there";
|
||||
|
||||
const size_t substr_len = strlen(substr);
|
||||
const size_t prefix_len = strlen(prefix);
|
||||
const size_t buf_size = substr_len + 1;
|
||||
|
||||
char buf[buf_size];
|
||||
memset(buf, 0, buf_size);
|
||||
|
||||
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_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));
|
||||
mu_assert_string_eq(prefix, buf);
|
||||
mu_assert_int_eq(substr_len, stream_write(stream, (uint8_t*)substr, substr_len));
|
||||
mu_check(stream_seek(stream, prefix_len, StreamOffsetFromStart));
|
||||
mu_assert_int_eq(substr_len, stream_read(stream, (uint8_t*)buf, substr_len));
|
||||
mu_assert_string_eq(substr, buf);
|
||||
|
||||
stream_free(stream);
|
||||
furi_record_close(RECORD_STORAGE);
|
||||
}
|
||||
|
||||
MU_TEST(stream_buffered_large_file_test) {
|
||||
string_t input_data;
|
||||
string_t output_data;
|
||||
string_init(input_data);
|
||||
string_init(output_data);
|
||||
|
||||
Storage* storage = furi_record_open(RECORD_STORAGE);
|
||||
|
||||
// generate test data consisting of several identical lines
|
||||
const size_t data_size = 4096;
|
||||
const size_t line_size = strlen(stream_test_data);
|
||||
const size_t rep_count = data_size / line_size + 1;
|
||||
|
||||
for(size_t i = 0; i < rep_count; ++i) {
|
||||
string_cat_printf(input_data, "%s\n", stream_test_data);
|
||||
}
|
||||
|
||||
// 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_assert_int_eq(0, stream_size(stream));
|
||||
mu_assert_int_eq(string_size(input_data), stream_write_string(stream, input_data));
|
||||
mu_assert_int_eq(string_size(input_data), stream_size(stream));
|
||||
|
||||
const size_t substr_start = 8;
|
||||
const size_t substr_len = 11;
|
||||
|
||||
mu_check(stream_seek(stream, substr_start, StreamOffsetFromStart));
|
||||
mu_assert_int_eq(substr_start, stream_tell(stream));
|
||||
|
||||
// copy one substring from test data
|
||||
char test_substr[substr_len + 1];
|
||||
memset(test_substr, 0, substr_len + 1);
|
||||
memcpy(test_substr, stream_test_data + substr_start, substr_len);
|
||||
|
||||
char buf[substr_len + 1];
|
||||
memset(buf, 0, substr_len + 1);
|
||||
|
||||
// read substring
|
||||
mu_assert_int_eq(substr_len, stream_read(stream, (uint8_t*)buf, substr_len));
|
||||
mu_assert_string_eq(test_substr, buf);
|
||||
memset(buf, 0, substr_len + 1);
|
||||
|
||||
// forward seek to cause a cache miss
|
||||
mu_check(stream_seek(
|
||||
stream, (line_size + 1) * (rep_count - 1) - substr_len, StreamOffsetFromCurrent));
|
||||
// read same substring from a different line
|
||||
mu_assert_int_eq(substr_len, stream_read(stream, (uint8_t*)buf, substr_len));
|
||||
mu_assert_string_eq(test_substr, buf);
|
||||
memset(buf, 0, substr_len + 1);
|
||||
|
||||
// backward seek to cause a cache miss
|
||||
mu_check(stream_seek(
|
||||
stream, -((line_size + 1) * (rep_count - 1) + substr_len), StreamOffsetFromCurrent));
|
||||
mu_assert_int_eq(substr_len, stream_read(stream, (uint8_t*)buf, substr_len));
|
||||
mu_assert_string_eq(test_substr, buf);
|
||||
|
||||
// read the whole file
|
||||
mu_check(stream_rewind(stream));
|
||||
string_t tmp;
|
||||
string_init(tmp);
|
||||
while(stream_read_line(stream, tmp)) {
|
||||
string_cat(output_data, tmp);
|
||||
}
|
||||
string_clear(tmp);
|
||||
|
||||
// check against generated data
|
||||
mu_assert_int_eq(string_size(input_data), string_size(output_data));
|
||||
mu_check(string_equal_p(input_data, output_data));
|
||||
mu_check(stream_eof(stream));
|
||||
|
||||
stream_free(stream);
|
||||
|
||||
furi_record_close(RECORD_STORAGE);
|
||||
string_clear(input_data);
|
||||
string_clear(output_data);
|
||||
}
|
||||
|
||||
MU_TEST_SUITE(stream_suite) {
|
||||
MU_RUN_TEST(stream_write_read_save_load_test);
|
||||
MU_RUN_TEST(stream_composite_test);
|
||||
MU_RUN_TEST(stream_split_test);
|
||||
MU_RUN_TEST(stream_buffered_write_after_read_test);
|
||||
MU_RUN_TEST(stream_buffered_large_file_test);
|
||||
}
|
||||
|
||||
int run_minunit_test_stream() {
|
||||
MU_RUN_SUITE(stream_suite);
|
||||
return MU_EXIT_CODE;
|
||||
}
|
627
applications/debug/unit_tests/subghz/subghz_test.c
Normal file
627
applications/debug/unit_tests/subghz/subghz_test.c
Normal file
@@ -0,0 +1,627 @@
|
||||
#include <furi.h>
|
||||
#include <furi_hal.h>
|
||||
#include "../minunit.h"
|
||||
#include <lib/subghz/receiver.h>
|
||||
#include <lib/subghz/transmitter.h>
|
||||
#include <lib/subghz/subghz_keystore.h>
|
||||
#include <lib/subghz/subghz_file_encoder_worker.h>
|
||||
#include <lib/subghz/protocols/registry.h>
|
||||
#include <flipper_format/flipper_format_i.h>
|
||||
|
||||
#define TAG "SubGhz TEST"
|
||||
#define KEYSTORE_DIR_NAME EXT_PATH("subghz/assets/keeloq_mfcodes")
|
||||
#define CAME_ATOMO_DIR_NAME EXT_PATH("subghz/assets/came_atomo")
|
||||
#define NICE_FLOR_S_DIR_NAME EXT_PATH("subghz/assets/nice_flor_s")
|
||||
#define TEST_RANDOM_DIR_NAME EXT_PATH("unit_tests/subghz/test_random_raw.sub")
|
||||
#define TEST_RANDOM_COUNT_PARSE 232
|
||||
#define TEST_TIMEOUT 10000
|
||||
|
||||
static SubGhzEnvironment* environment_handler;
|
||||
static SubGhzReceiver* receiver_handler;
|
||||
//static SubGhzTransmitter* transmitter_handler;
|
||||
static SubGhzFileEncoderWorker* file_worker_encoder_handler;
|
||||
static uint16_t subghz_test_decoder_count = 0;
|
||||
|
||||
static void subghz_test_rx_callback(
|
||||
SubGhzReceiver* receiver,
|
||||
SubGhzProtocolDecoderBase* decoder_base,
|
||||
void* context) {
|
||||
UNUSED(receiver);
|
||||
UNUSED(context);
|
||||
string_t text;
|
||||
string_init(text);
|
||||
subghz_protocol_decoder_base_get_string(decoder_base, text);
|
||||
subghz_receiver_reset(receiver_handler);
|
||||
FURI_LOG_T(TAG, "\r\n%s", string_get_cstr(text));
|
||||
string_clear(text);
|
||||
subghz_test_decoder_count++;
|
||||
}
|
||||
|
||||
static void subghz_test_init(void) {
|
||||
environment_handler = subghz_environment_alloc();
|
||||
subghz_environment_set_came_atomo_rainbow_table_file_name(
|
||||
environment_handler, CAME_ATOMO_DIR_NAME);
|
||||
subghz_environment_set_nice_flor_s_rainbow_table_file_name(
|
||||
environment_handler, NICE_FLOR_S_DIR_NAME);
|
||||
|
||||
receiver_handler = subghz_receiver_alloc_init(environment_handler);
|
||||
subghz_receiver_set_filter(receiver_handler, SubGhzProtocolFlag_Decodable);
|
||||
subghz_receiver_set_rx_callback(receiver_handler, subghz_test_rx_callback, NULL);
|
||||
}
|
||||
|
||||
static void subghz_test_deinit(void) {
|
||||
subghz_receiver_free(receiver_handler);
|
||||
subghz_environment_free(environment_handler);
|
||||
}
|
||||
|
||||
static bool subghz_decoder_test(const char* path, const char* name_decoder) {
|
||||
subghz_test_decoder_count = 0;
|
||||
uint32_t test_start = furi_get_tick();
|
||||
|
||||
SubGhzProtocolDecoderBase* decoder =
|
||||
subghz_receiver_search_decoder_base_by_name(receiver_handler, name_decoder);
|
||||
|
||||
if(decoder) {
|
||||
file_worker_encoder_handler = subghz_file_encoder_worker_alloc();
|
||||
if(subghz_file_encoder_worker_start(file_worker_encoder_handler, path)) {
|
||||
// the worker needs a file in order to open and read part of the file
|
||||
furi_delay_ms(100);
|
||||
|
||||
LevelDuration level_duration;
|
||||
while(furi_get_tick() - test_start < TEST_TIMEOUT) {
|
||||
level_duration =
|
||||
subghz_file_encoder_worker_get_level_duration(file_worker_encoder_handler);
|
||||
if(!level_duration_is_reset(level_duration)) {
|
||||
bool level = level_duration_get_level(level_duration);
|
||||
uint32_t duration = level_duration_get_duration(level_duration);
|
||||
// Yield, to load data inside the worker
|
||||
furi_thread_yield();
|
||||
decoder->protocol->decoder->feed(decoder, level, duration);
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
furi_delay_ms(10);
|
||||
}
|
||||
if(subghz_file_encoder_worker_is_running(file_worker_encoder_handler)) {
|
||||
subghz_file_encoder_worker_stop(file_worker_encoder_handler);
|
||||
}
|
||||
subghz_file_encoder_worker_free(file_worker_encoder_handler);
|
||||
}
|
||||
FURI_LOG_T(TAG, "\r\n Decoder count parse \033[0;33m%d\033[0m ", subghz_test_decoder_count);
|
||||
if(furi_get_tick() - test_start > TEST_TIMEOUT) {
|
||||
printf("\033[0;31mTest decoder %s ERROR TimeOut\033[0m\r\n", name_decoder);
|
||||
return false;
|
||||
} else {
|
||||
return subghz_test_decoder_count ? true : false;
|
||||
}
|
||||
}
|
||||
|
||||
static bool subghz_decode_random_test(const char* path) {
|
||||
subghz_test_decoder_count = 0;
|
||||
subghz_receiver_reset(receiver_handler);
|
||||
uint32_t test_start = furi_get_tick();
|
||||
|
||||
file_worker_encoder_handler = subghz_file_encoder_worker_alloc();
|
||||
if(subghz_file_encoder_worker_start(file_worker_encoder_handler, path)) {
|
||||
// the worker needs a file in order to open and read part of the file
|
||||
furi_delay_ms(100);
|
||||
|
||||
LevelDuration level_duration;
|
||||
while(furi_get_tick() - test_start < TEST_TIMEOUT * 10) {
|
||||
level_duration =
|
||||
subghz_file_encoder_worker_get_level_duration(file_worker_encoder_handler);
|
||||
if(!level_duration_is_reset(level_duration)) {
|
||||
bool level = level_duration_get_level(level_duration);
|
||||
uint32_t duration = level_duration_get_duration(level_duration);
|
||||
// Yield, to load data inside the worker
|
||||
furi_thread_yield();
|
||||
subghz_receiver_decode(receiver_handler, level, duration);
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
furi_delay_ms(10);
|
||||
if(subghz_file_encoder_worker_is_running(file_worker_encoder_handler)) {
|
||||
subghz_file_encoder_worker_stop(file_worker_encoder_handler);
|
||||
}
|
||||
subghz_file_encoder_worker_free(file_worker_encoder_handler);
|
||||
}
|
||||
FURI_LOG_D(TAG, "\r\n Decoder count parse \033[0;33m%d\033[0m ", subghz_test_decoder_count);
|
||||
if(furi_get_tick() - test_start > TEST_TIMEOUT * 10) {
|
||||
printf("\033[0;31mRandom test ERROR TimeOut\033[0m\r\n");
|
||||
return false;
|
||||
} else if(subghz_test_decoder_count == TEST_RANDOM_COUNT_PARSE) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static bool subghz_encoder_test(const char* path) {
|
||||
subghz_test_decoder_count = 0;
|
||||
uint32_t test_start = furi_get_tick();
|
||||
string_t temp_str;
|
||||
string_init(temp_str);
|
||||
bool file_load = false;
|
||||
|
||||
Storage* storage = furi_record_open(RECORD_STORAGE);
|
||||
FlipperFormat* fff_data_file = flipper_format_file_alloc(storage);
|
||||
|
||||
do {
|
||||
if(!flipper_format_file_open_existing(fff_data_file, path)) {
|
||||
FURI_LOG_E(TAG, "Error open file %s", path);
|
||||
break;
|
||||
}
|
||||
|
||||
if(!flipper_format_read_string(fff_data_file, "Preset", temp_str)) {
|
||||
FURI_LOG_E(TAG, "Missing Preset");
|
||||
break;
|
||||
}
|
||||
|
||||
if(!flipper_format_read_string(fff_data_file, "Protocol", temp_str)) {
|
||||
FURI_LOG_E(TAG, "Missing Protocol");
|
||||
break;
|
||||
}
|
||||
file_load = true;
|
||||
} while(false);
|
||||
if(file_load) {
|
||||
SubGhzTransmitter* transmitter =
|
||||
subghz_transmitter_alloc_init(environment_handler, string_get_cstr(temp_str));
|
||||
subghz_transmitter_deserialize(transmitter, fff_data_file);
|
||||
|
||||
SubGhzProtocolDecoderBase* decoder = subghz_receiver_search_decoder_base_by_name(
|
||||
receiver_handler, string_get_cstr(temp_str));
|
||||
|
||||
if(decoder) {
|
||||
LevelDuration level_duration;
|
||||
while(furi_get_tick() - test_start < TEST_TIMEOUT) {
|
||||
level_duration = subghz_transmitter_yield(transmitter);
|
||||
if(!level_duration_is_reset(level_duration)) {
|
||||
bool level = level_duration_get_level(level_duration);
|
||||
uint32_t duration = level_duration_get_duration(level_duration);
|
||||
decoder->protocol->decoder->feed(decoder, level, duration);
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
furi_delay_ms(10);
|
||||
}
|
||||
subghz_transmitter_free(transmitter);
|
||||
}
|
||||
flipper_format_free(fff_data_file);
|
||||
FURI_LOG_T(TAG, "\r\n Decoder count parse \033[0;33m%d\033[0m ", subghz_test_decoder_count);
|
||||
if(furi_get_tick() - test_start > TEST_TIMEOUT) {
|
||||
printf("\033[0;31mTest encoder %s ERROR TimeOut\033[0m\r\n", string_get_cstr(temp_str));
|
||||
subghz_test_decoder_count = 0;
|
||||
}
|
||||
string_clear(temp_str);
|
||||
|
||||
return subghz_test_decoder_count ? true : false;
|
||||
}
|
||||
|
||||
MU_TEST(subghz_keystore_test) {
|
||||
mu_assert(
|
||||
subghz_environment_load_keystore(environment_handler, KEYSTORE_DIR_NAME),
|
||||
"Test keystore error");
|
||||
}
|
||||
|
||||
//test decoders
|
||||
MU_TEST(subghz_decoder_came_atomo_test) {
|
||||
mu_assert(
|
||||
subghz_decoder_test(
|
||||
EXT_PATH("unit_tests/subghz/came_atomo_raw.sub"), SUBGHZ_PROTOCOL_CAME_ATOMO_NAME),
|
||||
"Test decoder " SUBGHZ_PROTOCOL_CAME_ATOMO_NAME " error\r\n");
|
||||
}
|
||||
|
||||
MU_TEST(subghz_decoder_came_test) {
|
||||
mu_assert(
|
||||
subghz_decoder_test(EXT_PATH("unit_tests/subghz/came_raw.sub"), SUBGHZ_PROTOCOL_CAME_NAME),
|
||||
"Test decoder " SUBGHZ_PROTOCOL_CAME_NAME " error\r\n");
|
||||
}
|
||||
|
||||
MU_TEST(subghz_decoder_came_twee_test) {
|
||||
mu_assert(
|
||||
subghz_decoder_test(
|
||||
EXT_PATH("unit_tests/subghz/came_twee_raw.sub"), SUBGHZ_PROTOCOL_CAME_TWEE_NAME),
|
||||
"Test decoder " SUBGHZ_PROTOCOL_CAME_TWEE_NAME " error\r\n");
|
||||
}
|
||||
|
||||
MU_TEST(subghz_decoder_faac_slh_test) {
|
||||
mu_assert(
|
||||
subghz_decoder_test(
|
||||
EXT_PATH("unit_tests/subghz/faac_slh_raw.sub"), SUBGHZ_PROTOCOL_FAAC_SLH_NAME),
|
||||
"Test decoder " SUBGHZ_PROTOCOL_FAAC_SLH_NAME " error\r\n");
|
||||
}
|
||||
|
||||
MU_TEST(subghz_decoder_gate_tx_test) {
|
||||
mu_assert(
|
||||
subghz_decoder_test(
|
||||
EXT_PATH("unit_tests/subghz/gate_tx_raw.sub"), SUBGHZ_PROTOCOL_GATE_TX_NAME),
|
||||
"Test decoder " SUBGHZ_PROTOCOL_GATE_TX_NAME " error\r\n");
|
||||
}
|
||||
|
||||
MU_TEST(subghz_decoder_hormann_hsm_test) {
|
||||
mu_assert(
|
||||
subghz_decoder_test(
|
||||
EXT_PATH("unit_tests/subghz/hormann_hsm_raw.sub"), SUBGHZ_PROTOCOL_HORMANN_HSM_NAME),
|
||||
"Test decoder " SUBGHZ_PROTOCOL_HORMANN_HSM_NAME " error\r\n");
|
||||
}
|
||||
|
||||
MU_TEST(subghz_decoder_ido_test) {
|
||||
mu_assert(
|
||||
subghz_decoder_test(
|
||||
EXT_PATH("unit_tests/subghz/ido_117_111_raw.sub"), SUBGHZ_PROTOCOL_IDO_NAME),
|
||||
"Test decoder " SUBGHZ_PROTOCOL_IDO_NAME " error\r\n");
|
||||
}
|
||||
|
||||
MU_TEST(subghz_decoder_keelog_test) {
|
||||
mu_assert(
|
||||
subghz_decoder_test(
|
||||
EXT_PATH("unit_tests/subghz/doorhan_raw.sub"), SUBGHZ_PROTOCOL_KEELOQ_NAME),
|
||||
"Test decoder " SUBGHZ_PROTOCOL_KEELOQ_NAME " error\r\n");
|
||||
}
|
||||
|
||||
MU_TEST(subghz_decoder_kia_seed_test) {
|
||||
mu_assert(
|
||||
subghz_decoder_test(
|
||||
EXT_PATH("unit_tests/subghz/kia_seed_raw.sub"), SUBGHZ_PROTOCOL_KIA_NAME),
|
||||
"Test decoder " SUBGHZ_PROTOCOL_KIA_NAME " error\r\n");
|
||||
}
|
||||
|
||||
MU_TEST(subghz_decoder_nero_radio_test) {
|
||||
mu_assert(
|
||||
subghz_decoder_test(
|
||||
EXT_PATH("unit_tests/subghz/nero_radio_raw.sub"), SUBGHZ_PROTOCOL_NERO_RADIO_NAME),
|
||||
"Test decoder " SUBGHZ_PROTOCOL_NERO_RADIO_NAME " error\r\n");
|
||||
}
|
||||
|
||||
MU_TEST(subghz_decoder_nero_sketch_test) {
|
||||
mu_assert(
|
||||
subghz_decoder_test(
|
||||
EXT_PATH("unit_tests/subghz/nero_sketch_raw.sub"), SUBGHZ_PROTOCOL_NERO_SKETCH_NAME),
|
||||
"Test decoder " SUBGHZ_PROTOCOL_NERO_SKETCH_NAME " error\r\n");
|
||||
}
|
||||
|
||||
MU_TEST(subghz_decoder_nice_flo_test) {
|
||||
mu_assert(
|
||||
subghz_decoder_test(
|
||||
EXT_PATH("unit_tests/subghz/nice_flo_raw.sub"), SUBGHZ_PROTOCOL_NICE_FLO_NAME),
|
||||
"Test decoder " SUBGHZ_PROTOCOL_NICE_FLO_NAME " error\r\n");
|
||||
}
|
||||
|
||||
MU_TEST(subghz_decoder_nice_flor_s_test) {
|
||||
mu_assert(
|
||||
subghz_decoder_test(
|
||||
EXT_PATH("unit_tests/subghz/nice_flor_s_raw.sub"), SUBGHZ_PROTOCOL_NICE_FLOR_S_NAME),
|
||||
"Test decoder " SUBGHZ_PROTOCOL_NICE_FLOR_S_NAME " error\r\n");
|
||||
}
|
||||
|
||||
MU_TEST(subghz_decoder_princeton_test) {
|
||||
mu_assert(
|
||||
subghz_decoder_test(
|
||||
EXT_PATH("unit_tests/subghz/Princeton_raw.sub"), SUBGHZ_PROTOCOL_PRINCETON_NAME),
|
||||
"Test decoder " SUBGHZ_PROTOCOL_PRINCETON_NAME " error\r\n");
|
||||
}
|
||||
|
||||
MU_TEST(subghz_decoder_scher_khan_magic_code_test) {
|
||||
mu_assert(
|
||||
subghz_decoder_test(
|
||||
EXT_PATH("unit_tests/subghz/scher_khan_magic_code.sub"),
|
||||
SUBGHZ_PROTOCOL_SCHER_KHAN_NAME),
|
||||
"Test decoder " SUBGHZ_PROTOCOL_SCHER_KHAN_NAME " error\r\n");
|
||||
}
|
||||
|
||||
MU_TEST(subghz_decoder_somfy_keytis_test) {
|
||||
mu_assert(
|
||||
subghz_decoder_test(
|
||||
EXT_PATH("unit_tests/subghz/Somfy_keytis_raw.sub"), SUBGHZ_PROTOCOL_SOMFY_KEYTIS_NAME),
|
||||
"Test decoder " SUBGHZ_PROTOCOL_SOMFY_KEYTIS_NAME " error\r\n");
|
||||
}
|
||||
|
||||
MU_TEST(subghz_decoder_somfy_telis_test) {
|
||||
mu_assert(
|
||||
subghz_decoder_test(
|
||||
EXT_PATH("unit_tests/subghz/somfy_telis_raw.sub"), SUBGHZ_PROTOCOL_SOMFY_TELIS_NAME),
|
||||
"Test decoder " SUBGHZ_PROTOCOL_SOMFY_TELIS_NAME " error\r\n");
|
||||
}
|
||||
|
||||
MU_TEST(subghz_decoder_star_line_test) {
|
||||
mu_assert(
|
||||
subghz_decoder_test(
|
||||
EXT_PATH("unit_tests/subghz/cenmax_raw.sub"), SUBGHZ_PROTOCOL_STAR_LINE_NAME),
|
||||
"Test decoder " SUBGHZ_PROTOCOL_STAR_LINE_NAME " error\r\n");
|
||||
}
|
||||
|
||||
MU_TEST(subghz_decoder_linear_test) {
|
||||
mu_assert(
|
||||
subghz_decoder_test(
|
||||
EXT_PATH("unit_tests/subghz/linear_raw.sub"), SUBGHZ_PROTOCOL_LINEAR_NAME),
|
||||
"Test decoder " SUBGHZ_PROTOCOL_LINEAR_NAME " error\r\n");
|
||||
}
|
||||
|
||||
MU_TEST(subghz_decoder_megacode_test) {
|
||||
mu_assert(
|
||||
subghz_decoder_test(
|
||||
EXT_PATH("unit_tests/subghz/megacode_raw.sub"), SUBGHZ_PROTOCOL_MEGACODE_NAME),
|
||||
"Test decoder " SUBGHZ_PROTOCOL_MEGACODE_NAME " error\r\n");
|
||||
}
|
||||
|
||||
MU_TEST(subghz_decoder_secplus_v1_test) {
|
||||
mu_assert(
|
||||
subghz_decoder_test(
|
||||
EXT_PATH("unit_tests/subghz/security_pls_1_0_raw.sub"),
|
||||
SUBGHZ_PROTOCOL_SECPLUS_V1_NAME),
|
||||
"Test decoder " SUBGHZ_PROTOCOL_SECPLUS_V1_NAME " error\r\n");
|
||||
}
|
||||
|
||||
MU_TEST(subghz_decoder_secplus_v2_test) {
|
||||
mu_assert(
|
||||
subghz_decoder_test(
|
||||
EXT_PATH("unit_tests/subghz/security_pls_2_0_raw.sub"),
|
||||
SUBGHZ_PROTOCOL_SECPLUS_V2_NAME),
|
||||
"Test decoder " SUBGHZ_PROTOCOL_SECPLUS_V2_NAME " error\r\n");
|
||||
}
|
||||
|
||||
MU_TEST(subghz_decoder_holtek_test) {
|
||||
mu_assert(
|
||||
subghz_decoder_test(
|
||||
EXT_PATH("unit_tests/subghz/holtek_raw.sub"), SUBGHZ_PROTOCOL_HOLTEK_NAME),
|
||||
"Test decoder " SUBGHZ_PROTOCOL_HOLTEK_NAME " error\r\n");
|
||||
}
|
||||
|
||||
MU_TEST(subghz_decoder_power_smart_test) {
|
||||
mu_assert(
|
||||
subghz_decoder_test(
|
||||
EXT_PATH("unit_tests/subghz/power_smart_raw.sub"), SUBGHZ_PROTOCOL_POWER_SMART_NAME),
|
||||
"Test decoder " SUBGHZ_PROTOCOL_POWER_SMART_NAME " error\r\n");
|
||||
}
|
||||
|
||||
MU_TEST(subghz_decoder_marantec_test) {
|
||||
mu_assert(
|
||||
subghz_decoder_test(
|
||||
EXT_PATH("unit_tests/subghz/marantec_raw.sub"), SUBGHZ_PROTOCOL_MARANTEC_NAME),
|
||||
"Test decoder " SUBGHZ_PROTOCOL_MARANTEC_NAME " error\r\n");
|
||||
}
|
||||
|
||||
MU_TEST(subghz_decoder_bett_test) {
|
||||
mu_assert(
|
||||
subghz_decoder_test(EXT_PATH("unit_tests/subghz/bett_raw.sub"), SUBGHZ_PROTOCOL_BETT_NAME),
|
||||
"Test decoder " SUBGHZ_PROTOCOL_BETT_NAME " error\r\n");
|
||||
}
|
||||
|
||||
MU_TEST(subghz_decoder_doitrand_test) {
|
||||
mu_assert(
|
||||
subghz_decoder_test(
|
||||
EXT_PATH("unit_tests/subghz/doitrand_raw.sub"), SUBGHZ_PROTOCOL_DOITRAND_NAME),
|
||||
"Test decoder " SUBGHZ_PROTOCOL_DOITRAND_NAME " error\r\n");
|
||||
}
|
||||
|
||||
MU_TEST(subghz_decoder_phoenix_v2_test) {
|
||||
mu_assert(
|
||||
subghz_decoder_test(
|
||||
EXT_PATH("unit_tests/subghz/phoenix_v2_raw.sub"), SUBGHZ_PROTOCOL_PHOENIX_V2_NAME),
|
||||
"Test decoder " SUBGHZ_PROTOCOL_PHOENIX_V2_NAME " error\r\n");
|
||||
}
|
||||
|
||||
MU_TEST(subghz_decoder_honeywell_wdb_test) {
|
||||
mu_assert(
|
||||
subghz_decoder_test(
|
||||
EXT_PATH("unit_tests/subghz/honeywell_wdb_raw.sub"),
|
||||
SUBGHZ_PROTOCOL_HONEYWELL_WDB_NAME),
|
||||
"Test decoder " SUBGHZ_PROTOCOL_HONEYWELL_WDB_NAME " error\r\n");
|
||||
}
|
||||
|
||||
MU_TEST(subghz_decoder_magellen_test) {
|
||||
mu_assert(
|
||||
subghz_decoder_test(
|
||||
EXT_PATH("unit_tests/subghz/magellen_raw.sub"), SUBGHZ_PROTOCOL_MAGELLEN_NAME),
|
||||
"Test decoder " SUBGHZ_PROTOCOL_MAGELLEN_NAME " error\r\n");
|
||||
}
|
||||
|
||||
MU_TEST(subghz_decoder_intertechno_v3_test) {
|
||||
mu_assert(
|
||||
subghz_decoder_test(
|
||||
EXT_PATH("unit_tests/subghz/intertechno_v3_raw.sub"),
|
||||
SUBGHZ_PROTOCOL_INTERTECHNO_V3_NAME),
|
||||
"Test decoder " SUBGHZ_PROTOCOL_INTERTECHNO_V3_NAME " error\r\n");
|
||||
}
|
||||
|
||||
MU_TEST(subghz_decoder_clemsa_test) {
|
||||
mu_assert(
|
||||
subghz_decoder_test(
|
||||
EXT_PATH("unit_tests/subghz/clemsa_raw.sub"), SUBGHZ_PROTOCOL_CLEMSA_NAME),
|
||||
"Test decoder " SUBGHZ_PROTOCOL_CLEMSA_NAME " error\r\n");
|
||||
}
|
||||
|
||||
//test encoders
|
||||
MU_TEST(subghz_encoder_princeton_test) {
|
||||
mu_assert(
|
||||
subghz_encoder_test(EXT_PATH("unit_tests/subghz/princeton.sub")),
|
||||
"Test encoder " SUBGHZ_PROTOCOL_PRINCETON_NAME " error\r\n");
|
||||
}
|
||||
|
||||
MU_TEST(subghz_encoder_came_test) {
|
||||
mu_assert(
|
||||
subghz_encoder_test(EXT_PATH("unit_tests/subghz/came.sub")),
|
||||
"Test encoder " SUBGHZ_PROTOCOL_CAME_NAME " error\r\n");
|
||||
}
|
||||
|
||||
MU_TEST(subghz_encoder_came_twee_test) {
|
||||
mu_assert(
|
||||
subghz_encoder_test(EXT_PATH("unit_tests/subghz/came_twee.sub")),
|
||||
"Test encoder " SUBGHZ_PROTOCOL_CAME_TWEE_NAME " error\r\n");
|
||||
}
|
||||
|
||||
MU_TEST(subghz_encoder_gate_tx_test) {
|
||||
mu_assert(
|
||||
subghz_encoder_test(EXT_PATH("unit_tests/subghz/gate_tx.sub")),
|
||||
"Test encoder " SUBGHZ_PROTOCOL_GATE_TX_NAME " error\r\n");
|
||||
}
|
||||
|
||||
MU_TEST(subghz_encoder_nice_flo_test) {
|
||||
mu_assert(
|
||||
subghz_encoder_test(EXT_PATH("unit_tests/subghz/nice_flo.sub")),
|
||||
"Test encoder " SUBGHZ_PROTOCOL_NICE_FLO_NAME " error\r\n");
|
||||
}
|
||||
|
||||
MU_TEST(subghz_encoder_keelog_test) {
|
||||
mu_assert(
|
||||
subghz_encoder_test(EXT_PATH("unit_tests/subghz/doorhan.sub")),
|
||||
"Test encoder " SUBGHZ_PROTOCOL_KEELOQ_NAME " error\r\n");
|
||||
}
|
||||
|
||||
MU_TEST(subghz_encoder_linear_test) {
|
||||
mu_assert(
|
||||
subghz_encoder_test(EXT_PATH("unit_tests/subghz/linear.sub")),
|
||||
"Test encoder " SUBGHZ_PROTOCOL_LINEAR_NAME " error\r\n");
|
||||
}
|
||||
|
||||
MU_TEST(subghz_encoder_megacode_test) {
|
||||
mu_assert(
|
||||
subghz_encoder_test(EXT_PATH("unit_tests/subghz/megacode.sub")),
|
||||
"Test encoder " SUBGHZ_PROTOCOL_MEGACODE_NAME " error\r\n");
|
||||
}
|
||||
|
||||
MU_TEST(subghz_encoder_holtek_test) {
|
||||
mu_assert(
|
||||
subghz_encoder_test(EXT_PATH("unit_tests/subghz/holtek.sub")),
|
||||
"Test encoder " SUBGHZ_PROTOCOL_HOLTEK_NAME " error\r\n");
|
||||
}
|
||||
|
||||
MU_TEST(subghz_encoder_secplus_v1_test) {
|
||||
mu_assert(
|
||||
subghz_encoder_test(EXT_PATH("unit_tests/subghz/security_pls_1_0.sub")),
|
||||
"Test encoder " SUBGHZ_PROTOCOL_SECPLUS_V1_NAME " error\r\n");
|
||||
}
|
||||
|
||||
MU_TEST(subghz_encoder_secplus_v2_test) {
|
||||
mu_assert(
|
||||
subghz_encoder_test(EXT_PATH("unit_tests/subghz/security_pls_2_0.sub")),
|
||||
"Test encoder " SUBGHZ_PROTOCOL_SECPLUS_V2_NAME " error\r\n");
|
||||
}
|
||||
|
||||
MU_TEST(subghz_encoder_power_smart_test) {
|
||||
mu_assert(
|
||||
subghz_encoder_test(EXT_PATH("unit_tests/subghz/power_smart.sub")),
|
||||
"Test encoder " SUBGHZ_PROTOCOL_POWER_SMART_NAME " error\r\n");
|
||||
}
|
||||
|
||||
MU_TEST(subghz_encoder_marantec_test) {
|
||||
mu_assert(
|
||||
subghz_encoder_test(EXT_PATH("unit_tests/subghz/marantec.sub")),
|
||||
"Test encoder " SUBGHZ_PROTOCOL_MARANTEC_NAME " error\r\n");
|
||||
}
|
||||
|
||||
MU_TEST(subghz_encoder_bett_test) {
|
||||
mu_assert(
|
||||
subghz_encoder_test(EXT_PATH("unit_tests/subghz/bett.sub")),
|
||||
"Test encoder " SUBGHZ_PROTOCOL_BETT_NAME " error\r\n");
|
||||
}
|
||||
|
||||
MU_TEST(subghz_encoder_doitrand_test) {
|
||||
mu_assert(
|
||||
subghz_encoder_test(EXT_PATH("unit_tests/subghz/doitrand.sub")),
|
||||
"Test encoder " SUBGHZ_PROTOCOL_DOITRAND_NAME " error\r\n");
|
||||
}
|
||||
|
||||
MU_TEST(subghz_encoder_phoenix_v2_test) {
|
||||
mu_assert(
|
||||
subghz_encoder_test(EXT_PATH("unit_tests/subghz/phoenix_v2.sub")),
|
||||
"Test encoder " SUBGHZ_PROTOCOL_PHOENIX_V2_NAME " error\r\n");
|
||||
}
|
||||
|
||||
MU_TEST(subghz_encoder_honeywell_wdb_test) {
|
||||
mu_assert(
|
||||
subghz_encoder_test(EXT_PATH("unit_tests/subghz/honeywell_wdb.sub")),
|
||||
"Test encoder " SUBGHZ_PROTOCOL_HONEYWELL_WDB_NAME " error\r\n");
|
||||
}
|
||||
|
||||
MU_TEST(subghz_encoder_magellen_test) {
|
||||
mu_assert(
|
||||
subghz_encoder_test(EXT_PATH("unit_tests/subghz/magellen.sub")),
|
||||
"Test encoder " SUBGHZ_PROTOCOL_MAGELLEN_NAME " error\r\n");
|
||||
}
|
||||
|
||||
MU_TEST(subghz_encoder_intertechno_v3_test) {
|
||||
mu_assert(
|
||||
subghz_encoder_test(EXT_PATH("unit_tests/subghz/intertechno_v3.sub")),
|
||||
"Test encoder " SUBGHZ_PROTOCOL_INTERTECHNO_V3_NAME " error\r\n");
|
||||
}
|
||||
|
||||
MU_TEST(subghz_encoder_clemsa_test) {
|
||||
mu_assert(
|
||||
subghz_encoder_test(EXT_PATH("unit_tests/subghz/clemsa.sub")),
|
||||
"Test encoder " SUBGHZ_PROTOCOL_CLEMSA_NAME " error\r\n");
|
||||
}
|
||||
|
||||
MU_TEST(subghz_random_test) {
|
||||
mu_assert(subghz_decode_random_test(TEST_RANDOM_DIR_NAME), "Random test error\r\n");
|
||||
}
|
||||
|
||||
MU_TEST_SUITE(subghz) {
|
||||
subghz_test_init();
|
||||
MU_RUN_TEST(subghz_keystore_test);
|
||||
|
||||
MU_RUN_TEST(subghz_decoder_came_atomo_test);
|
||||
MU_RUN_TEST(subghz_decoder_came_test);
|
||||
MU_RUN_TEST(subghz_decoder_came_twee_test);
|
||||
MU_RUN_TEST(subghz_decoder_faac_slh_test);
|
||||
MU_RUN_TEST(subghz_decoder_gate_tx_test);
|
||||
MU_RUN_TEST(subghz_decoder_hormann_hsm_test);
|
||||
MU_RUN_TEST(subghz_decoder_ido_test);
|
||||
MU_RUN_TEST(subghz_decoder_keelog_test);
|
||||
MU_RUN_TEST(subghz_decoder_kia_seed_test);
|
||||
MU_RUN_TEST(subghz_decoder_nero_radio_test);
|
||||
MU_RUN_TEST(subghz_decoder_nero_sketch_test);
|
||||
MU_RUN_TEST(subghz_decoder_nice_flo_test);
|
||||
MU_RUN_TEST(subghz_decoder_nice_flor_s_test);
|
||||
MU_RUN_TEST(subghz_decoder_princeton_test);
|
||||
MU_RUN_TEST(subghz_decoder_scher_khan_magic_code_test);
|
||||
MU_RUN_TEST(subghz_decoder_somfy_keytis_test);
|
||||
MU_RUN_TEST(subghz_decoder_somfy_telis_test);
|
||||
MU_RUN_TEST(subghz_decoder_star_line_test);
|
||||
MU_RUN_TEST(subghz_decoder_linear_test);
|
||||
MU_RUN_TEST(subghz_decoder_megacode_test);
|
||||
MU_RUN_TEST(subghz_decoder_secplus_v1_test);
|
||||
MU_RUN_TEST(subghz_decoder_secplus_v2_test);
|
||||
MU_RUN_TEST(subghz_decoder_holtek_test);
|
||||
MU_RUN_TEST(subghz_decoder_power_smart_test);
|
||||
MU_RUN_TEST(subghz_decoder_marantec_test);
|
||||
MU_RUN_TEST(subghz_decoder_bett_test);
|
||||
MU_RUN_TEST(subghz_decoder_doitrand_test);
|
||||
MU_RUN_TEST(subghz_decoder_phoenix_v2_test);
|
||||
MU_RUN_TEST(subghz_decoder_honeywell_wdb_test);
|
||||
MU_RUN_TEST(subghz_decoder_magellen_test);
|
||||
MU_RUN_TEST(subghz_decoder_intertechno_v3_test);
|
||||
MU_RUN_TEST(subghz_decoder_clemsa_test);
|
||||
|
||||
MU_RUN_TEST(subghz_encoder_princeton_test);
|
||||
MU_RUN_TEST(subghz_encoder_came_test);
|
||||
MU_RUN_TEST(subghz_encoder_came_twee_test);
|
||||
MU_RUN_TEST(subghz_encoder_gate_tx_test);
|
||||
MU_RUN_TEST(subghz_encoder_nice_flo_test);
|
||||
MU_RUN_TEST(subghz_encoder_keelog_test);
|
||||
MU_RUN_TEST(subghz_encoder_linear_test);
|
||||
MU_RUN_TEST(subghz_encoder_megacode_test);
|
||||
MU_RUN_TEST(subghz_encoder_holtek_test);
|
||||
MU_RUN_TEST(subghz_encoder_secplus_v1_test);
|
||||
MU_RUN_TEST(subghz_encoder_secplus_v2_test);
|
||||
MU_RUN_TEST(subghz_encoder_power_smart_test);
|
||||
MU_RUN_TEST(subghz_encoder_marantec_test);
|
||||
MU_RUN_TEST(subghz_encoder_bett_test);
|
||||
MU_RUN_TEST(subghz_encoder_doitrand_test);
|
||||
MU_RUN_TEST(subghz_encoder_phoenix_v2_test);
|
||||
MU_RUN_TEST(subghz_encoder_honeywell_wdb_test);
|
||||
MU_RUN_TEST(subghz_encoder_magellen_test);
|
||||
MU_RUN_TEST(subghz_encoder_intertechno_v3_test);
|
||||
MU_RUN_TEST(subghz_encoder_clemsa_test);
|
||||
|
||||
MU_RUN_TEST(subghz_random_test);
|
||||
subghz_test_deinit();
|
||||
}
|
||||
|
||||
int run_minunit_test_subghz() {
|
||||
MU_RUN_SUITE(subghz);
|
||||
return MU_EXIT_CODE;
|
||||
}
|
137
applications/debug/unit_tests/test_index.c
Normal file
137
applications/debug/unit_tests/test_index.c
Normal file
@@ -0,0 +1,137 @@
|
||||
#include "m-string.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <furi.h>
|
||||
#include <furi_hal.h>
|
||||
#include "minunit_vars.h"
|
||||
#include <notification/notification_messages.h>
|
||||
#include <cli/cli.h>
|
||||
#include <loader/loader.h>
|
||||
|
||||
#define TAG "UnitTests"
|
||||
|
||||
int run_minunit_test_furi();
|
||||
int run_minunit_test_infrared();
|
||||
int run_minunit_test_rpc();
|
||||
int run_minunit_test_flipper_format();
|
||||
int run_minunit_test_flipper_format_string();
|
||||
int run_minunit_test_stream();
|
||||
int run_minunit_test_storage();
|
||||
int run_minunit_test_subghz();
|
||||
int run_minunit_test_dirwalk();
|
||||
int run_minunit_test_protocol_dict();
|
||||
int run_minunit_test_lfrfid_protocols();
|
||||
int run_minunit_test_nfc();
|
||||
int run_minunit_test_bit_lib();
|
||||
|
||||
typedef int (*UnitTestEntry)();
|
||||
|
||||
typedef struct {
|
||||
const char* name;
|
||||
const UnitTestEntry entry;
|
||||
} UnitTest;
|
||||
|
||||
const UnitTest unit_tests[] = {
|
||||
{.name = "furi", .entry = run_minunit_test_furi},
|
||||
{.name = "storage", .entry = run_minunit_test_storage},
|
||||
{.name = "stream", .entry = run_minunit_test_stream},
|
||||
{.name = "dirwalk", .entry = run_minunit_test_dirwalk},
|
||||
{.name = "flipper_format", .entry = run_minunit_test_flipper_format},
|
||||
{.name = "flipper_format_string", .entry = run_minunit_test_flipper_format_string},
|
||||
{.name = "rpc", .entry = run_minunit_test_rpc},
|
||||
{.name = "subghz", .entry = run_minunit_test_subghz},
|
||||
{.name = "infrared", .entry = run_minunit_test_infrared},
|
||||
{.name = "nfc", .entry = run_minunit_test_nfc},
|
||||
{.name = "protocol_dict", .entry = run_minunit_test_protocol_dict},
|
||||
{.name = "lfrfid", .entry = run_minunit_test_lfrfid_protocols},
|
||||
{.name = "bit_lib", .entry = run_minunit_test_bit_lib},
|
||||
};
|
||||
|
||||
void minunit_print_progress() {
|
||||
static const char progress[] = {'\\', '|', '/', '-'};
|
||||
static uint8_t progress_counter = 0;
|
||||
static TickType_t last_tick = 0;
|
||||
TickType_t current_tick = xTaskGetTickCount();
|
||||
if(current_tick - last_tick > 20) {
|
||||
last_tick = current_tick;
|
||||
printf("[%c]\033[3D", progress[++progress_counter % COUNT_OF(progress)]);
|
||||
fflush(stdout);
|
||||
}
|
||||
}
|
||||
|
||||
void minunit_print_fail(const char* str) {
|
||||
printf(FURI_LOG_CLR_E "%s\r\n" FURI_LOG_CLR_RESET, str);
|
||||
}
|
||||
|
||||
void unit_tests_cli(Cli* cli, string_t args, void* context) {
|
||||
UNUSED(cli);
|
||||
UNUSED(args);
|
||||
UNUSED(context);
|
||||
uint32_t failed_tests = 0;
|
||||
minunit_run = 0;
|
||||
minunit_assert = 0;
|
||||
minunit_fail = 0;
|
||||
minunit_status = 0;
|
||||
|
||||
Loader* loader = furi_record_open(RECORD_LOADER);
|
||||
NotificationApp* notification = furi_record_open(RECORD_NOTIFICATION);
|
||||
|
||||
// TODO: lock device while test running
|
||||
if(loader_is_locked(loader)) {
|
||||
printf("RPC: stop all applications to run tests\r\n");
|
||||
notification_message(notification, &sequence_blink_magenta_100);
|
||||
} else {
|
||||
notification_message_block(notification, &sequence_set_only_blue_255);
|
||||
|
||||
uint32_t heap_before = memmgr_get_free_heap();
|
||||
uint32_t cycle_counter = furi_get_tick();
|
||||
|
||||
for(size_t i = 0; i < COUNT_OF(unit_tests); i++) {
|
||||
if(cli_cmd_interrupt_received(cli)) {
|
||||
break;
|
||||
}
|
||||
|
||||
if(string_size(args)) {
|
||||
if(string_cmp_str(args, unit_tests[i].name) == 0) {
|
||||
failed_tests += unit_tests[i].entry();
|
||||
} else {
|
||||
printf("Skipping %s\r\n", unit_tests[i].name);
|
||||
}
|
||||
} else {
|
||||
failed_tests += 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);
|
||||
|
||||
// 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(failed_tests == 0) {
|
||||
notification_message(notification, &sequence_success);
|
||||
printf("Status: PASSED\r\n");
|
||||
} else {
|
||||
notification_message(notification, &sequence_error);
|
||||
printf("Status: FAILED\r\n");
|
||||
}
|
||||
}
|
||||
|
||||
furi_record_close(RECORD_NOTIFICATION);
|
||||
furi_record_close(RECORD_LOADER);
|
||||
}
|
||||
|
||||
void unit_tests_on_system_start() {
|
||||
#ifdef SRV_CLI
|
||||
Cli* cli = furi_record_open(RECORD_CLI);
|
||||
|
||||
// We need to launch apps from tests, so we cannot lock loader
|
||||
cli_add_command(cli, "unit_tests", CliCommandFlagParallelSafe, unit_tests_cli, NULL);
|
||||
furi_record_close(RECORD_CLI);
|
||||
#endif
|
||||
}
|
88
applications/debug/unit_tests/varint/varint_test.c
Normal file
88
applications/debug/unit_tests/varint/varint_test.c
Normal file
@@ -0,0 +1,88 @@
|
||||
#include <furi.h>
|
||||
#include <furi_hal.h>
|
||||
#include "../minunit.h"
|
||||
#include <toolbox/varint.h>
|
||||
#include <toolbox/profiler.h>
|
||||
|
||||
MU_TEST(test_varint_basic_u) {
|
||||
mu_assert_int_eq(1, varint_uint32_length(0));
|
||||
mu_assert_int_eq(5, varint_uint32_length(UINT32_MAX));
|
||||
|
||||
uint8_t data[8] = {};
|
||||
uint32_t out_value;
|
||||
|
||||
mu_assert_int_eq(1, varint_uint32_pack(0, data));
|
||||
mu_assert_int_eq(1, varint_uint32_unpack(&out_value, data, 8));
|
||||
mu_assert_int_eq(0, out_value);
|
||||
|
||||
mu_assert_int_eq(5, varint_uint32_pack(UINT32_MAX, data));
|
||||
mu_assert_int_eq(5, varint_uint32_unpack(&out_value, data, 8));
|
||||
mu_assert_int_eq(UINT32_MAX, out_value);
|
||||
}
|
||||
|
||||
MU_TEST(test_varint_basic_i) {
|
||||
mu_assert_int_eq(5, varint_int32_length(INT32_MIN / 2));
|
||||
mu_assert_int_eq(1, varint_int32_length(0));
|
||||
mu_assert_int_eq(5, varint_int32_length(INT32_MAX / 2));
|
||||
|
||||
mu_assert_int_eq(2, varint_int32_length(127));
|
||||
mu_assert_int_eq(2, varint_int32_length(-127));
|
||||
|
||||
uint8_t data[8] = {};
|
||||
int32_t out_value;
|
||||
mu_assert_int_eq(1, varint_int32_pack(0, data));
|
||||
mu_assert_int_eq(1, varint_int32_unpack(&out_value, data, 8));
|
||||
mu_assert_int_eq(0, out_value);
|
||||
|
||||
mu_assert_int_eq(2, varint_int32_pack(127, data));
|
||||
mu_assert_int_eq(2, varint_int32_unpack(&out_value, data, 8));
|
||||
mu_assert_int_eq(127, out_value);
|
||||
|
||||
mu_assert_int_eq(2, varint_int32_pack(-127, data));
|
||||
mu_assert_int_eq(2, varint_int32_unpack(&out_value, data, 8));
|
||||
mu_assert_int_eq(-127, out_value);
|
||||
|
||||
mu_assert_int_eq(5, varint_int32_pack(INT32_MAX, data));
|
||||
mu_assert_int_eq(5, varint_int32_unpack(&out_value, data, 8));
|
||||
mu_assert_int_eq(INT32_MAX, out_value);
|
||||
|
||||
mu_assert_int_eq(5, varint_int32_pack(INT32_MIN / 2 + 1, data));
|
||||
mu_assert_int_eq(5, varint_int32_unpack(&out_value, data, 8));
|
||||
mu_assert_int_eq(INT32_MIN / 2 + 1, out_value);
|
||||
}
|
||||
|
||||
MU_TEST(test_varint_rand_u) {
|
||||
uint8_t data[8] = {};
|
||||
uint32_t out_value;
|
||||
|
||||
for(size_t i = 0; i < 200000; i++) {
|
||||
uint32_t rand_value = rand();
|
||||
mu_assert_int_eq(
|
||||
varint_uint32_pack(rand_value, data), varint_uint32_unpack(&out_value, data, 8));
|
||||
mu_assert_int_eq(rand_value, out_value);
|
||||
}
|
||||
}
|
||||
|
||||
MU_TEST(test_varint_rand_i) {
|
||||
uint8_t data[8] = {};
|
||||
int32_t out_value;
|
||||
|
||||
for(size_t i = 0; i < 200000; i++) {
|
||||
int32_t rand_value = rand() + (INT32_MIN / 2 + 1);
|
||||
mu_assert_int_eq(
|
||||
varint_int32_pack(rand_value, data), varint_int32_unpack(&out_value, data, 8));
|
||||
mu_assert_int_eq(rand_value, out_value);
|
||||
}
|
||||
}
|
||||
|
||||
MU_TEST_SUITE(test_varint_suite) {
|
||||
MU_RUN_TEST(test_varint_basic_u);
|
||||
MU_RUN_TEST(test_varint_basic_i);
|
||||
MU_RUN_TEST(test_varint_rand_u);
|
||||
MU_RUN_TEST(test_varint_rand_i);
|
||||
}
|
||||
|
||||
int run_minunit_test_varint() {
|
||||
MU_RUN_SUITE(test_varint_suite);
|
||||
return MU_EXIT_CODE;
|
||||
}
|
Reference in New Issue
Block a user