This is an automated email from the ASF dual-hosted git repository. marko pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/mynewt-core.git
commit 4f39ba0aecb34ee96273ffccfea34f11f764f417 Author: Marko Kiiskila <[email protected]> AuthorDate: Wed Aug 21 16:49:23 2019 +0300 sys/config; add option to store config in FCB2. --- sys/config/include/config/config_fcb2.h | 72 ++++ sys/config/pkg.yml | 2 + sys/config/{ => selftest-fcb2}/pkg.yml | 28 +- sys/config/selftest-fcb2/src/conf_test_fcb2.c | 401 +++++++++++++++++++++ sys/config/selftest-fcb2/src/conf_test_fcb2.h | 105 ++++++ .../src/testcases/config_empty_lookups.c | 34 ++ .../src/testcases/config_test_commit.c | 41 +++ .../src/testcases/config_test_compress_reset.c | 92 +++++ .../src/testcases/config_test_custom_compress.c | 121 +++++++ .../src/testcases/config_test_empty_fcb.c | 44 +++ .../src/testcases/config_test_get_stored.c | 78 ++++ .../src/testcases/config_test_getset_bytes.c | 49 +++ .../src/testcases/config_test_getset_int.c | 40 ++ .../src/testcases/config_test_getset_int64.c | 56 +++ .../src/testcases/config_test_getset_unknown.c | 48 +++ .../src/testcases/config_test_save_1_fcb.c | 48 +++ .../src/testcases/config_test_save_2_fcb.c | 87 +++++ .../src/testcases/config_test_save_3_fcb.c | 53 +++ .../src/testcases/config_test_save_one_fcb.c | 57 +++ sys/config/{pkg.yml => selftest-fcb2/syscfg.yml} | 30 +- sys/config/src/config_fcb2.c | 356 ++++++++++++++++++ sys/config/src/config_init.c | 40 ++ sys/config/syscfg.yml | 11 +- 23 files changed, 1850 insertions(+), 43 deletions(-) diff --git a/sys/config/include/config/config_fcb2.h b/sys/config/include/config/config_fcb2.h new file mode 100644 index 0000000..7072521 --- /dev/null +++ b/sys/config/include/config/config_fcb2.h @@ -0,0 +1,72 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +#ifndef __SYS_CONFIG_FCB2_H_ +#define __SYS_CONFIG_FCB2_H_ + +#include "config/config.h" +#include "config/config_store.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct conf_fcb2 { + struct conf_store cf2_store; + struct fcb cf2_fcb; +}; + +/** + * Add FCB as a sourced of persisted configation + * + * @param cf Information regarding FCB2 area to add. + * + * @return 0 on success, non-zero on failure. + */ +int conf_fcb2_src(struct conf_fcb2 *cf); + +/** + * Set FCB as the destination for persisting configation + * + * @param cf Information regarding FCB2 area to add. This FCB area should have + * been added using conf_fcb2_src() previously. + * + * @return 0 on success, non-zero on failure. + */ +int conf_fcb2_dst(struct conf_fcb2 *cf); + +/** + * Do a custom compression cycle. Caller provides a callback function which + * returns whether value should be copied or not. Note that compression + * automatically filters out old configuration values. + * + * @param cf FCB2 source to compress. + * @param copy_or_not Function which gets called with key/value pair. + * Returns 0 if copy should happen, 1 if key/value pair + * should be skipped. + */ +void conf_fcb2_compress(struct conf_fcb2 *cf, + int (*copy_or_not)(const char *name, const char *val, + void *con_arg), + void *con_arg); + +#ifdef __cplusplus +} +#endif + +#endif /* __SYS_CONFIG_FCB2_H_ */ diff --git a/sys/config/pkg.yml b/sys/config/pkg.yml index 93fe279..f361a8b 100644 --- a/sys/config/pkg.yml +++ b/sys/config/pkg.yml @@ -32,6 +32,8 @@ pkg.deps.CONFIG_NEWTMGR: - "@apache-mynewt-core/mgmt/mgmt" pkg.deps.CONFIG_FCB: - "@apache-mynewt-core/fs/fcb" +pkg.deps.CONFIG_FCB2: + - "@apache-mynewt-core/fs/fcb2" pkg.deps.CONFIG_NFFS: - "@apache-mynewt-core/fs/nffs" diff --git a/sys/config/pkg.yml b/sys/config/selftest-fcb2/pkg.yml similarity index 62% copy from sys/config/pkg.yml copy to sys/config/selftest-fcb2/pkg.yml index 93fe279..757b560 100644 --- a/sys/config/pkg.yml +++ b/sys/config/selftest-fcb2/pkg.yml @@ -1,4 +1,3 @@ -# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information @@ -6,7 +5,7 @@ # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at -# +# # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, @@ -16,25 +15,16 @@ # specific language governing permissions and limitations # under the License. # - -pkg.name: sys/config -pkg.description: Configuration management for embedded systems. +pkg.name: sys/config/selftest-fcb2 +pkg.type: unittest +pkg.description: "Config unit tests for fcb2." pkg.author: "Apache Mynewt <[email protected]>" pkg.homepage: "http://mynewt.apache.org/" pkg.keywords: pkg.deps: - - "@apache-mynewt-core/encoding/base64" -pkg.deps.CONFIG_CLI: - - "@apache-mynewt-core/sys/shell" -pkg.deps.CONFIG_NEWTMGR: - - "@apache-mynewt-core/encoding/cborattr" - - "@apache-mynewt-core/mgmt/mgmt" -pkg.deps.CONFIG_FCB: - - "@apache-mynewt-core/fs/fcb" -pkg.deps.CONFIG_NFFS: - - "@apache-mynewt-core/fs/nffs" - -pkg.init: - config_pkg_init: 'MYNEWT_VAL(CONFIG_SYSINIT_STAGE_1)' - config_pkg_init_stage2: 'MYNEWT_VAL(CONFIG_SYSINIT_STAGE_2)' + - "@apache-mynewt-core/fs/fcb2" + - "@apache-mynewt-core/sys/config" + - "@apache-mynewt-core/sys/console/stub" + - "@apache-mynewt-core/sys/log/stub" + - "@apache-mynewt-core/test/testutil" diff --git a/sys/config/selftest-fcb2/src/conf_test_fcb2.c b/sys/config/selftest-fcb2/src/conf_test_fcb2.c new file mode 100644 index 0000000..8f097fd --- /dev/null +++ b/sys/config/selftest-fcb2/src/conf_test_fcb2.c @@ -0,0 +1,401 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#include <stdio.h> +#include <string.h> + +#include <os/mynewt.h> +#include <flash_map/flash_map.h> +#include <testutil/testutil.h> +#include <fcb/fcb.h> +#include <config/config.h> +#include <config/config_fcb2.h> +#include <config_priv.h> +#include "conf_test_fcb2.h" + +char val_string[CONF_TEST_FCB_VAL_STR_CNT][CONF_MAX_VAL_LEN]; + +uint8_t val8; +int c2_var_count = 1; + +uint32_t val32; +uint64_t val64; + +int test_get_called; +int test_set_called; +int test_commit_called; +int test_export_block; + +char *ctest_handle_get(int argc, char **argv, char *val, + int val_len_max); +int ctest_handle_set(int argc, char **argv, char *val); +int ctest_handle_commit(void); +int ctest_handle_export(void (*cb)(char *name, char *value), + enum conf_export_tgt tgt); +char *c2_handle_get(int argc, char **argv, char *val, + int val_len_max); +int c2_handle_set(int argc, char **argv, char *val); +int c2_handle_export(void (*cb)(char *name, char *value), + enum conf_export_tgt tgt); +char *c3_handle_get(int argc, char **argv, char *val, + int val_len_max); +int c3_handle_set(int argc, char **argv, char *val); +int c3_handle_export(void (*cb)(char *name, char *value), + enum conf_export_tgt tgt); + +struct conf_handler config_test_handler = { + .ch_name = "myfoo", + .ch_get = ctest_handle_get, + .ch_set = ctest_handle_set, + .ch_commit = ctest_handle_commit, + .ch_export = ctest_handle_export +}; + +char * +ctest_handle_get(int argc, char **argv, char *val, int val_len_max) +{ + test_get_called = 1; + if (argc == 1 && !strcmp(argv[0], "mybar")) { + return conf_str_from_value(CONF_INT8, &val8, val, val_len_max); + } + if (argc == 1 && !strcmp(argv[0], "mybar64")) { + return conf_str_from_value(CONF_INT64, &val64, val, val_len_max); + } + return NULL; +} + +int +ctest_handle_set(int argc, char **argv, char *val) +{ + uint8_t newval; + uint64_t newval64; + int rc; + + test_set_called = 1; + if (argc == 1 && !strcmp(argv[0], "mybar")) { + rc = CONF_VALUE_SET(val, CONF_INT8, newval); + TEST_ASSERT(rc == 0); + val8 = newval; + return 0; + } + if (argc == 1 && !strcmp(argv[0], "mybar64")) { + rc = CONF_VALUE_SET(val, CONF_INT64, newval64); + TEST_ASSERT(rc == 0); + val64 = newval64; + return 0; + } + return OS_ENOENT; +} + +int +ctest_handle_commit(void) +{ + test_commit_called = 1; + return 0; +} + +int +ctest_handle_export(void (*cb)(char *name, char *value), + enum conf_export_tgt tgt) +{ + char value[32]; + + if (test_export_block) { + return 0; + } + conf_str_from_value(CONF_INT8, &val8, value, sizeof(value)); + cb("myfoo/mybar", value); + + conf_str_from_value(CONF_INT64, &val64, value, sizeof(value)); + cb("myfoo/mybar64", value); + + return 0; +} + +struct conf_handler c2_test_handler = { + .ch_name = "2nd", + .ch_get = c2_handle_get, + .ch_set = c2_handle_set, + .ch_commit = NULL, + .ch_export = c2_handle_export +}; + +char * +c2_var_find(char *name) +{ + int idx = 0; + int len; + char *eptr; + + len = strlen(name); + TEST_ASSERT(!strncmp(name, "string", 6)); + TEST_ASSERT(len > 6); + + idx = strtoul(&name[6], &eptr, 10); + TEST_ASSERT(*eptr == '\0'); + TEST_ASSERT(idx < c2_var_count); + return val_string[idx]; +} + +char * +c2_handle_get(int argc, char **argv, char *val, int val_len_max) +{ + int len; + char *valptr; + + if (argc == 1) { + valptr = c2_var_find(argv[0]); + if (!valptr) { + return NULL; + } + len = strlen(val_string[0]); + if (len > val_len_max) { + len = val_len_max; + } + strncpy(val, valptr, len); + } + return NULL; +} + +int +c2_handle_set(int argc, char **argv, char *val) +{ + char *valptr; + + if (argc == 1) { + valptr = c2_var_find(argv[0]); + if (!valptr) { + return OS_ENOENT; + } + if (val) { + strncpy(valptr, val, sizeof(val_string[0])); + } else { + memset(valptr, 0, sizeof(val_string[0])); + } + return 0; + } + return OS_ENOENT; +} + +int +c2_handle_export(void (*cb)(char *name, char *value), + enum conf_export_tgt tgt) +{ + int i; + char name[32]; + + for (i = 0; i < c2_var_count; i++) { + snprintf(name, sizeof(name), "2nd/string%d", i); + cb(name, val_string[i]); + } + return 0; +} + +struct conf_handler c3_test_handler = { + .ch_name = "3", + .ch_get = c3_handle_get, + .ch_set = c3_handle_set, + .ch_commit = NULL, + .ch_export = c3_handle_export +}; + +char * +c3_handle_get(int argc, char **argv, char *val, int val_len_max) +{ + if (argc == 1 && !strcmp(argv[0], "v")) { + return conf_str_from_value(CONF_INT32, &val32, val, val_len_max); + } + return NULL; +} + +int +c3_handle_set(int argc, char **argv, char *val) +{ + uint32_t newval; + int rc; + + if (argc == 1 && !strcmp(argv[0], "v")) { + rc = CONF_VALUE_SET(val, CONF_INT32, newval); + TEST_ASSERT(rc == 0); + val32 = newval; + return 0; + } + return OS_ENOENT; +} + +int +c3_handle_export(void (*cb)(char *name, char *value), + enum conf_export_tgt tgt) +{ + char value[32]; + + conf_str_from_value(CONF_INT32, &val32, value, sizeof(value)); + cb("3/v", value); + + return 0; +} + +void +ctest_clear_call_state(void) +{ + test_get_called = 0; + test_set_called = 0; + test_commit_called = 0; +} + +int +ctest_get_call_state(void) +{ + return test_get_called + test_set_called + test_commit_called; +} + +void config_wipe_srcs(void) +{ + SLIST_INIT(&conf_load_srcs); + conf_save_dst = NULL; +} + +void config_wipe_fcb2(struct flash_sector_range *fsr, int cnt) +{ + int rc; + int i; + + for (i = 0; i < cnt; i++) { + rc = flash_area_erase(&fsr[i].fsr_flash_area, 0, + fsr[i].fsr_sector_size * fsr[i].fsr_sector_count); + TEST_ASSERT(rc == 0); + } +} + +struct flash_sector_range fcb_range[] = { + [0] = { + .fsr_flash_area = { + .fa_off = 0x00000000, + .fa_size = 64 * 1024 + }, + .fsr_range_start = 0, + .fsr_first_sector = 0, + .fsr_sector_size = 16 * 1024, + .fsr_sector_count = 4, + .fsr_align = 1, + } +}; + +void +config_test_fill_area( + char test_value[CONF_TEST_FCB_VAL_STR_CNT][CONF_MAX_VAL_LEN], + int iteration) +{ + int i, j; + + for (j = 0; j < CONF_TEST_FCB_VAL_STR_CNT; j++) { + for (i = 0; i < CONF_MAX_VAL_LEN; i++) { + test_value[j][i] = ((j * 2) + i + iteration) % 10 + '0'; + } + test_value[j][sizeof(test_value[j]) - 1] = '\0'; + } +} + +static void +conf_test_fcb_pre_test(void *arg) +{ + int rc; + + rc = conf_register(&config_test_handler); + TEST_ASSERT_FATAL(rc == 0); +} + +static void +conf_test_fcb_pre_test2(void *arg) +{ + int rc; + + rc = conf_register(&config_test_handler); + TEST_ASSERT_FATAL(rc == 0); + + rc = conf_register(&c2_test_handler); + TEST_ASSERT_FATAL(rc == 0); +} + +static void +conf_test_fcb_pre_test3(void *arg) +{ + int rc; + + rc = conf_register(&config_test_handler); + TEST_ASSERT_FATAL(rc == 0); + + rc = conf_register(&c2_test_handler); + TEST_ASSERT_FATAL(rc == 0); + + rc = conf_register(&c3_test_handler); + TEST_ASSERT_FATAL(rc == 0); +} + +TEST_SUITE(config_test_c0) +{ + config_empty_lookups(); +} + +TEST_SUITE(config_test_c1) +{ + tu_config.pre_test_cb = conf_test_fcb_pre_test; + + config_test_getset_unknown(); + config_test_getset_int(); + config_test_getset_bytes(); + config_test_getset_int64(); + + config_test_commit(); + + config_test_save_1_fcb(); +} + +TEST_SUITE(config_test_c2) +{ + tu_config.pre_test_cb = conf_test_fcb_pre_test2; + + config_test_empty_fcb(); + + config_test_save_2_fcb(); + + config_test_save_one_fcb(); + config_test_get_stored_fcb(); +} + +TEST_SUITE(config_test_c3) +{ + tu_config.pre_test_cb = conf_test_fcb_pre_test3; + + config_test_save_3_fcb(); + + config_test_compress_reset(); + config_test_custom_compress(); +} + +int +main(int argc, char **argv) +{ + config_test_c0(); + config_test_c1(); + config_test_c2(); + config_test_c3(); + + return tu_any_failed; +} diff --git a/sys/config/selftest-fcb2/src/conf_test_fcb2.h b/sys/config/selftest-fcb2/src/conf_test_fcb2.h new file mode 100644 index 0000000..3b2b63f --- /dev/null +++ b/sys/config/selftest-fcb2/src/conf_test_fcb2.h @@ -0,0 +1,105 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +#ifndef _CONF_TEST_FCB2_H +#define _CONF_TEST_FCB2_H + +#include <stdio.h> +#include <string.h> +#include <os/mynewt.h> +#include <flash_map/flash_map.h> +#include <testutil/testutil.h> +#include <fcb/fcb.h> +#include <config/config.h> +#include <config/config_fcb2.h> +#include <config_priv.h> + +#ifdef __cplusplus +extern "C" { +#endif + +extern uint8_t val8; +extern int c2_var_count; + +#define CONF_TEST_FCB_VAL_STR_CNT 64 + +extern char val_string[CONF_TEST_FCB_VAL_STR_CNT][CONF_MAX_VAL_LEN]; + +#define CONF_TEST_FCB_RANGE_CNT 1 + +extern struct flash_sector_range fcb_range[CONF_TEST_FCB_RANGE_CNT]; + +extern uint32_t val32; +extern uint64_t val64; + +extern int test_get_called; +extern int test_set_called; +extern int test_commit_called; +extern int test_export_block; + +void ctest_clear_call_state(void); +int ctest_get_call_state(void); +void config_wipe_srcs(void); +extern void config_test_fill_area( + char test_value[CONF_TEST_FCB_VAL_STR_CNT][CONF_MAX_VAL_LEN], + int iteration); + +void config_wipe_fcb2(struct flash_sector_range *fsr, int cnt); + +char *ctest_handle_get(int argc, char **argv, char *val, int val_len_max); +int ctest_handle_set(int argc, char **argv, char *val); +int ctest_handle_commit(void); +int ctest_handle_export(void (*cb)(char *name, char *value), + enum conf_export_tgt tgt); + +char *c2_handle_get(int argc, char **argv, char *val, int val_len_max); +int c2_handle_set(int argc, char **argv, char *val); +int c2_handle_export(void (*cb)(char *name, char *value), + enum conf_export_tgt tgt); + +char *c3_handle_get(int argc, char **argv, char *val, int val_len_max); +int c3_handle_set(int argc, char **argv, char *val); +int c3_handle_export(void (*cb)(char *name, char *value), + enum conf_export_tgt tgt); + +extern struct conf_handler config_test_handler; + +extern struct conf_handler c2_test_handler; + +extern struct conf_handler c3_test_handler; + +TEST_CASE_DECL(config_empty_lookups) +TEST_CASE_DECL(config_test_getset_unknown) +TEST_CASE_DECL(config_test_getset_int) +TEST_CASE_DECL(config_test_getset_bytes) +TEST_CASE_DECL(config_test_getset_int64) +TEST_CASE_DECL(config_test_commit) +TEST_CASE_DECL(config_test_empty_fcb) +TEST_CASE_DECL(config_test_save_1_fcb) +TEST_CASE_DECL(config_test_save_2_fcb) +TEST_CASE_DECL(config_test_save_3_fcb) +TEST_CASE_DECL(config_test_compress_reset) +TEST_CASE_DECL(config_test_save_one_fcb) +TEST_CASE_DECL(config_test_custom_compress) +TEST_CASE_DECL(config_test_get_stored_fcb) + +#ifdef __cplusplus +} +#endif + +#endif /* _CONF_TEST_FCB_H */ diff --git a/sys/config/selftest-fcb2/src/testcases/config_empty_lookups.c b/sys/config/selftest-fcb2/src/testcases/config_empty_lookups.c new file mode 100644 index 0000000..5294b5f --- /dev/null +++ b/sys/config/selftest-fcb2/src/testcases/config_empty_lookups.c @@ -0,0 +1,34 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +#include "conf_test_fcb2.h" + +TEST_CASE_SELF(config_empty_lookups) +{ + int rc; + char name[80]; + char tmp[64], *str; + + strcpy(name, "foo/bar"); + rc = conf_set_value(name, "tmp"); + TEST_ASSERT(rc != 0); + + strcpy(name, "foo/bar"); + str = conf_get_value(name, tmp, sizeof(tmp)); + TEST_ASSERT(str == NULL); +} diff --git a/sys/config/selftest-fcb2/src/testcases/config_test_commit.c b/sys/config/selftest-fcb2/src/testcases/config_test_commit.c new file mode 100644 index 0000000..9729e46 --- /dev/null +++ b/sys/config/selftest-fcb2/src/testcases/config_test_commit.c @@ -0,0 +1,41 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +#include "conf_test_fcb2.h" + +TEST_CASE_SELF(config_test_commit) +{ + char name[80]; + int rc; + + strcpy(name, "bar"); + rc = conf_commit(name); + TEST_ASSERT(rc); + TEST_ASSERT(ctest_get_call_state() == 0); + + rc = conf_commit(NULL); + TEST_ASSERT(rc == 0); + TEST_ASSERT(test_commit_called == 1); + ctest_clear_call_state(); + + strcpy(name, "myfoo"); + rc = conf_commit(name); + TEST_ASSERT(rc == 0); + TEST_ASSERT(test_commit_called == 1); + ctest_clear_call_state(); +} diff --git a/sys/config/selftest-fcb2/src/testcases/config_test_compress_reset.c b/sys/config/selftest-fcb2/src/testcases/config_test_compress_reset.c new file mode 100644 index 0000000..f74c8da --- /dev/null +++ b/sys/config/selftest-fcb2/src/testcases/config_test_compress_reset.c @@ -0,0 +1,92 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +#include "conf_test_fcb2.h" + +TEST_CASE_SELF(config_test_compress_reset) +{ + int rc; + struct conf_fcb2 cf; + uint16_t fa; + char test_value[CONF_TEST_FCB_VAL_STR_CNT][CONF_MAX_VAL_LEN]; + int elems[4]; + int i; + + config_wipe_srcs(); + config_wipe_fcb2(fcb_range, CONF_TEST_FCB_RANGE_CNT); + + cf.cf2_fcb.f_magic = MYNEWT_VAL(CONFIG_FCB_MAGIC); + cf.cf2_fcb.f_range_cnt = CONF_TEST_FCB_RANGE_CNT; + cf.cf2_fcb.f_sector_cnt = fcb_range[0].fsr_sector_count; + cf.cf2_fcb.f_ranges = fcb_range; + + rc = conf_fcb2_src(&cf); + TEST_ASSERT(rc == 0); + + rc = conf_fcb2_dst(&cf); + TEST_ASSERT(rc == 0); + + c2_var_count = 1; + memset(elems, 0, sizeof(elems)); + + for (i = 0; ; i++) { + config_test_fill_area(test_value, i); + memcpy(val_string, test_value, sizeof(val_string)); + + rc = conf_save(); + TEST_ASSERT(rc == 0); + + if (cf.cf2_fcb.f_active_id == fcb_range[0].fsr_sector_count - 2) { + /* + * Started using space just before scratch. + */ + break; + } + memset(val_string, 0, sizeof(val_string)); + + rc = conf_load(); + TEST_ASSERT(rc == 0); + TEST_ASSERT(!memcmp(val_string, test_value, CONF_MAX_VAL_LEN)); + } + + fa = cf.cf2_fcb.f_active_id; + rc = fcb_append_to_scratch(&cf.cf2_fcb); + TEST_ASSERT(rc == 0); + TEST_ASSERT(fcb_free_sector_cnt(&cf.cf2_fcb) == 0); + TEST_ASSERT(fa != cf.cf2_fcb.f_active_id); + + config_wipe_srcs(); + + memset(&cf, 0, sizeof(cf)); + + cf.cf2_fcb.f_magic = MYNEWT_VAL(CONFIG_FCB_MAGIC); + cf.cf2_fcb.f_range_cnt = CONF_TEST_FCB_RANGE_CNT; + cf.cf2_fcb.f_sector_cnt = fcb_range[0].fsr_sector_count; + cf.cf2_fcb.f_ranges = fcb_range; + + rc = conf_fcb2_src(&cf); + TEST_ASSERT(rc == 0); + + rc = conf_fcb2_dst(&cf); + TEST_ASSERT(rc == 0); + + TEST_ASSERT(fcb_free_sector_cnt(&cf.cf2_fcb) == 1); + TEST_ASSERT(fa == cf.cf2_fcb.f_active_id); + + c2_var_count = 0; +} diff --git a/sys/config/selftest-fcb2/src/testcases/config_test_custom_compress.c b/sys/config/selftest-fcb2/src/testcases/config_test_custom_compress.c new file mode 100644 index 0000000..2204a8f --- /dev/null +++ b/sys/config/selftest-fcb2/src/testcases/config_test_custom_compress.c @@ -0,0 +1,121 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +#include "conf_test_fcb2.h" + +static int unique_val_cnt; + +static int +test_custom_compress_filter1(const char *val, const char *name, void *arg) +{ + unique_val_cnt++; + return 0; +} + +static int +test_custom_compress_filter2(const char *val, const char *name, void *arg) +{ + if (!strcmp(val, "myfoo/mybar")) { + return 0; + } + return 1; +} + +TEST_CASE_SELF(config_test_custom_compress) +{ + int rc; + struct conf_fcb2 cf; + char test_value[CONF_TEST_FCB_VAL_STR_CNT][CONF_MAX_VAL_LEN]; + int elems[4]; + int i; + + config_wipe_srcs(); + config_wipe_fcb2(fcb_range, CONF_TEST_FCB_RANGE_CNT); + + cf.cf2_fcb.f_magic = MYNEWT_VAL(CONFIG_FCB_MAGIC); + cf.cf2_fcb.f_range_cnt = CONF_TEST_FCB_RANGE_CNT; + cf.cf2_fcb.f_sector_cnt = fcb_range[0].fsr_sector_count; + cf.cf2_fcb.f_ranges = fcb_range; + + rc = conf_fcb2_src(&cf); + TEST_ASSERT(rc == 0); + + rc = conf_fcb2_dst(&cf); + TEST_ASSERT(rc == 0); + + c2_var_count = 1; + test_export_block = 0; + val8 = 4; + val64 = 8; + memset(elems, 0, sizeof(elems)); + + for (i = 0; ; i++) { + config_test_fill_area(test_value, i); + memcpy(val_string, test_value, sizeof(val_string)); + + rc = conf_save(); + TEST_ASSERT(rc == 0); + + if (cf.cf2_fcb.f_active_id == fcb_range[0].fsr_sector_count - 2) { + /* + * Started using space just before scratch. + */ + break; + } + memset(val_string, 0, sizeof(val_string)); + + rc = conf_load(); + TEST_ASSERT(rc == 0); + TEST_ASSERT(!memcmp(val_string, test_value, CONF_MAX_VAL_LEN)); + } + + for (i = 0; i < cf.cf2_fcb.f_sector_cnt - 1; i++) { + conf_fcb2_compress(&cf, test_custom_compress_filter1, NULL); + } + TEST_ASSERT(unique_val_cnt == 4); /* c2, c3 and ctest together */ + + test_export_block = 1; + + /* + * Read values back, make sure they were carried over. + */ + memset(val_string, 0, sizeof(val_string)); + val8 = 0; + val64 = 0; + rc = conf_load(); + TEST_ASSERT(rc == 0); + TEST_ASSERT(!memcmp(val_string, test_value, CONF_MAX_VAL_LEN)); + TEST_ASSERT(val8 == 4); + TEST_ASSERT(val64 == 8); + + /* + * Only leave one var. + */ + for (i = 0; i < cf.cf2_fcb.f_sector_cnt - 1; i++) { + conf_fcb2_compress(&cf, test_custom_compress_filter2, NULL); + } + + memset(val_string, 0, sizeof(val_string)); + val8 = 0; + val64 = 0; + rc = conf_load(); + TEST_ASSERT(rc == 0); + TEST_ASSERT(val_string[0][0] == 0); + TEST_ASSERT(val8 == 4); + TEST_ASSERT(val64 == 0); +} diff --git a/sys/config/selftest-fcb2/src/testcases/config_test_empty_fcb.c b/sys/config/selftest-fcb2/src/testcases/config_test_empty_fcb.c new file mode 100644 index 0000000..c2d28c5 --- /dev/null +++ b/sys/config/selftest-fcb2/src/testcases/config_test_empty_fcb.c @@ -0,0 +1,44 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +#include "conf_test_fcb2.h" + +TEST_CASE_SELF(config_test_empty_fcb) +{ + int rc; + struct conf_fcb2 cf; + + config_wipe_srcs(); + config_wipe_fcb2(fcb_range, CONF_TEST_FCB_RANGE_CNT); + + cf.cf2_fcb.f_magic = MYNEWT_VAL(CONFIG_FCB_MAGIC); + cf.cf2_fcb.f_range_cnt = CONF_TEST_FCB_RANGE_CNT; + cf.cf2_fcb.f_sector_cnt = fcb_range[0].fsr_sector_count; + cf.cf2_fcb.f_ranges = fcb_range; + + rc = conf_fcb2_src(&cf); + TEST_ASSERT(rc == 0); + + /* + * No values + */ + conf_load(); + + config_wipe_srcs(); + ctest_clear_call_state(); +} diff --git a/sys/config/selftest-fcb2/src/testcases/config_test_get_stored.c b/sys/config/selftest-fcb2/src/testcases/config_test_get_stored.c new file mode 100644 index 0000000..3be6c89 --- /dev/null +++ b/sys/config/selftest-fcb2/src/testcases/config_test_get_stored.c @@ -0,0 +1,78 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +#include "conf_test_fcb2.h" + +TEST_CASE_SELF(config_test_get_stored_fcb) +{ + int rc; + struct conf_fcb2 cf; + char stored_val[32]; + + config_wipe_srcs(); + config_wipe_fcb2(fcb_range, CONF_TEST_FCB_RANGE_CNT); + + cf.cf2_fcb.f_magic = MYNEWT_VAL(CONFIG_FCB_MAGIC); + cf.cf2_fcb.f_range_cnt = CONF_TEST_FCB_RANGE_CNT; + cf.cf2_fcb.f_sector_cnt = fcb_range[0].fsr_sector_count; + cf.cf2_fcb.f_ranges = fcb_range; + + rc = conf_fcb2_src(&cf); + TEST_ASSERT(rc == 0); + + rc = conf_fcb2_dst(&cf); + TEST_ASSERT(rc == 0); + + test_export_block = 0; + val8 = 33; + rc = conf_save(); + TEST_ASSERT(rc == 0); + + /* + * Nonexistent key + */ + rc = conf_get_stored_value("random/name", stored_val, sizeof(stored_val)); + TEST_ASSERT(rc == OS_ENOENT); + + rc = conf_get_stored_value("myfoo/mybar", stored_val, sizeof(stored_val)); + TEST_ASSERT(rc == 0); + TEST_ASSERT(atoi(stored_val) == 33); + + rc = conf_save_one("myfoo/mybar", "42"); + TEST_ASSERT(rc == 0); + + rc = conf_get_stored_value("myfoo/mybar", stored_val, sizeof(stored_val)); + TEST_ASSERT(rc == 0); + TEST_ASSERT(atoi(stored_val) == 42); + + val8 = 31; + rc = conf_save(); + TEST_ASSERT(rc == 0); + + rc = conf_get_stored_value("myfoo/mybar", stored_val, sizeof(stored_val)); + TEST_ASSERT(rc == 0); + TEST_ASSERT(atoi(stored_val) == 31); + + /* + * Too small of a buffer + */ + rc = conf_get_stored_value("myfoo/mybar", stored_val, 1); + TEST_ASSERT(rc == OS_EINVAL); + + test_export_block = 1; +} diff --git a/sys/config/selftest-fcb2/src/testcases/config_test_getset_bytes.c b/sys/config/selftest-fcb2/src/testcases/config_test_getset_bytes.c new file mode 100644 index 0000000..b757f53 --- /dev/null +++ b/sys/config/selftest-fcb2/src/testcases/config_test_getset_bytes.c @@ -0,0 +1,49 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +#include "conf_test_fcb2.h" + +TEST_CASE_SELF(config_test_getset_bytes) +{ + char orig[32]; + char bytes[32]; + char str[48]; + char *ret; + int j, i; + int tmp; + int rc; + + for (j = 1; j < sizeof(orig); j++) { + for (i = 0; i < j; i++) { + orig[i] = i + j + 1; + } + ret = conf_str_from_bytes(orig, j, str, sizeof(str)); + TEST_ASSERT(ret); + tmp = strlen(str); + TEST_ASSERT(tmp < sizeof(str)); + + memset(bytes, 0, sizeof(bytes)); + tmp = sizeof(bytes); + + tmp = sizeof(bytes); + rc = conf_bytes_from_str(str, bytes, &tmp); + TEST_ASSERT(rc == 0); + TEST_ASSERT(tmp == j); + TEST_ASSERT(!memcmp(orig, bytes, j)); + } +} diff --git a/sys/config/selftest-fcb2/src/testcases/config_test_getset_int.c b/sys/config/selftest-fcb2/src/testcases/config_test_getset_int.c new file mode 100644 index 0000000..3e2d61a --- /dev/null +++ b/sys/config/selftest-fcb2/src/testcases/config_test_getset_int.c @@ -0,0 +1,40 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +#include "conf_test_fcb2.h" + +TEST_CASE_SELF(config_test_getset_int) +{ + char name[80]; + char tmp[64], *str; + int rc; + + strcpy(name, "myfoo/mybar"); + rc = conf_set_value(name, "42"); + TEST_ASSERT(rc == 0); + TEST_ASSERT(test_set_called == 1); + TEST_ASSERT(val8 == 42); + ctest_clear_call_state(); + + strcpy(name, "myfoo/mybar"); + str = conf_get_value(name, tmp, sizeof(tmp)); + TEST_ASSERT(str); + TEST_ASSERT(test_get_called == 1); + TEST_ASSERT(!strcmp("42", tmp)); + ctest_clear_call_state(); +} diff --git a/sys/config/selftest-fcb2/src/testcases/config_test_getset_int64.c b/sys/config/selftest-fcb2/src/testcases/config_test_getset_int64.c new file mode 100644 index 0000000..147f5a2 --- /dev/null +++ b/sys/config/selftest-fcb2/src/testcases/config_test_getset_int64.c @@ -0,0 +1,56 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +#include "conf_test_fcb2.h" + +TEST_CASE_SELF(config_test_getset_int64) +{ + char name[80]; + char tmp[64], *str; + int rc; + int64_t cmp; + + strcpy(name, "myfoo/mybar64"); + rc = conf_set_value(name, "-9218247941279444428"); + TEST_ASSERT(rc == 0); + TEST_ASSERT(test_set_called == 1); + cmp = 0x8012345678901234; + TEST_ASSERT(memcmp(&val64, &cmp, sizeof(val64)) == 0); + ctest_clear_call_state(); + + strcpy(name, "myfoo/mybar64"); + str = conf_get_value(name, tmp, sizeof(tmp)); + TEST_ASSERT(str); + TEST_ASSERT(test_get_called == 1); + TEST_ASSERT(!strcmp("-9218247941279444428", tmp)); + ctest_clear_call_state(); + + strcpy(name, "myfoo/mybar64"); + rc = conf_set_value(name, "1"); + TEST_ASSERT(rc == 0); + TEST_ASSERT(test_set_called == 1); + TEST_ASSERT(val64 == 1); + ctest_clear_call_state(); + + strcpy(name, "myfoo/mybar64"); + str = conf_get_value(name, tmp, sizeof(tmp)); + TEST_ASSERT(str); + TEST_ASSERT(test_get_called == 1); + TEST_ASSERT(!strcmp("1", tmp)); + ctest_clear_call_state(); +} diff --git a/sys/config/selftest-fcb2/src/testcases/config_test_getset_unknown.c b/sys/config/selftest-fcb2/src/testcases/config_test_getset_unknown.c new file mode 100644 index 0000000..cd21a82 --- /dev/null +++ b/sys/config/selftest-fcb2/src/testcases/config_test_getset_unknown.c @@ -0,0 +1,48 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +#include "conf_test_fcb2.h" + +TEST_CASE_SELF(config_test_getset_unknown) +{ + char name[80]; + char tmp[64], *str; + int rc; + + strcpy(name, "foo/bar"); + rc = conf_set_value(name, "tmp"); + TEST_ASSERT(rc != 0); + TEST_ASSERT(ctest_get_call_state() == 0); + + strcpy(name, "foo/bar"); + str = conf_get_value(name, tmp, sizeof(tmp)); + TEST_ASSERT(str == NULL); + TEST_ASSERT(ctest_get_call_state() == 0); + + strcpy(name, "myfoo/bar"); + rc = conf_set_value(name, "tmp"); + TEST_ASSERT(rc == OS_ENOENT); + TEST_ASSERT(test_set_called == 1); + ctest_clear_call_state(); + + strcpy(name, "myfoo/bar"); + str = conf_get_value(name, tmp, sizeof(tmp)); + TEST_ASSERT(str == NULL); + TEST_ASSERT(test_get_called == 1); + ctest_clear_call_state(); +} diff --git a/sys/config/selftest-fcb2/src/testcases/config_test_save_1_fcb.c b/sys/config/selftest-fcb2/src/testcases/config_test_save_1_fcb.c new file mode 100644 index 0000000..43ab8de --- /dev/null +++ b/sys/config/selftest-fcb2/src/testcases/config_test_save_1_fcb.c @@ -0,0 +1,48 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +#include "conf_test_fcb2.h" + +TEST_CASE_SELF(config_test_save_1_fcb) +{ + int rc; + struct conf_fcb2 cf; + + config_wipe_srcs(); + + cf.cf2_fcb.f_magic = MYNEWT_VAL(CONFIG_FCB_MAGIC); + cf.cf2_fcb.f_range_cnt = CONF_TEST_FCB_RANGE_CNT; + cf.cf2_fcb.f_sector_cnt = fcb_range[0].fsr_sector_count; + cf.cf2_fcb.f_ranges = fcb_range; + + rc = conf_fcb2_src(&cf); + TEST_ASSERT(rc == 0); + + rc = conf_fcb2_dst(&cf); + TEST_ASSERT(rc == 0); + + val8 = 33; + rc = conf_save(); + TEST_ASSERT(rc == 0); + + val8 = 0; + + rc = conf_load(); + TEST_ASSERT(rc == 0); + TEST_ASSERT(val8 == 33); +} diff --git a/sys/config/selftest-fcb2/src/testcases/config_test_save_2_fcb.c b/sys/config/selftest-fcb2/src/testcases/config_test_save_2_fcb.c new file mode 100644 index 0000000..da9c0cb --- /dev/null +++ b/sys/config/selftest-fcb2/src/testcases/config_test_save_2_fcb.c @@ -0,0 +1,87 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +#include "conf_test_fcb2.h" + +TEST_CASE_SELF(config_test_save_2_fcb) +{ + int rc; + struct conf_fcb2 cf; + char test_value[CONF_TEST_FCB_VAL_STR_CNT][CONF_MAX_VAL_LEN]; + int i; + + config_wipe_srcs(); + + cf.cf2_fcb.f_magic = MYNEWT_VAL(CONFIG_FCB_MAGIC); + cf.cf2_fcb.f_range_cnt = CONF_TEST_FCB_RANGE_CNT; + cf.cf2_fcb.f_sector_cnt = fcb_range[0].fsr_sector_count; + cf.cf2_fcb.f_ranges = fcb_range; + + rc = conf_fcb2_src(&cf); + TEST_ASSERT(rc == 0); + + rc = conf_fcb2_dst(&cf); + TEST_ASSERT(rc == 0); + + config_test_fill_area(test_value, 0); + memcpy(val_string, test_value, sizeof(val_string)); + + val8 = 42; + rc = conf_save(); + TEST_ASSERT(rc == 0); + + val8 = 0; + memset(val_string[0], 0, sizeof(val_string[0])); + rc = conf_load(); + TEST_ASSERT(rc == 0); + TEST_ASSERT(val8 == 42); + TEST_ASSERT(!strcmp(val_string[0], test_value[0])); + test_export_block = 1; + + /* + * Now add the number of settings to max. Keep adjusting the test_data, + * check that rollover happens when it's supposed to. + */ + c2_var_count = 64; + + for (i = 0; i < 32; i++) { + config_test_fill_area(test_value, i); + memcpy(val_string, test_value, sizeof(val_string)); + + rc = conf_save(); + TEST_ASSERT(rc == 0); + + memset(val_string, 0, sizeof(val_string)); + + val8 = 0; + rc = conf_load(); + TEST_ASSERT(rc == 0); + { + int i; + + for (i = 0; i < sizeof(val_string); i++) { + if (((char *)val_string)[i] != (((char *)test_value)[i])) { + printf("diff at off %d\n", i); + } + } + } + TEST_ASSERT(!memcmp(val_string, test_value, sizeof(val_string))); + TEST_ASSERT(val8 == 42); + } + c2_var_count = 0; +} diff --git a/sys/config/selftest-fcb2/src/testcases/config_test_save_3_fcb.c b/sys/config/selftest-fcb2/src/testcases/config_test_save_3_fcb.c new file mode 100644 index 0000000..99cb89a --- /dev/null +++ b/sys/config/selftest-fcb2/src/testcases/config_test_save_3_fcb.c @@ -0,0 +1,53 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +#include "conf_test_fcb2.h" + +TEST_CASE_SELF(config_test_save_3_fcb) +{ + int rc; + struct conf_fcb2 cf; + int i; + + config_wipe_srcs(); + config_wipe_fcb2(fcb_range, CONF_TEST_FCB_RANGE_CNT); + + cf.cf2_fcb.f_magic = MYNEWT_VAL(CONFIG_FCB_MAGIC); + cf.cf2_fcb.f_range_cnt = CONF_TEST_FCB_RANGE_CNT; + cf.cf2_fcb.f_sector_cnt = fcb_range[0].fsr_sector_count; + cf.cf2_fcb.f_ranges = fcb_range; + + rc = conf_fcb2_src(&cf); + TEST_ASSERT(rc == 0); + + rc = conf_fcb2_dst(&cf); + TEST_ASSERT(rc == 0); + + for (i = 0; i < 4096; i++) { + val32 = i; + + rc = conf_save(); + TEST_ASSERT(rc == 0); + + val32 = 0; + + rc = conf_load(); + TEST_ASSERT(rc == 0); + TEST_ASSERT(val32 == i); + } +} diff --git a/sys/config/selftest-fcb2/src/testcases/config_test_save_one_fcb.c b/sys/config/selftest-fcb2/src/testcases/config_test_save_one_fcb.c new file mode 100644 index 0000000..1ae9915 --- /dev/null +++ b/sys/config/selftest-fcb2/src/testcases/config_test_save_one_fcb.c @@ -0,0 +1,57 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +#include "conf_test_fcb2.h" + +TEST_CASE_SELF(config_test_save_one_fcb) +{ + int rc; + struct conf_fcb2 cf; + + config_wipe_srcs(); + config_wipe_fcb2(fcb_range, CONF_TEST_FCB_RANGE_CNT); + + cf.cf2_fcb.f_magic = MYNEWT_VAL(CONFIG_FCB_MAGIC); + cf.cf2_fcb.f_range_cnt = CONF_TEST_FCB_RANGE_CNT; + cf.cf2_fcb.f_sector_cnt = fcb_range[0].fsr_sector_count; + cf.cf2_fcb.f_ranges = fcb_range; + + rc = conf_fcb2_src(&cf); + TEST_ASSERT(rc == 0); + + rc = conf_fcb2_dst(&cf); + TEST_ASSERT(rc == 0); + + val8 = 33; + rc = conf_save(); + TEST_ASSERT(rc == 0); + + rc = conf_save_one("myfoo/mybar", "42"); + TEST_ASSERT(rc == 0); + + rc = conf_load(); + TEST_ASSERT(rc == 0); + TEST_ASSERT(val8 == 42); + + rc = conf_save_one("myfoo/mybar", "44"); + TEST_ASSERT(rc == 0); + + rc = conf_load(); + TEST_ASSERT(rc == 0); + TEST_ASSERT(val8 == 44); +} diff --git a/sys/config/pkg.yml b/sys/config/selftest-fcb2/syscfg.yml similarity index 54% copy from sys/config/pkg.yml copy to sys/config/selftest-fcb2/syscfg.yml index 93fe279..87e8798 100644 --- a/sys/config/pkg.yml +++ b/sys/config/selftest-fcb2/syscfg.yml @@ -1,4 +1,3 @@ -# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information @@ -6,7 +5,7 @@ # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at -# +# # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, @@ -17,24 +16,9 @@ # under the License. # -pkg.name: sys/config -pkg.description: Configuration management for embedded systems. -pkg.author: "Apache Mynewt <[email protected]>" -pkg.homepage: "http://mynewt.apache.org/" -pkg.keywords: - -pkg.deps: - - "@apache-mynewt-core/encoding/base64" -pkg.deps.CONFIG_CLI: - - "@apache-mynewt-core/sys/shell" -pkg.deps.CONFIG_NEWTMGR: - - "@apache-mynewt-core/encoding/cborattr" - - "@apache-mynewt-core/mgmt/mgmt" -pkg.deps.CONFIG_FCB: - - "@apache-mynewt-core/fs/fcb" -pkg.deps.CONFIG_NFFS: - - "@apache-mynewt-core/fs/nffs" - -pkg.init: - config_pkg_init: 'MYNEWT_VAL(CONFIG_SYSINIT_STAGE_1)' - config_pkg_init_stage2: 'MYNEWT_VAL(CONFIG_SYSINIT_STAGE_2)' +syscfg.vals: + CONFIG_FCB2: 1 + CONFIG_FCB: 0 + CONFIG_AUTO_INIT: 0 + MCU_FLASH_STYLE_ST: 1 + MCU_FLASH_STYLE_NORDIC: 0 diff --git a/sys/config/src/config_fcb2.c b/sys/config/src/config_fcb2.c new file mode 100644 index 0000000..f3627ae --- /dev/null +++ b/sys/config/src/config_fcb2.c @@ -0,0 +1,356 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#include <os/mynewt.h> + +#if MYNEWT_VAL(CONFIG_FCB2) + +#include <fcb/fcb.h> +#include <string.h> + +#include "config/config.h" +#include "config/config_store.h" +#include "config/config_fcb2.h" +#include "config/config_generic_kv.h" +#include "config_priv.h" + +#define CONF_FCB2_VERS 2 + +struct conf_fcb2_load_cb_arg { + conf_store_load_cb cb; + void *cb_arg; +}; + +struct conf_kv_load_cb_arg { + const char *name; + char *value; + size_t len; +}; + +static int conf_fcb2_load(struct conf_store *, conf_store_load_cb cb, + void *cb_arg); +static int conf_fcb2_save(struct conf_store *, const char *name, + const char *value); + +static struct conf_store_itf conf_fcb2_itf = { + .csi_load = conf_fcb2_load, + .csi_save = conf_fcb2_save, +}; + +int +conf_fcb2_src(struct conf_fcb2 *cf) +{ + int rc; + + cf->cf2_fcb.f_version = CONF_FCB2_VERS; + if (cf->cf2_fcb.f_sector_cnt > 1) { + cf->cf2_fcb.f_scratch_cnt = 1; + } else { + cf->cf2_fcb.f_scratch_cnt = 0; + } + while (1) { + rc = fcb_init(&cf->cf2_fcb); + if (rc) { + return OS_INVALID_PARM; + } + + /* + * Check if system was reset in middle of emptying a sector. This + * situation is recognized by checking if the scratch block is missing. + */ + if (cf->cf2_fcb.f_scratch_cnt && + fcb_free_sector_cnt(&cf->cf2_fcb) < 1) { + fcb_sector_erase(&cf->cf2_fcb, cf->cf2_fcb.f_active.fe_sector); + } else { + break; + } + } + + cf->cf2_store.cs_itf = &conf_fcb2_itf; + conf_src_register(&cf->cf2_store); + + return OS_OK; +} + +int +conf_fcb2_dst(struct conf_fcb2 *cf) +{ + cf->cf2_store.cs_itf = &conf_fcb2_itf; + conf_dst_register(&cf->cf2_store); + + return OS_OK; +} + +static int +conf_fcb2_load_cb(struct fcb_entry *loc, void *arg) +{ + struct conf_fcb2_load_cb_arg *argp; + char buf[CONF_MAX_NAME_LEN + CONF_MAX_VAL_LEN + 32]; + char *name_str; + char *val_str; + int rc; + int len; + + argp = (struct conf_fcb2_load_cb_arg *)arg; + + len = loc->fe_data_len; + if (len >= sizeof(buf)) { + len = sizeof(buf) - 1; + } + + rc = fcb_read(loc, 0, buf, len); + if (rc) { + return 0; + } + buf[len] = '\0'; + + rc = conf_line_parse(buf, &name_str, &val_str); + if (rc) { + return 0; + } + argp->cb(name_str, val_str, argp->cb_arg); + return 0; +} + +static int +conf_fcb2_load(struct conf_store *cs, conf_store_load_cb cb, void *cb_arg) +{ + struct conf_fcb2 *cf = (struct conf_fcb2 *)cs; + struct conf_fcb2_load_cb_arg arg; + int rc; + + arg.cb = cb; + arg.cb_arg = cb_arg; + rc = fcb_walk(&cf->cf2_fcb, FCB_SECTOR_OLDEST, conf_fcb2_load_cb, &arg); + if (rc) { + return OS_EINVAL; + } + return OS_OK; +} + +static int +conf_fcb2_var_read(struct fcb_entry *loc, char *buf, char **name, char **val) +{ + int rc; + + rc = fcb_read(loc, 0, buf, loc->fe_data_len); + if (rc) { + return rc; + } + buf[loc->fe_data_len] = '\0'; + rc = conf_line_parse(buf, name, val); + return rc; +} + +static void +conf_fcb2_compress_internal(struct fcb *fcb, + int (*copy_or_not)(const char *name, const char *val, + void *cn_arg), + void *cn_arg) +{ + int rc; + char buf1[CONF_MAX_NAME_LEN + CONF_MAX_VAL_LEN + 32]; + char buf2[CONF_MAX_NAME_LEN + CONF_MAX_VAL_LEN + 32]; + struct fcb_entry loc1; + struct fcb_entry loc2; + char *name1, *val1; + char *name2, *val2; + int copy; + + rc = fcb_append_to_scratch(fcb); + if (rc) { + return; /* XXX */ + } + + loc1.fe_range = NULL; + loc1.fe_entry_num = 0; + while (fcb_getnext(fcb, &loc1) == 0) { + if (loc1.fe_sector != fcb->f_oldest_sec) { + break; + } + rc = conf_fcb2_var_read(&loc1, buf1, &name1, &val1); + if (rc) { + continue; + } + if (!val1) { + continue; + } + loc2 = loc1; + copy = 1; + while (fcb_getnext(fcb, &loc2) == 0) { + rc = conf_fcb2_var_read(&loc2, buf2, &name2, &val2); + if (rc) { + continue; + } + if (!strcmp(name1, name2)) { + copy = 0; + break; + } + } + if (!copy) { + continue; + } + + if (copy_or_not) { + if (copy_or_not(name1, val1, cn_arg)) { + /* Copy rejected */ + continue; + } + } + /* + * Can't find one. Must copy. + */ + rc = fcb_read(&loc1, 0, buf1, loc1.fe_data_len); + if (rc) { + continue; + } + rc = fcb_append(fcb, loc1.fe_data_len, &loc2); + if (rc) { + continue; + } + rc = fcb_write(&loc2, 0, buf1, loc1.fe_data_len); + if (rc) { + continue; + } + fcb_append_finish(&loc2); + } + rc = fcb_rotate(fcb); + if (rc) { + /* XXXX */ + ; + } +} + +static int +conf_fcb2_append(struct fcb *fcb, char *buf, int len) +{ + int rc; + int i; + struct fcb_entry loc; + + for (i = 0; i < 10; i++) { + rc = fcb_append(fcb, len, &loc); + if (rc != FCB_ERR_NOSPACE) { + break; + } + if (fcb->f_scratch_cnt == 0) { + return OS_ENOMEM; + } + conf_fcb2_compress_internal(fcb, NULL, NULL); + } + if (rc) { + return OS_EINVAL; + } + rc = fcb_write(&loc, 0, buf, len); + if (rc) { + return OS_EINVAL; + } + fcb_append_finish(&loc); + return OS_OK; +} + +static int +conf_fcb2_save(struct conf_store *cs, const char *name, const char *value) +{ + struct conf_fcb2 *cf = (struct conf_fcb2 *)cs; + + return conf_fcb_kv_save(&cf->cf2_fcb, name, value); +} + +void +conf_fcb2_compress(struct conf_fcb2 *cf, + int (*copy_or_not)(const char *name, const char *val, + void *cn_arg), + void *cn_arg) +{ + conf_fcb2_compress_internal(&cf->cf2_fcb, copy_or_not, cn_arg); +} + +static int +conf_kv_load_cb(struct fcb_entry *loc, void *arg) +{ + struct conf_kv_load_cb_arg *cb_arg = arg; + char buf[CONF_MAX_NAME_LEN + CONF_MAX_VAL_LEN + 32]; + char *name_str; + char *val_str; + int rc; + int len; + + len = loc->fe_data_len; + if (len >= sizeof(buf)) { + len = sizeof(buf) - 1; + } + + rc = fcb_read(loc, 0, buf, len); + if (rc) { + return 0; + } + buf[len] = '\0'; + + rc = conf_line_parse(buf, &name_str, &val_str); + if (rc) { + return 0; + } + + if (strcmp(name_str, cb_arg->name)) { + return 0; + } + + strncpy(cb_arg->value, val_str, cb_arg->len); + cb_arg->value[cb_arg->len - 1] = '\0'; + + return 0; +} + +int +conf_fcb_kv_load(struct fcb *fcb, const char *name, char *value, size_t len) +{ + struct conf_kv_load_cb_arg arg; + int rc; + + arg.name = name; + arg.value = value; + arg.len = len; + + rc = fcb_walk(fcb, 0, conf_kv_load_cb, &arg); + if (rc) { + return OS_EINVAL; + } + + return OS_OK; +} + +int +conf_fcb_kv_save(struct fcb *fcb, const char *name, const char *value) +{ + char buf[CONF_MAX_NAME_LEN + CONF_MAX_VAL_LEN + 32]; + int len; + + if (!name) { + return OS_INVALID_PARM; + } + + len = conf_line_make(buf, sizeof(buf), name, value); + if (len < 0 || len + 2 > sizeof(buf)) { + return OS_INVALID_PARM; + } + return conf_fcb2_append(fcb, buf, len); +} + +#endif diff --git a/sys/config/src/config_init.c b/sys/config/src/config_init.c index 9a3f9e3..ca5cccc 100644 --- a/sys/config/src/config_init.c +++ b/sys/config/src/config_init.c @@ -88,6 +88,44 @@ config_init_fcb(void) SYSINIT_PANIC_ASSERT(rc == 0); } +#elif MYNEWT_VAL(CONFIG_FCB2) + +#include "fcb/fcb.h" +#include "config/config_fcb2.h" + +static struct flash_sector_range config_init_fcb2_sector_range; +static struct conf_fcb2 config_init_conf_fcb2 = { + .cf2_fcb.f_magic = MYNEWT_VAL(CONFIG_FCB_MAGIC), + .cf2_fcb.f_range_cnt = 1, + .cf2_fcb.f_ranges = &config_init_fcb2_sector_range +}; + +static void +config_init_fcb2(void) +{ + int cnt; + int rc; + + cnt = 1; + rc = flash_area_to_sector_ranges(MYNEWT_VAL(CONFIG_FCB_FLASH_AREA), &cnt, + &config_init_fcb2_sector_range); + SYSINIT_PANIC_ASSERT(rc == 0); + + config_init_conf_fcb2.cf2_fcb.f_sector_cnt = + config_init_fcb2_sector_range.fsr_sector_count; + + rc = conf_fcb2_src(&config_init_conf_fcb2); + if (rc) { + flash_area_erase(&config_init_fcb2_sector_range.fsr_flash_area, 0, + config_init_fcb2_sector_range.fsr_sector_count * + config_init_fcb2_sector_range.fsr_sector_size); + rc = conf_fcb2_src(&config_init_conf_fcb2); + } + SYSINIT_PANIC_ASSERT(rc == 0); + rc = conf_fcb2_dst(&config_init_conf_fcb2); + SYSINIT_PANIC_ASSERT(rc == 0); +} + #endif #endif @@ -104,6 +142,8 @@ config_pkg_init(void) config_init_fs(); #elif MYNEWT_VAL(CONFIG_FCB) config_init_fcb(); +#elif MYNEWT_VAL(CONFIG_FCB2) + config_init_fcb2(); #endif #endif } diff --git a/sys/config/syscfg.yml b/sys/config/syscfg.yml index b3995f7..684f962 100644 --- a/sys/config/syscfg.yml +++ b/sys/config/syscfg.yml @@ -22,12 +22,21 @@ syscfg.defs: value: 0 restrictions: - '!CONFIG_NFFS' + - '!CONFIG_FCB2' - 'CONFIG_FCB_FLASH_AREA' CONFIG_NFFS: description: 'Config default storage is in NFFS' value: 0 restrictions: - '!CONFIG_FCB' + - '!CONFIG_FCB2' + CONFIG_FCB2: + description: 'Config default storage is in FCB2' + value: 0 + restrictions: + - '!CONFIG_FCB' + - '!CONFIG_NFFS' + - 'CONFIG_FCB_FLASH_AREA' CONFIG_NEWTMGR: description: 'Newtmgr access to config' value: 0 @@ -63,7 +72,7 @@ syscfg.defs: Config CLI commands read 1, write 2, read/write 3 value: 3 -syscfg.defs.CONFIG_FCB: +syscfg.defs.(CONFIG_FCB || CONFIG_FCB2): CONFIG_FCB_FLASH_AREA: description: 'BSP flash area for config' type: 'flash_owner'
