This is an automated email from the ASF dual-hosted git repository.
utzig pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/mynewt-core.git
The following commit(s) were added to refs/heads/master by this push:
new 3ff50ac apps: fs_test: Add filesystem testing application
new 617b9c3 Merge pull request #2527 from utzig/apps-fs-test
3ff50ac is described below
commit 3ff50ac1b58121d4598354c135c8562dad2131b6
Author: Fabio Utzig <[email protected]>
AuthorDate: Fri Mar 12 07:18:46 2021 -0300
apps: fs_test: Add filesystem testing application
The fs_test app exercises all defined `fs/fs` interfaces, and is useful
when adding new filesystems' support or debugging filesystem issues.
Signed-off-by: Fabio Utzig <[email protected]>
---
apps/fs_test/pkg.yml | 38 ++++
apps/fs_test/src/littlefs.c | 51 +++++
apps/fs_test/src/main.c | 452 ++++++++++++++++++++++++++++++++++++++++++++
apps/fs_test/src/nffs.c | 39 ++++
apps/fs_test/syscfg.yml | 41 ++++
5 files changed, 621 insertions(+)
diff --git a/apps/fs_test/pkg.yml b/apps/fs_test/pkg.yml
new file mode 100644
index 0000000..af1d493
--- /dev/null
+++ b/apps/fs_test/pkg.yml
@@ -0,0 +1,38 @@
+#
+# 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.
+#
+
+pkg.name: apps/fs_test
+pkg.type: app
+pkg.description: "Exercise an FS using the standard FS interface."
+pkg.author: "Apache Mynewt <[email protected]>"
+pkg.homepage: "http://mynewt.apache.org/"
+pkg.keywords:
+
+pkg.deps:
+ - "@apache-mynewt-core/kernel/os"
+ - "@apache-mynewt-core/sys/console/full"
+ - "@apache-mynewt-core/sys/log/full"
+ - "@apache-mynewt-core/sys/log/modlog"
+
+pkg.deps.FS_TEST_NFFS:
+ - "@apache-mynewt-core/sys/stats/full"
+ - "@apache-mynewt-core/fs/nffs"
+
+pkg.deps.FS_TEST_LITTLEFS:
+ - "@apache-mynewt-core/fs/littlefs"
diff --git a/apps/fs_test/src/littlefs.c b/apps/fs_test/src/littlefs.c
new file mode 100644
index 0000000..74604d1
--- /dev/null
+++ b/apps/fs_test/src/littlefs.c
@@ -0,0 +1,51 @@
+/*
+ * 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(FS_TEST_LITTLEFS)
+
+#if !MYNEWT_VAL(LITTLEFS_FLASH_AREA)
+#error "No LITTLEFS_FLASH_AREA defined"
+#endif
+
+#include "littlefs/lfs.h"
+
+int littlefs_reformat(void);
+int littlefs_init(void);
+
+int
+fs_lowlevel_init(void)
+{
+ int rc;
+
+ (void)rc;
+
+ /* always force format before starting */
+#if MYNEWT_VAL(FS_TEST_FORCE_REFORMAT)
+ rc = littlefs_reformat();
+ if (rc) {
+ return rc;
+ }
+#endif
+
+ return littlefs_init();
+}
+
+#endif
diff --git a/apps/fs_test/src/main.c b/apps/fs_test/src/main.c
new file mode 100644
index 0000000..7246a94
--- /dev/null
+++ b/apps/fs_test/src/main.c
@@ -0,0 +1,452 @@
+/*
+ * 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"
+#include <bsp/bsp.h>
+#include <hal/hal_flash.h>
+#include <console/console.h>
+#include <log/log.h>
+#include "flash_map/flash_map.h"
+#include <fs/fs.h>
+#include <hal/hal_gpio.h>
+#include <assert.h>
+#include <string.h>
+#include <stdint.h>
+#include <stdbool.h>
+#include <stdio.h>
+
+#ifdef ARCH_sim
+#include <mcu/mcu_sim.h>
+#endif
+
+#define BLINKY_PRIO (8)
+#define BLINKY_STACK_SIZE OS_STACK_ALIGN(64)
+static struct os_task blinky_task;
+
+#define FS_TEST_PRIO (9)
+#define FS_TEST_STACK_SIZE OS_STACK_ALIGN(2048)
+static struct os_task fs_test_task;
+
+#if !MYNEWT_VAL(FS_TEST_LITTLEFS) && !MYNEWT_VAL(FS_TEST_NFFS)
+#error "No filesystem selected, or unsupported FS!"
+#endif
+
+static char *random_strings[] = {
+ "Q4qrwYFQIzCj8JsjxIVQIywAWkkFo2kk",
+ "sEIdSP7uG6XkJr3ZkOCYPL8Rj80gGPVe2w",
+ "idZNVRMBuaYP3E8CSL36NXYpGPj5ED",
+ "000o2PHKjvxfV4AuvDaqye2QPJK7269",
+ "R3Xg4daYGr",
+};
+
+/* Root directory where files will be created */
+static const char *dirformat = "fs_test_%d";
+
+#define STARTUP_DELAY MYNEWT_VAL(FS_TEST_STARTUP_DELAY)
+#define MAX_TEST_FILES MYNEWT_VAL(FS_TEST_MAX_FILES)
+
+#define BLINK_NORMAL (OS_TICKS_PER_SEC)
+#define BLINK_SLOW (OS_TICKS_PER_SEC * 2)
+#define BLINK_FAST (OS_TICKS_PER_SEC / 2)
+static uint32_t g_blink_freq = BLINK_NORMAL;
+
+static int
+fs_test_create_directory(char *dirname)
+{
+ char name[20];
+ int i;
+ int rc;
+
+ i = 0;
+ while (true) {
+ sprintf(name, dirformat, i);
+ rc = fs_mkdir(name);
+ if (rc != FS_EEXIST) {
+ break;
+ }
+ i++;
+ }
+
+ if (rc == FS_EOK) {
+ printf("Created new test directory (%s)\n", name);
+ strcpy(dirname, name);
+ } else {
+ printf("Failed creating test directory (%d)\n", rc);
+ }
+
+ return rc;
+}
+
+static int
+fs_test_write_files(char *root)
+{
+ int i;
+ char name[30];
+ struct fs_file *file = NULL;
+ char *string;
+ uint32_t len;
+ int rc;
+
+ for (i = 0; i < MAX_TEST_FILES; i++) {
+ sprintf(name, "%s/test_%d", root, i);
+ string = random_strings[i % ARRAY_SIZE(random_strings)];
+ len = strlen(string);
+
+ printf("Opening new file (%s) for writing... ", name);
+ rc = fs_open(name, FS_ACCESS_WRITE | FS_ACCESS_TRUNCATE, &file);
+ if (rc != 0) {
+ printf("fail (%d)\n", rc);
+ return -1;
+ }
+ printf("ok\n");
+
+ printf("Writing data to new file... ");
+ rc = fs_write(file, string, len);
+ if (rc != 0) {
+ printf("fail (%d)\n", rc);
+ fs_close(file);
+ return -1;
+ }
+ printf("ok\n");
+
+ fs_close(file);
+ }
+
+ return 0;
+}
+
+static int
+fs_test_read_files(char *root)
+{
+ int i;
+ char name[30];
+ char buf[45];
+ struct fs_file *file = NULL;
+ char *string;
+ uint32_t len;
+ uint32_t outlen;
+ uint32_t pos;
+ int rc;
+
+ for (i = 0; i < MAX_TEST_FILES; i++) {
+ sprintf(name, "%s/test_%d", root, i);
+ string = random_strings[i % ARRAY_SIZE(random_strings)];
+ len = strlen(string);
+
+ printf("Opening new file (%s) for reading... ", name);
+ rc = fs_open(name, FS_ACCESS_READ, &file);
+ if (rc != 0) {
+ printf("fail (%d)\n", rc);
+ printf("Failed opening for reading: %d\n", rc);
+ return rc;
+ }
+ printf("ok\n");
+
+ printf("Getting file length... ");
+ rc = fs_filelen(file, &outlen);
+ if (rc != 0) {
+ printf("fail (%d)\n", rc);
+ fs_close(file);
+ return rc;
+ }
+ printf("ok (%ld)\n", outlen);
+
+ if (len != outlen) {
+ printf("%s has an unexpected length (%lu!=%lu)\n", name, len,
outlen);
+ fs_close(file);
+ return -1;
+ }
+
+ pos = fs_getpos(file);
+ if (pos != 0) {
+ printf("Invalid position (%lu), should be (0)\n", pos);
+ fs_close(file);
+ return -1;
+ }
+
+ printf("Reading from file... ");
+ memset(buf, 0, sizeof(buf));
+ rc = fs_read(file, len, buf, &outlen);
+ if (rc != 0) {
+ printf("fail (%d)\n", rc);
+ fs_close(file);
+ return rc;
+ }
+ printf("ok\n");
+
+ printf("Compare read results... ");
+ if (strncmp(buf, string, len) != 0) {
+ printf("fail\n");
+ fs_close(file);
+ return -1;
+ }
+ printf("ok\n");
+
+ pos = fs_getpos(file);
+ if (pos != len) {
+ printf("Invalid position (%lu), should be (%lu)\n", pos, len);
+ fs_close(file);
+ return -1;
+ }
+
+ printf("Seek to middle position of file... ");
+ rc = fs_seek(file, len / 2);
+ if (rc != 0) {
+ printf("fail (%d)\n", rc);
+ fs_close(file);
+ return rc;
+ }
+ printf("ok\n");
+
+ pos = fs_getpos(file);
+ if (pos != len / 2) {
+ printf("Invalid position (%lu), should be (%lu)\n", pos, len / 2);
+ fs_close(file);
+ return -1;
+ }
+
+ printf("Reading again... ");
+ memset(buf, 0, sizeof(buf));
+ rc = fs_read(file, len / 2, buf, &outlen);
+ if (rc != 0) {
+ printf("fail (%d)\n", rc);
+ fs_close(file);
+ return -1;
+ }
+ printf("ok\n");
+
+ printf("Comparing read results... ");
+ if (strncmp(buf, &string[len / 2], len / 2) != 0) {
+ printf("fail\n");
+ fs_close(file);
+ return -1;
+ }
+ printf("ok\n");
+
+ fs_close(file);
+ }
+
+ return 0;
+}
+
+static int
+fs_test_rename_files(char *root)
+{
+ int i;
+ char name[30];
+ char new_name[30];
+ int rc;
+
+ for (i = 0; i < MAX_TEST_FILES; i++) {
+ sprintf(name, "%s/test_%d", root, i);
+ sprintf(new_name, "%s/tested_%d", root, i);
+
+ printf("Renaming (%s) to (%s)... ", name, new_name);
+ rc = fs_rename(name, new_name);
+ if (rc != 0) {
+ printf("fail (%d)\n", rc);
+ return -1;
+ }
+ printf("ok\n");
+ }
+
+ return 0;
+}
+
+static int
+fs_test_read_directory(char *root)
+{
+ struct fs_dir *dir;
+ struct fs_dirent *dirent;
+ char name[40];
+ uint8_t out_len;
+ int rc;
+
+ printf("Opening (%s) directory... ", root);
+ rc = fs_opendir(root, &dir);
+ if (rc != 0) {
+ printf("fail (%d)\n", rc);
+ return -1;
+ }
+ printf("ok\n");
+
+ do {
+ printf("Reading directory entry... ");
+ rc = fs_readdir(dir, &dirent);
+ if (rc == FS_ENOENT) {
+ printf("ok\n");
+ rc = 0;
+ break;
+ } else if (rc != 0) {
+ printf("fail (%d)\n", rc);
+ rc = -1;
+ goto out;
+ }
+ printf("ok\n");
+
+ printf("Getting dirent information... ");
+ rc = fs_dirent_name(dirent, 40, name, &out_len);
+ if (rc != 0) {
+ printf("fail (%d)\n", rc);
+ rc = -1;
+ goto out;
+ }
+ printf("ok\n");
+
+ if (fs_dirent_is_dir(dirent)) {
+ printf("Found directory (%s)\n", name);
+ } else {
+ printf("Found file (%s)\n", name);
+ }
+ } while (1);
+
+out:
+ fs_closedir(dir);
+
+ return rc;
+}
+
+static int
+fs_test_cleanup(char *root)
+{
+ int i;
+ char name[30];
+ int rc;
+
+ memset(name, 0, sizeof(name));
+
+ for (i = 0; i < MAX_TEST_FILES; i++) {
+ sprintf(name, "%s/tested_%d", root, i);
+
+ printf("Removing file (%s)... ", name);
+ rc = fs_unlink(name);
+ if (rc != 0) {
+ printf("fail (%d)\n", rc);
+ return -1;
+ }
+ printf("ok\n");
+ }
+
+ printf("Remove directory (%s)... ", root);
+ rc = fs_unlink(root);
+ if (rc < 0) {
+ printf("fail (%d)\n", rc);
+ return -1;
+ }
+ printf("ok\n");
+
+ return 0;
+}
+
+extern int fs_lowlevel_init(void);
+
+static void
+fs_test_handler(void *arg)
+{
+ int rc;
+ char root[30];
+
+ g_blink_freq = BLINK_SLOW;
+
+ printf("Will start test in %d secs...\n", STARTUP_DELAY);
+ os_time_delay(STARTUP_DELAY * OS_TICKS_PER_SEC);
+
+ rc = fs_lowlevel_init();
+ if (rc == 0) {
+ rc = fs_test_create_directory(root);
+ }
+ if (rc == 0) {
+ rc = fs_test_write_files(root);
+ }
+ if (rc == 0) {
+ rc = fs_test_read_files(root);
+ }
+ if (rc == 0) {
+ rc = fs_test_rename_files(root);
+ }
+ if (rc == 0) {
+ rc = fs_test_read_directory(root);
+ }
+ if (rc == 0) {
+ rc = fs_test_cleanup(root);
+ }
+
+ if (rc) {
+ printf("Filesystem testing has failed\n");
+ g_blink_freq = BLINK_FAST;
+ } else {
+ printf("Filesystem testing was successful\n");
+ g_blink_freq = BLINK_NORMAL;
+ }
+
+ while (1) {
+ os_time_delay(1);
+ }
+}
+
+static void
+blinky_handler(void *arg)
+{
+ int led_pin;
+
+ led_pin = LED_BLINK_PIN;
+ hal_gpio_init_out(led_pin, 1);
+
+ while (1) {
+ os_time_delay(g_blink_freq);
+ hal_gpio_toggle(led_pin);
+ }
+}
+
+static void
+init_tasks(void)
+{
+ os_stack_t *pstack;
+
+ pstack = malloc(sizeof(*pstack) * FS_TEST_STACK_SIZE);
+ assert(pstack);
+
+ os_task_init(&fs_test_task, "fs_test", fs_test_handler, NULL,
+ FS_TEST_PRIO, OS_WAIT_FOREVER, pstack, FS_TEST_STACK_SIZE);
+
+ pstack = malloc(sizeof(*pstack) * BLINKY_STACK_SIZE);
+ assert(pstack);
+
+ os_task_init(&blinky_task, "blinky", blinky_handler, NULL,
+ BLINKY_PRIO, OS_WAIT_FOREVER, pstack, BLINKY_STACK_SIZE);
+}
+
+int
+main(int argc, char **argv)
+{
+#ifdef ARCH_sim
+ mcu_sim_parse_args(argc, argv);
+#endif
+
+ sysinit();
+
+ init_tasks();
+
+ /*
+ * As the last thing, process events from default event queue.
+ */
+ while (1) {
+ os_eventq_run(os_eventq_dflt_get());
+ }
+}
diff --git a/apps/fs_test/src/nffs.c b/apps/fs_test/src/nffs.c
new file mode 100644
index 0000000..6fdb502
--- /dev/null
+++ b/apps/fs_test/src/nffs.c
@@ -0,0 +1,39 @@
+/*
+ * 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(FS_TEST_NFFS)
+
+#if !MYNEWT_VAL(NFFS_FLASH_AREA)
+#error "No NFFS_FLASH_AREA defined"
+#endif
+
+#include "nffs/nffs.h"
+
+/*
+ * TODO: NFFS currently only supports formatting while mounting on sysinit
+ */
+int
+fs_lowlevel_init(void)
+{
+ return 0;
+}
+
+#endif
diff --git a/apps/fs_test/syscfg.yml b/apps/fs_test/syscfg.yml
new file mode 100644
index 0000000..596a8e5
--- /dev/null
+++ b/apps/fs_test/syscfg.yml
@@ -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.
+#
+
+syscfg.defs:
+ FS_TEST_NFFS:
+ description: 'Run tests on an NFFS partition'
+ value: 0
+ restrictions:
+ - '!FS_TEST_LITTLEFS'
+ FS_TEST_LITTLEFS:
+ description: 'Run tests on a LittleFS partition'
+ value: 0
+ restrictions:
+ - '!FS_TEST_NFFS'
+ FS_TEST_MAX_FILES:
+ description: 'Amount of files to create for read/write test'
+ value: 4
+ FS_TEST_FORCE_REFORMAT:
+ description: 'Always format the flash area before running'
+ value: 0
+ FS_TEST_STARTUP_DELAY:
+ description: 'Time to wait before starting the tests in seconds'
+ value: 0
+
+syscfg.vals.FS_TEST_LITTLEFS:
+ LITTLEFS_DISABLE_SYSINIT: 1