Skip to content

Conversation

@MichelRottleuthner
Copy link
Contributor

Contribution description

Bumps the FlashDB package to current master and improves the test a bit.
The current version in RIOT has a bug in the file-based storage implementation. The bug breaks the libc based file access and therefore breaks the file-based mode on all boards except native, which uses the posix mode file access.

During testing I noticed the test apps are not easy to interpret on the first look. They also don't actually work on real hardware. The test in master swallows most errors silently and in most cases doesn't check return codes. Some values were not persisted across reboots (e.g., the boot_counter) as they got lost somewhere in the cache.

I added some output to the test that makes it easier to see if something went wrong. Explicitly calling the de-init functions of FlashDB in the test application fixes the issue with the broken persistence.

Testing procedure

To test on a board you should make sure the persistent storage is clean, for example:
make BOARD=adafruit-feather-nrf52840-sense -C tests/sys/vfs_default all flash term
Then format through the RIOT shell:

> vfs umount /nvm0
> format /nvm0

Run the flashdb_vfs test:
USEMODULE=test_utils_interactive_sync make BOARD=adafruit-feather-nrf52840-sense -C tests/pkg/flashdb_vfs all flash term

# START
# main(): This is RIOT! (Version: 2026.01-devel-158-g522b2-flashdb_test_fixes)
# mkdir '/nvm0/fdb_kvdb1' [OK]
# ==================== kvdb_basic_sample ====================
# get the 'boot_count' value is 0 [OK]
# set the 'boot_count' value to 1 [OK]
# get the 'boot_count' value is 1 [OK]
# ===========================================================
# ================= kvdb_type_string_sample =================
# create the 'temp' string KV, value is: 36C [OK]
# get the 'temp' value is: 36C [OK]
# set 'temp' value to 38C [OK]
# delete the 'temp' finish [OK]
# ===========================================================
# ================== kvdb_type_blob_sample ==================
# create the 'temp' blob KV, value is: 36 [OK]
# get the 'temp' value is: 36 [OK]
# set 'temp' value to 38 [OK]
# delete the 'temp' finish [OK]
# ===========================================================
# kvdb deinit [OK]
# mkdir '/nvm0/fdb_tsdb1' [OK]
# ======================= tsdb_sample =======================
# append the new status.temp (36) and status.humi (85) [OK]
# append the new status.temp (38) and status.humi (90) [OK]
# [query_cb] queried a TSL: time: 11, temp: 36, humi: 85 [OK]
# [query_cb] queried a TSL: time: 12, temp: 38, humi: 90 [OK]
# [query_by_time_cb] queried a TSL: time: 11, temp: 36, humi: 85 [OK]
# [query_by_time_cb] queried a TSL: time: 12, temp: 38, humi: 90 [OK]
# query count is: 2
# set the TSL (time 11) status from 2 to 3 [OK]
# set the TSL (time 12) status from 2 to 3 [OK]
# ===========================================================
# tsdb deinit [OK]

smash that reset button

# START
# main(): This is RIOT! (Version: 2026.01-devel-158-g522b2-flashdb_test_fixes)
# mkdir '/nvm0/fdb_kvdb1' [OK]
# ==================== kvdb_basic_sample ====================
# get the 'boot_count' value is 1 [OK]
# set the 'boot_count' value to 2 [OK]
# get the 'boot_count' value is 2 [OK]
# ===========================================================
# ================= kvdb_type_string_sample =================
# create the 'temp' string KV, value is: 36C [OK]
# get the 'temp' value is: 36C [OK]
# set 'temp' value to 38C [OK]
# delete the 'temp' finish [OK]
# ===========================================================
# ================== kvdb_type_blob_sample ==================
# create the 'temp' blob KV, value is: 36 [OK]
# get the 'temp' value is: 36 [OK]
# set 'temp' value to 38 [OK]
# delete the 'temp' finish [OK]
# ===========================================================
# kvdb deinit [OK]
# mkdir '/nvm0/fdb_tsdb1' [OK]
# ======================= tsdb_sample =======================
# append the new status.temp (36) and status.humi (85) [FAILED]
# append the new status.temp (38) and status.humi (90) [FAILED]
# [query_cb] queried a TSL: time: 11, temp: 36, humi: 85 [OK]
# [query_cb] queried a TSL: time: 12, temp: 38, humi: 90 [OK]
# [query_by_time_cb] queried a TSL: time: 11, temp: 36, humi: 85 [OK]
# [query_by_time_cb] queried a TSL: time: 12, temp: 38, humi: 90 [OK]
# query count is: 0
# set the TSL (time 11) status from 3 to 3 [OK]
# set the TSL (time 12) status from 3 to 3 [OK]
# ===========================================================
# tsdb deinit [OK]

Same for tests/pkg/flashdb_mtd. Both applications should also work on native (for me they did).

Note that the failure with the time series append operations happens due to the dummy timer implementation of the test. That also happened before but wasn't visible.

Issues/PRs references

The package repo actually some more tests. We should probably integrate those in the future instead of the simplified examples we currently have as our tests.

@MichelRottleuthner MichelRottleuthner added the Type: bug The issue reports a bug / The PR fixes a bug (including spelling errors) label Nov 20, 2025
@MichelRottleuthner MichelRottleuthner added the Area: pkg Area: External package ports label Nov 20, 2025
@github-actions github-actions bot added the Area: tests Area: tests and testing framework label Nov 20, 2025
@MichelRottleuthner
Copy link
Contributor Author

squashed fixups

@leandrolanzieri leandrolanzieri added the CI: ready for build If set, CI server will compile all applications for all available boards for the labeled PR label Nov 20, 2025
Copy link
Contributor

@leandrolanzieri leandrolanzieri left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice! Thanks for this.

Do you mind applying the static check suggestions now that we're touching the file anyway? I'll run this on hardware tomorrow.

@riot-ci
Copy link

riot-ci commented Nov 20, 2025

Murdock results

✔️ PASSED

367d796 fixup! tests/pkg/flashdb_vfs: improve tsdb_sample test and output

Success Failures Total Runtime
10932 0 10932 10m:02s

Artifacts

/* create database directory */
vfs_mkdir(FDB_DIR "/fdb_tsdb1", 0777);
int res = vfs_mkdir(TSDB_DIR, 0777);
printf("mkdir '%s' %s", TSDB_DIR, resstr(res == 0 || res == -EEXIST));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any particular reason to return if there's an error while creating a directory for the KVDB and not here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch!, I just forgot to also add it here. Fixed.

The stacksize was not large enough to run this on an embedded target with flash based mtd and littlefs2.
The test now checks return values for expected values and reports issues to the user.
Without this change, some changes to the persistent storage (e.g., with
littlefs2 on mtd_spi_nor) are not actually written back to the 'disk'.
The boot_count in the example was therefore not persistent across reboots.
Deinitializing solves this by properly closing all open files.
This bumps the package version to the current master as the most recent release
has a bug in the LIBC-flavour of the file-based storage backend. Without this
fix the file-based sotrage is therefore not usable on any target other than
native.
{ /* GET the KV value */
/* get the "boot_count" KV value */
fdb_kv_get_blob(kvdb, "boot_count", fdb_blob_make(&blob, &boot_count, sizeof(boot_count)));
/* the blob.saved.len is more than 0 when get the value successful */
Copy link
Contributor

@mguetschow mguetschow Nov 21, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was under the impression most (all?) the tests were taken from their docs: https://armink.github.io/FlashDB/#/sample-kvdb-basic

I haven't done so yet, but maybe you could double-check if they have changed in the meantime. Nevertheless, it definitely makes sense to catch return values.

Will try to have a closer look at it today or beginning of next week.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right, makes sense to check that. And yes, the tests look like a straight copy of the package examples. Maybe it makes sense to also upstream that later. The FlashDB repo has no changes compared to the version currently used in RIOT (git diff --name-only b1043ed10defdeec6f97c4099cb212a777a727fe 2.1.1 tests samples in the FlashDB repo lists nothing). As I pointed out in the PR description in the long run it would probably be better to replace our tests with the the package tests instead of using the examples for testing. But the changes of this PR already grew bigger than I anticipated for a quick version bump ;)

Copy link
Contributor

@mguetschow mguetschow left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice! Smaller nit's below. Now that we have the [OK] values, it wouldn't be to hard to add a Python test for it (maybe in a follow-up PR, though) :)

Comment on lines +79 to +83
/* converts a test condition to a human readable string */
const char *resstr(bool condition)
{
return condition ? "[OK]" : "[FAILED]";
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why no static inline function in a header file that can be included in the c files instead of explicitly declaring extern resstr everywhere?

/* change the "boot_count" KV's value */
fdb_kv_set_blob(kvdb, "boot_count", fdb_blob_make(&blob, &boot_count, sizeof(boot_count)));
printf("set the 'boot_count' value to %d\n", boot_count);
int res = fdb_kv_set_blob(kvdb, "boot_count",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
int res = fdb_kv_set_blob(kvdb, "boot_count",
fdb_err_t res = fdb_kv_set_blob(kvdb, "boot_count",

is the correct return type

{ /* GET the KV value */
int expected = boot_count;
/* get the "boot_count" KV value */
int res = fdb_kv_get_blob(kvdb, "boot_count",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
int res = fdb_kv_get_blob(kvdb, "boot_count",
size_t res = fdb_kv_get_blob(kvdb, "boot_count",

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(could also be its own function as this is basically duplicated from above)

USEMODULE += vfs_auto_format

CFLAGS += -DTHREAD_STACKSIZE_MAIN=THREAD_STACKSIZE_LARGE
CFLAGS += -DTHREAD_STACKSIZE_MAIN=THREAD_STACKSIZE_LARGE*2
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why is this a new requirement?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Area: pkg Area: External package ports Area: tests Area: tests and testing framework CI: ready for build If set, CI server will compile all applications for all available boards for the labeled PR Type: bug The issue reports a bug / The PR fixes a bug (including spelling errors)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants