From 59fd22be1bcf699fbf39b9c57c8af20c6812e7da Mon Sep 17 00:00:00 2001 From: Daniel Agar <daniel@agar.ca> Date: Tue, 23 Jan 2018 19:12:14 -0500 Subject: [PATCH] parameters import/export test --- src/include/unit_test.h | 2 +- src/systemcmds/tests/params.c | 5 + src/systemcmds/tests/test_parameters.cpp | 338 +++++++++++++++++++++++ 3 files changed, 344 insertions(+), 1 deletion(-) diff --git a/src/include/unit_test.h b/src/include/unit_test.h index 23bf4efe24..4e79b5951c 100644 --- a/src/include/unit_test.h +++ b/src/include/unit_test.h @@ -161,7 +161,7 @@ protected: /// since it will give you better error reporting of the actual values being compared. #define ut_compare_float(message, v1, v2, precision) \ do { \ - int _p = pow(10.0f, precision); \ + int _p = powf(10.0f, precision); \ int _v1 = (int)(v1 * _p + 0.5f); \ int _v2 = (int)(v2 * _p + 0.5f); \ if (_v1 != _v2) { \ diff --git a/src/systemcmds/tests/params.c b/src/systemcmds/tests/params.c index 62971fa789..37d260e929 100644 --- a/src/systemcmds/tests/params.c +++ b/src/systemcmds/tests/params.c @@ -41,6 +41,11 @@ PARAM_DEFINE_INT32(TEST_1, 2); */ PARAM_DEFINE_INT32(TEST_2, 4); +/** + * @group Testing + */ +PARAM_DEFINE_FLOAT(TEST_3, 5.0f); + /** * @group Testing */ diff --git a/src/systemcmds/tests/test_parameters.cpp b/src/systemcmds/tests/test_parameters.cpp index 36a42f666f..3d412580e9 100644 --- a/src/systemcmds/tests/test_parameters.cpp +++ b/src/systemcmds/tests/test_parameters.cpp @@ -1,5 +1,8 @@ #include <unit_test.h> +#include <px4_defines.h> +#include <fcntl.h> + class ParameterTest : public UnitTest { public: @@ -11,6 +14,7 @@ public: p1 = param_find("TEST_RC2_X"); p2 = param_find("TEST_1"); p3 = param_find("TEST_2"); + p4 = param_find("TEST_3"); } private: @@ -19,16 +23,25 @@ private: param_t p1{PARAM_INVALID}; param_t p2{PARAM_INVALID}; param_t p3{PARAM_INVALID}; + param_t p4{PARAM_INVALID}; bool _assert_parameter_int_value(param_t param, int32_t expected); + bool _assert_parameter_float_value(param_t param, float expected); + bool _set_all_int_parameters_to(int32_t value); + // tests on the test parameters (TEST_RC_X, TEST_RC2_X, TEST_1, TEST_2, TEST_3) bool SimpleFind(); bool ResetAll(); bool ResetAllExcludesOne(); bool ResetAllExcludesTwo(); bool ResetAllExcludesBoundaryCheck(); bool ResetAllExcludesWildcard(); + bool exportImport(); + + // tests on system parameters + // WARNING, can potentially trash your system + bool exportImportAll(); }; bool ParameterTest::_assert_parameter_int_value(param_t param, int32_t expected) @@ -41,6 +54,16 @@ bool ParameterTest::_assert_parameter_int_value(param_t param, int32_t expected) return true; } +bool ParameterTest::_assert_parameter_float_value(param_t param, float expected) +{ + float value; + int result = param_get(param, &value); + ut_compare("param_get did not return parameter", 0, result); + ut_compare_float("value for param doesn't match default value", expected, value, 0.001); + + return true; +} + bool ParameterTest::_set_all_int_parameters_to(int32_t value) { param_set(p0, &value); @@ -157,14 +180,329 @@ bool ParameterTest::ResetAllExcludesWildcard() return ret; } +bool ParameterTest::exportImport() +{ + static constexpr float MAGIC_FLOAT_VAL = 0.314159f; + + bool ret = true; + + param_t test_params[] = {p0, p1, p2, p3, p4}; + + // set all params to corresponding param_t value + for (auto p : test_params) { + if (param_type(p) == PARAM_TYPE_INT32) { + const int32_t set_val = p; + + if (param_set_no_notification(p, &set_val) != PX4_OK) { + PX4_ERR("param_set_no_notification failed for: %d", p); + ut_assert("param_set_no_notification failed", false); + } + + int32_t get_val = 0; + + if (param_get(p, &get_val) != PX4_OK) { + PX4_ERR("param_get failed for: %d", p); + ut_assert("param_set_no_notification failed", false); + } + + ut_compare("value for param doesn't match default value", p, get_val); + } + + if (param_type(p) == PARAM_TYPE_FLOAT) { + const float set_val = (float)p + MAGIC_FLOAT_VAL; + + if (param_set_no_notification(p, &set_val) != PX4_OK) { + PX4_ERR("param_set_no_notification failed for: %d", p); + ut_assert("param_set_no_notification failed", false); + } + + float get_val = 0.0f; + + if (param_get(p, &get_val) != PX4_OK) { + PX4_ERR("param_get failed for: %d", p); + ut_assert("param_set_no_notification failed", false); + } + + ut_compare("value for param doesn't match default value", p, (float)p + MAGIC_FLOAT_VAL); + } + } + + // save + if (param_save_default() != PX4_OK) { + PX4_ERR("param_save_default failed"); + return false; + } + + // zero all params and verify, but don't save + for (auto p : test_params) { + if (param_type(p) == PARAM_TYPE_INT32) { + const int32_t set_val = 0; + + if (param_set_no_notification(p, &set_val) != PX4_OK) { + PX4_ERR("param_set_no_notification failed for: %d", p); + ut_assert("param_set_no_notification failed", false); + } + + int32_t get_val = -1; + + if (param_get(p, &get_val) != PX4_OK) { + PX4_ERR("param_get failed for: %d", p); + ut_assert("param_set_no_notification failed", false); + } + + ut_compare("value for param doesn't match default value", set_val, get_val); + } + + if (param_type(p) == PARAM_TYPE_FLOAT) { + const float set_val = 0.0f; + + if (param_set_no_notification(p, &set_val) != PX4_OK) { + PX4_ERR("param_set_no_notification failed for: %d", p); + ut_assert("param_set_no_notification failed", false); + } + + float get_val = -1.0f; + + if (param_get(p, &get_val) != PX4_OK) { + PX4_ERR("param_get failed for: %d", p); + ut_assert("param_set_no_notification failed", false); + } + + ut_compare_float("value for param doesn't match default value", set_val, get_val, 0.001f); + } + } + + // load saved params + if (param_load_default() != PX4_OK) { + PX4_ERR("param_save_default failed"); + ret = true; + } + + // check every param + for (auto p : test_params) { + if (param_type(p) == PARAM_TYPE_INT32) { + + int32_t get_val = 0.0f; + + if (param_get(p, &get_val) != PX4_OK) { + PX4_ERR("param_get failed for: %d", p); + ut_assert("param_set_no_notification failed", false); + } + + ut_compare("value for param doesn't match default value", p, get_val); + } + + if (param_type(p) == PARAM_TYPE_FLOAT) { + float get_val = 0.0f; + + if (param_get(p, &get_val) != PX4_OK) { + PX4_ERR("param_get failed for: %d", p); + ut_assert("param_set_no_notification failed", false); + } + + ut_compare_float("value for param doesn't match default value", p, (float)p + MAGIC_FLOAT_VAL, 0.001f); + } + } + + return ret; +} + +bool ParameterTest::exportImportAll() +{ + static constexpr float MAGIC_FLOAT_VAL = 0.217828f; + + // backup current parameters + const char *param_file_name = PX4_ROOTFSDIR "/fs/microsd/param_backup"; + int fd = open(param_file_name, O_WRONLY | O_CREAT, PX4_O_MODE_666); + + if (fd < 0) { + PX4_ERR("open '%s' failed (%i)", param_file_name, errno); + return false; + } + + int result = param_export(fd, false); + + if (result != PX4_OK) { + PX4_ERR("param_export failed"); + close(fd); + return false; + } + + close(fd); + + bool ret = true; + + int N = param_count(); + + // set all params to corresponding param_t value + for (unsigned i = 0; i < N; i++) { + + param_t p = param_for_index(i); + + if (p == PARAM_INVALID) { + PX4_ERR("param invalid: %d(%d)", p, i); + break; + } + + if (param_type(p) == PARAM_TYPE_INT32) { + const int32_t set_val = p; + + if (param_set_no_notification(p, &set_val) != PX4_OK) { + PX4_ERR("param_set_no_notification failed for: %d", p); + ut_assert("param_set_no_notification failed", false); + } + + int32_t get_val = 0; + + if (param_get(p, &get_val) != PX4_OK) { + PX4_ERR("param_get failed for: %d", p); + ut_assert("param_set_no_notification failed", false); + } + + ut_compare("value for param doesn't match default value", p, get_val); + } + + if (param_type(p) == PARAM_TYPE_FLOAT) { + const float set_val = (float)p + MAGIC_FLOAT_VAL; + + if (param_set_no_notification(p, &set_val) != PX4_OK) { + PX4_ERR("param_set_no_notification failed for: %d", p); + ut_assert("param_set_no_notification failed", false); + } + + float get_val = 0.0f; + + if (param_get(p, &get_val) != PX4_OK) { + PX4_ERR("param_get failed for: %d", p); + ut_assert("param_set_no_notification failed", false); + } + + ut_compare("value for param doesn't match default value", p, (float)p + MAGIC_FLOAT_VAL); + } + } + + // save + if (param_save_default() != PX4_OK) { + PX4_ERR("param_save_default failed"); + return false; + } + + // zero all params and verify, but don't save + for (unsigned i = 0; i < N; i++) { + param_t p = param_for_index(i); + + if (param_type(p) == PARAM_TYPE_INT32) { + + const int32_t set_val = 0; + + if (param_set_no_notification(p, &set_val) != PX4_OK) { + PX4_ERR("param set failed: %d", p); + ut_assert("param_set_no_notification failed", false); + } + + int32_t get_val = -1; + + if (param_get(p, &get_val) != PX4_OK) { + PX4_ERR("param_get failed for: %d", p); + ut_assert("param_set_no_notification failed", false); + } + + ut_compare("value for param doesn't match default value", set_val, get_val); + } + + if (param_type(p) == PARAM_TYPE_FLOAT) { + float set_val = 0.0f; + + if (param_set_no_notification(p, &set_val) != PX4_OK) { + PX4_ERR("param set failed: %d", p); + ut_assert("param_set_no_notification failed", false); + } + + float get_val = -1.0f; + + if (param_get(p, &get_val) != PX4_OK) { + PX4_ERR("param_get failed for: %d", p); + ut_assert("param_set_no_notification failed", false); + } + + ut_compare("value for param doesn't match default value", set_val, get_val); + } + } + + // load saved params + if (param_load_default() != PX4_OK) { + PX4_ERR("param_save_default failed"); + ret = true; + } + + // check every param + for (unsigned i = 0; i < N; i++) { + param_t p = param_for_index(i); + + if (param_type(p) == PARAM_TYPE_INT32) { + + int32_t get_val = 0; + + if (param_get(p, &get_val) != PX4_OK) { + PX4_ERR("param_get failed for: %d", p); + ut_assert("param_set_no_notification failed", false); + } + + ut_compare("value for param doesn't match default value", p, get_val); + } + + if (param_type(p) == PARAM_TYPE_FLOAT) { + float get_val = 0.0f; + + if (param_get(p, &get_val) != PX4_OK) { + PX4_ERR("param_get failed for: %d", p); + ut_assert("param_set_no_notification failed", false); + } + + ut_compare("value for param doesn't match default value", p, (float)p + MAGIC_FLOAT_VAL); + } + } + + param_reset_all(); + + // restore original params + fd = open(param_file_name, O_RDONLY); + + if (fd < 0) { + PX4_ERR("open '%s' failed (%i)", param_file_name, errno); + return false; + } + + result = param_import(fd); + close(fd); + + if (result < 0) { + PX4_ERR("importing from '%s' failed (%i)", param_file_name, result); + return false; + } + + return ret; +} + bool ParameterTest::run_tests() { + param_control_autosave(false); + + ut_run_test(ResetAll); ut_run_test(SimpleFind); ut_run_test(ResetAll); ut_run_test(ResetAllExcludesOne); ut_run_test(ResetAllExcludesTwo); ut_run_test(ResetAllExcludesBoundaryCheck); ut_run_test(ResetAllExcludesWildcard); + ut_run_test(exportImport); + + // WARNING, can potentially trash your system +#ifdef __PX4_POSIX + ut_run_test(exportImportAll); +#endif /* __PX4_POSIX */ + + param_control_autosave(true); return (_tests_failed == 0); } -- GitLab