* [PATCH 3/4] test: self: add ramfs test
2022-10-10 6:14 [PATCH 1/4] test: self: change CONFIG_CMD_SELFTEST default to y Ahmad Fatoum
2022-10-10 6:14 ` [PATCH 2/4] test: self: always build envvar test when SELFTEST_ENABLE_ALL Ahmad Fatoum
@ 2022-10-10 6:14 ` Ahmad Fatoum
2022-10-10 6:14 ` [PATCH 4/4] fs: implement unreaddir Ahmad Fatoum
2022-10-11 15:02 ` [PATCH 1/4] test: self: change CONFIG_CMD_SELFTEST default to y Sascha Hauer
3 siblings, 0 replies; 5+ messages in thread
From: Ahmad Fatoum @ 2022-10-10 6:14 UTC (permalink / raw)
To: barebox; +Cc: Ahmad Fatoum
Add some simple testing for ramfs: creating a directory, filling it with
files, writing some data into them, unlinking some files again, reading
data out of them, iterating over the files and cleaning up the directory
again.
Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
test/self/Kconfig | 5 ++
test/self/Makefile | 1 +
test/self/ramfs.c | 189 +++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 195 insertions(+)
create mode 100644 test/self/ramfs.c
diff --git a/test/self/Kconfig b/test/self/Kconfig
index 4bf4b874d5e4..052b49972329 100644
--- a/test/self/Kconfig
+++ b/test/self/Kconfig
@@ -33,6 +33,7 @@ config SELFTEST_ENABLE_ALL
select SELFTEST_PROGRESS_NOTIFIER
select SELFTEST_OF_MANIPULATION
select SELFTEST_ENVIRONMENT_VARIABLES
+ select SELFTEST_FS_RAMFS
help
Selects all self-tests compatible with current configuration
@@ -58,4 +59,8 @@ config SELFTEST_PROGRESS_NOTIFIER
config SELFTEST_ENVIRONMENT_VARIABLES
bool "environment variable selftest"
+config SELFTEST_FS_RAMFS
+ bool "ramfs selftest"
+ depends on FS_RAMFS
+
endif
diff --git a/test/self/Makefile b/test/self/Makefile
index ca9f9c34d1e5..6f2c0d394034 100644
--- a/test/self/Makefile
+++ b/test/self/Makefile
@@ -6,3 +6,4 @@ obj-$(CONFIG_SELFTEST_PRINTF) += printf.o
obj-$(CONFIG_SELFTEST_PROGRESS_NOTIFIER) += progress-notifier.o
obj-$(CONFIG_SELFTEST_OF_MANIPULATION) += of_manipulation.o of_manipulation.dtb.o
obj-$(CONFIG_SELFTEST_ENVIRONMENT_VARIABLES) += envvar.o
+obj-$(CONFIG_FS_RAMFS) += ramfs.o
diff --git a/test/self/ramfs.c b/test/self/ramfs.c
new file mode 100644
index 000000000000..927b035e1e8c
--- /dev/null
+++ b/test/self/ramfs.c
@@ -0,0 +1,189 @@
+// SPDX-License-Identifier: GPL-2.0-only
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <common.h>
+#include <fcntl.h>
+#include <fs.h>
+#include <dirent.h>
+#include <libfile.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <bselftest.h>
+#include <linux/sizes.h>
+
+BSELFTEST_GLOBALS();
+
+#define __expect(_ret, _cond, fmt, ...) ({ \
+ bool cond = (_cond); \
+ int ret = (_ret); \
+ total_tests++; \
+ \
+ if (!cond) { \
+ failed_tests++; \
+ printf("%s:%d error %pe: " fmt "\n", \
+ __func__, __LINE__, ERR_PTR(ret), ##__VA_ARGS__); \
+ } \
+ cond; \
+})
+
+#define expect_success(ret, ...) __expect((ret), (ret) >= 0, __VA_ARGS__)
+#define expect_fail(ret, ...) __expect((ret), (ret) < 0, __VA_ARGS__)
+
+static inline int get_file_count(int i)
+{
+ if (40 <= i && i < 50)
+ return 40;
+
+ if (i >= 50)
+ i -= 10;
+
+ /* we create a file for i == 0 as well */
+ return i + 1;
+}
+
+static void test_ramfs(void)
+{
+ char fname[128];
+ char *content = NULL;
+ char *oldpwd = NULL;
+ DIR *dir = NULL;
+ const char *dname;
+ struct stat st;
+ int i, j, ret, fd;
+ struct dirent *d;
+
+ dname = make_temp("ramfs-test");
+ ret = mkdir(dname, 0777);
+
+ if (!expect_success(ret, "creating directory"))
+ return;
+
+ ret = stat(dname, &st);
+ if (!expect_success(ret, "stating directory"))
+ goto out;
+
+ expect_success(S_ISDIR(st.st_mode) ? 0 : -ENOTDIR,
+ "directory check");
+
+ content = malloc(99);
+ if (WARN_ON(!content))
+ goto out;
+
+ for (i = 0; i < 99; i++) {
+ scnprintf(fname, sizeof(fname), "%s/file-%02d", dname, i);
+
+ fd = open(fname, O_RDWR | O_CREAT);
+ if (!expect_success(fd, "creating file"))
+ continue;
+
+ for (j = 0; j < i; j++)
+ content[j] = i;
+
+ ret = write(fd, content, i);
+ expect_success(ret, "writing file");
+ close(fd);
+
+ if (40 <= i && i < 50) {
+ ret = unlink(fname);
+ expect_success(ret, "unlinking file");
+ }
+
+ ret = stat(fname, &st);
+ if (40 <= i && i < 50) {
+ expect_fail(ret, "stating file");
+ } else {
+ expect_success(ret, "stating file");
+
+ expect_success(S_ISREG(st.st_mode) ? 0 : -EINVAL,
+ "stating file");
+ }
+
+ dir = opendir(dname);
+ if (!expect_success(PTR_ERR_OR_ZERO(dir), "opening parent directory"))
+ continue;
+
+ j = 0;
+
+ while ((d = readdir(dir))) {
+ if (!strcmp(d->d_name, ".") || !strcmp(d->d_name, ".."))
+ continue;
+
+ j++;
+ }
+
+ expect_success(j == get_file_count(i) ? 0 : -EINVAL,
+ "unexpected file count iterating directory");
+
+ closedir(dir);
+ }
+
+ oldpwd = pushd(dname);
+ if (!expect_success(oldpwd != NULL ? 0 : -EINVAL, "pushd()"))
+ goto out;;
+
+ dir = opendir(".");
+ if (!expect_success(PTR_ERR_OR_ZERO(dir), "opening parent directory"))
+ goto out;
+
+ i = 1;
+
+ while ((d = readdir(dir))) {
+ size_t size = 0;
+ char *buf;
+
+ if (!strcmp(d->d_name, ".") || !strcmp(d->d_name, ".."))
+ continue;
+
+ buf = read_file(d->d_name, &size);
+ if (size) {
+ for (j = 0; j < size; j++) {
+ expect_success(buf[j] == size ? 0 : -EINVAL,
+ "unexpected file content");
+ }
+ }
+
+ scnprintf(fname, sizeof(fname), "file-%02zu", size);
+
+ expect_success(strcmp(d->d_name, fname) == 0 ? 0 : -EINVAL,
+ "unexpected file content");
+
+ free(buf);
+
+ i++;
+ }
+
+ expect_success(i == 90 ? 0 : -EINVAL,
+ "unexpected file count iterating directory: %u", i);
+
+ ret = make_directory("test/a/b/c/d/e/f/g/h/i/j/k/l");
+ expect_success(ret, "make_directory()");
+
+ if (!ret) {
+ const char hello[] = "hello";
+ char *buf;
+
+ ret = write_file("test/a/b/c/d/e/f/g/h/i/j/k/l/FILE",
+ ARRAY_AND_SIZE(hello));
+ expect_success(ret, "write_file()");
+
+ buf = read_file("test/a/b/c/d/e/f/g/h/i/j/k/l/FILE", NULL);
+ if (expect_success(PTR_ERR_OR_ZERO(buf), "read_file()")) {
+ expect_success(memcmp(buf, ARRAY_AND_SIZE(hello)),
+ "read_file() content");
+ }
+ }
+
+out:
+ popd(oldpwd);
+ free(content);
+
+ closedir(dir);
+
+ ret = unlink_recursive(dname, NULL);
+ expect_success(ret, "unlinking directory");
+
+ dir = opendir(dname);
+ expect_fail(dir ? 0 : -EISDIR, "opening removed directory");
+}
+bselftest(core, test_ramfs);
--
2.30.2
^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH 4/4] fs: implement unreaddir
2022-10-10 6:14 [PATCH 1/4] test: self: change CONFIG_CMD_SELFTEST default to y Ahmad Fatoum
2022-10-10 6:14 ` [PATCH 2/4] test: self: always build envvar test when SELFTEST_ENABLE_ALL Ahmad Fatoum
2022-10-10 6:14 ` [PATCH 3/4] test: self: add ramfs test Ahmad Fatoum
@ 2022-10-10 6:14 ` Ahmad Fatoum
2022-10-11 15:02 ` [PATCH 1/4] test: self: change CONFIG_CMD_SELFTEST default to y Sascha Hauer
3 siblings, 0 replies; 5+ messages in thread
From: Ahmad Fatoum @ 2022-10-10 6:14 UTC (permalink / raw)
To: barebox; +Cc: Ahmad Fatoum
When iterating over a directory, it can be useful to put back the just
read directory entry, so it can be retried at a later time. This will be
needed for the EFI loader variable support.
Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
fs/fs.c | 15 +++++++++++++++
include/dirent.h | 1 +
test/self/ramfs.c | 17 ++++++++++++++++-
3 files changed, 32 insertions(+), 1 deletion(-)
diff --git a/fs/fs.c b/fs/fs.c
index 620cd6597a63..6583e0a6e9b3 100644
--- a/fs/fs.c
+++ b/fs/fs.c
@@ -890,6 +890,21 @@ static int fillonedir(struct dir_context *ctx, const char *name, int namlen,
return 0;
}
+int unreaddir(DIR *dir, const struct dirent *d)
+{
+ struct readdir_entry *entry;
+
+ if (d != &dir->d)
+ return -EINVAL;
+
+ entry = xzalloc(sizeof(*entry));
+ entry->d = *d;
+ list_add_tail(&entry->list, &dir->entries);
+
+ return 0;
+}
+EXPORT_SYMBOL(unreaddir);
+
struct dirent *readdir(DIR *dir)
{
struct readdir_entry *entry;
diff --git a/include/dirent.h b/include/dirent.h
index 61a76c5b59b9..285074e9f7de 100644
--- a/include/dirent.h
+++ b/include/dirent.h
@@ -18,6 +18,7 @@ typedef struct dir {
DIR *opendir(const char *pathname);
struct dirent *readdir(DIR *dir);
+int unreaddir(DIR *dir, const struct dirent *d);
int closedir(DIR *dir);
#endif /* __DIRENT_H */
diff --git a/test/self/ramfs.c b/test/self/ramfs.c
index 927b035e1e8c..f8e1d60a61b5 100644
--- a/test/self/ramfs.c
+++ b/test/self/ramfs.c
@@ -44,6 +44,7 @@ static inline int get_file_count(int i)
static void test_ramfs(void)
{
+ int files[] = { 1, 3, 5, 7, 11, 13, 17 };
char fname[128];
char *content = NULL;
char *oldpwd = NULL;
@@ -127,6 +128,7 @@ static void test_ramfs(void)
goto out;
i = 1;
+ j = 0;
while ((d = readdir(dir))) {
size_t size = 0;
@@ -150,7 +152,20 @@ static void test_ramfs(void)
free(buf);
- i++;
+ /*
+ * For select files, we test unreaddir once and check if
+ * we read back same element on repeated readdir
+ */
+ for (j = 0; j < ARRAY_SIZE(files); j++) {
+ if (size == files[j]) {
+ ret = unreaddir(dir, d);
+ expect_success(ret, "unreaddir");
+ files[j] = -1;
+ break;
+ }
+ }
+ if (j == ARRAY_SIZE(files))
+ i++;
}
expect_success(i == 90 ? 0 : -EINVAL,
--
2.30.2
^ permalink raw reply [flat|nested] 5+ messages in thread