Skip to content
Permalink
Browse files
configfs: Add unit tests
Signed-off-by: Bart Van Assche <bvanassche@acm.org>
  • Loading branch information
bvanassche committed Jul 21, 2021
1 parent 0d18c12 commit a4fab8c72635f28d5d3f4d2ffae50e1bccd3ae8b
Show file tree
Hide file tree
Showing 3 changed files with 142 additions and 0 deletions.
@@ -10,3 +10,11 @@ config CONFIGFS_FS

Both sysfs and configfs can and should exist together on the
same system. One is not a replacement for the other.

config CONFIGFS_KUNIT_TEST
tristate "Configfs Kunit test" if !KUNIT_ALL_TESTS
depends on CONFIGFS_FS && KUNIT
default KUNIT_ALL_TESTS
help
Run the configfs unit test at boot time. For more information, see
also the Kunit documentation in Documentation/dev-tools/kunit/.
@@ -6,3 +6,5 @@
obj-$(CONFIG_CONFIGFS_FS) += configfs.o

configfs-objs := inode.o file.o dir.o symlink.o mount.o item.o

obj-$(CONFIG_CONFIGFS_KUNIT_TEST) += configfs-test.o
@@ -0,0 +1,132 @@
#include <kunit/test.h>
#include <linux/configfs.h>
#include <linux/fs.h>
#include <linux/uio.h>

enum { ATTR_MAX_SIZE = 256 };

struct configfs_test_item {
struct config_item item;
uint32_t nbytes;
char data[ATTR_MAX_SIZE];
};

static ssize_t bin_attr_read(struct config_item *item, void *buf, size_t len)
{
struct configfs_test_item *ti = container_of(item, typeof(*ti), item);

memcpy(buf, ti->data, ti->nbytes);
return ti->nbytes;
}

static ssize_t bin_attr_write(struct config_item *item, const void *buf,
size_t len)
{
struct configfs_test_item *ti = container_of(item, typeof(*ti), item);

if (len > ATTR_MAX_SIZE)
return -EINVAL;
ti->nbytes = len;
memcpy(ti->data, buf, len);
return len;
}

CONFIGFS_BIN_ATTR(, bin_attr, NULL, ATTR_MAX_SIZE);

static struct configfs_bin_attribute *bin_attrs[] = {
&attr_bin_attr,
NULL,
};

static ssize_t text_attr_show(struct config_item *item, char *buf)
{
return bin_attr_read(item, buf, strlen(buf));
}

static ssize_t text_attr_store(struct config_item *item, const char *buf,
size_t size)
{
return bin_attr_write(item, buf, size);
}

CONFIGFS_ATTR(, text_attr);

static struct configfs_attribute *text_attrs[] = {
&attr_text_attr,
NULL,
};

static const struct config_item_type test_configfs_type = {
.ct_owner = THIS_MODULE,
.ct_bin_attrs = bin_attrs,
.ct_attrs = text_attrs,
};

static void configfs_text_attr(struct kunit *test)
{
struct file *f = filp_open("/sys/kernel/config/unit-test/text_attr",
O_RDWR, 0);
static const char text1[] =
"The quick brown fox jumps over the lazy dog";
const int off1 = 0;
const int len1 = strlen(text1);
static const char text2[] = "slow-";
const int off2 = 4;
const int len2 = strlen(text2);
int res;
loff_t pos;

KUNIT_EXPECT_TRUE(test, !IS_ERR(f));
if (IS_ERR(f))
return;
pos = off1;
res = kernel_write(f, text1, len1, &pos);
KUNIT_EXPECT_EQ(test, res, len1);
KUNIT_EXPECT_EQ(test, pos, off1 + len1);
pos = off2;
res = kernel_write(f, text2, len2, &pos);
KUNIT_EXPECT_EQ(test, res, len2);
KUNIT_EXPECT_EQ(test, pos, off2 + len2);
filp_close(f, NULL);
}

static void configfs_bin_attr(struct kunit *test)
{
KUNIT_EXPECT_EQ(test, 0, 0);
}

static struct kunit_case configfs_test_cases[] = {
KUNIT_CASE(configfs_text_attr),
KUNIT_CASE(configfs_bin_attr),
{},
};

static struct configfs_subsystem test_subsys = {
.su_group = {
.cg_item = {
.ci_namebuf = "unit-test",
.ci_type = &test_configfs_type,
}
},
};

static int configfs_test_init(struct kunit *test)
{
config_group_init(&test_subsys.su_group);
mutex_init(&test_subsys.su_mutex);
return configfs_register_subsystem(&test_subsys);
}

static void configfs_test_exit(struct kunit *test)
{
configfs_unregister_subsystem(&test_subsys);
}

static struct kunit_suite configfs_test_module = {
.name = "configfs unit tests",
.init = configfs_test_init,
.exit = configfs_test_exit,
.name = "configfs-kunit-test",
.test_cases = configfs_test_cases,
};
kunit_test_suites(&configfs_test_module);

0 comments on commit a4fab8c

Please sign in to comment.