]> www.infradead.org Git - mtd-utils.git/commitdiff
Add unittest for libmtd
authorDaniel Walter <dwalter@sigma-star.at>
Wed, 31 Aug 2016 08:08:30 +0000 (10:08 +0200)
committerDavid Oberhollenzer <david.oberhollenzer@sigma-star.at>
Thu, 17 Nov 2016 10:36:56 +0000 (11:36 +0100)
unit tests for most functions provided by
libmtd.

Signed-off-by: Daniel Walter <dwalter@sigma-star.at>
tests/unittests/libmtd_test.c [new file with mode: 0644]

diff --git a/tests/unittests/libmtd_test.c b/tests/unittests/libmtd_test.c
new file mode 100644 (file)
index 0000000..fc28dc0
--- /dev/null
@@ -0,0 +1,491 @@
+#include <stdarg.h>
+#include <setjmp.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+#include <unistd.h>
+#include <cmocka.h>
+
+#include "mtd/mtd-user.h"
+#include "libmtd.h"
+#include "libmtd_int.h"
+
+#include "test_lib.h"
+
+static libmtd_t mock_libmtd_open()
+{
+       /* create a mock object for libmtd, not using sysfs */
+       expect_open(SYSFS_ROOT "/class/mtd/mtd0/name", O_RDONLY, 4);
+       expect_close(4,0);
+       libmtd_t lib = libmtd_open();
+       assert_non_null(lib);
+       return lib;
+}
+
+static void test_libmtd_open(void **state)
+{
+       expect_open(SYSFS_ROOT "/class/mtd/mtd0/name", O_RDONLY, 4);
+       expect_close(4,0);
+       struct libmtd *lib = libmtd_open();
+       assert_non_null(lib);
+       assert_string_equal(lib->sysfs_mtd, SYSFS_ROOT "/class/mtd");
+       assert_string_equal(lib->mtd, SYSFS_ROOT "/class/mtd/mtd%d");
+       assert_string_equal(lib->mtd_name, SYSFS_ROOT "/class/mtd/mtd%d/name");
+       assert_string_equal(lib->mtd_dev, SYSFS_ROOT "/class/mtd/mtd%d/dev");
+       assert_string_equal(lib->mtd_type, SYSFS_ROOT "/class/mtd/mtd%d/type");
+       assert_string_equal(lib->mtd_eb_size, SYSFS_ROOT "/class/mtd/mtd%d/erasesize");
+       assert_string_equal(lib->mtd_size, SYSFS_ROOT "/class/mtd/mtd%d/size");
+       assert_string_equal(lib->mtd_min_io_size, SYSFS_ROOT "/class/mtd/mtd%d/writesize");
+       assert_string_equal(lib->mtd_subpage_size, SYSFS_ROOT "/class/mtd/mtd%d/subpagesize");
+       assert_string_equal(lib->mtd_oob_size, SYSFS_ROOT "/class/mtd/mtd%d/oobsize");
+       assert_string_equal(lib->mtd_region_cnt, SYSFS_ROOT "/class/mtd/mtd%d/numeraseregions");
+       assert_string_equal(lib->mtd_flags, SYSFS_ROOT "/class/mtd/mtd%d/flags");
+
+       libmtd_close(lib);
+       (void) state;
+}
+
+static void test_mtd_dev_present(void **state)
+{
+       int ret;
+       libmtd_t lib = mock_libmtd_open();
+       expect_stat(SYSFS_ROOT "/class/mtd/mtd0", 0);
+       ret = mtd_dev_present(lib, 0);
+       assert_int_equal(ret, 1);
+       libmtd_close(lib);
+       (void) state;
+}
+
+static void test_mtd_mark_bad(void **state)
+{
+       struct mtd_dev_info mtd;
+       loff_t seek;
+       int eb = 12;
+       memset(&mtd, 0, sizeof(mtd));
+       mtd.bb_allowed = 1;
+       mtd.eb_cnt = 1024;
+       mtd.eb_size = 128;
+       seek = (loff_t)eb * mtd.eb_size;
+       expect_ioctl(MEMSETBADBLOCK, 0, &seek, sizeof(seek));
+       int r = mtd_mark_bad(&mtd, 4, eb);
+       assert_int_equal(r, 0);
+
+       (void) state;
+}
+
+static void test_mtd_is_bad(void **state)
+{
+       struct mtd_dev_info mtd;
+       loff_t seek;
+       int eb = 0x42;
+       memset(&mtd, 0, sizeof(mtd));
+       mtd.bb_allowed = 1;
+       mtd.eb_cnt = 1024;
+       mtd.eb_size = 128;
+       seek = (loff_t)eb * mtd.eb_size;
+       expect_ioctl(MEMGETBADBLOCK, 0, &seek, sizeof(seek));
+       int r = mtd_is_bad(&mtd, 4, eb);
+       assert_int_equal(r, 0);
+
+       (void) state;
+}
+
+static void test_mtd_lock(void **state)
+{
+       int eb = 0xBA;
+       struct mtd_dev_info mtd;
+       memset(&mtd, 0, sizeof(mtd));
+       mtd.bb_allowed = 1;
+       mtd.eb_cnt = 1024;
+       mtd.eb_size = 128;
+       struct erase_info_user ei;
+       memset(&ei, 0, sizeof(ei));
+       ei.start = eb * mtd.eb_size;
+       ei.length = mtd.eb_size;
+       expect_ioctl(MEMLOCK, 0, &ei, sizeof(ei));
+       int r = mtd_lock(&mtd, 4, eb);
+       assert_int_equal(r, 0);
+
+       (void) state;
+}
+
+static void test_mtd_unlock(void **state)
+{
+       int eb = 0xBA;
+       struct mtd_dev_info mtd;
+       memset(&mtd, 0, sizeof(mtd));
+       mtd.bb_allowed = 1;
+       mtd.eb_cnt = 1024;
+       mtd.eb_size = 128;
+       struct erase_info_user ei;
+       memset(&ei, 0, sizeof(ei));
+       ei.start = eb * mtd.eb_size;
+       ei.length = mtd.eb_size;
+       expect_ioctl(MEMUNLOCK, 0, &ei, sizeof(ei));
+       int r = mtd_unlock(&mtd, 4, eb);
+       assert_int_equal(r, 0);
+
+       (void) state;
+}
+
+static void test_mtd_is_locked(void **state)
+{
+       int eb = 0xBA;
+       struct mtd_dev_info mtd;
+       memset(&mtd, 0, sizeof(mtd));
+       mtd.bb_allowed = 1;
+       mtd.eb_cnt = 1024;
+       mtd.eb_size = 128;
+       struct erase_info_user ei;
+       memset(&ei, 0, sizeof(ei));
+       ei.start = eb * mtd.eb_size;
+       ei.length = mtd.eb_size;
+       expect_ioctl(MEMISLOCKED, 0, &ei, sizeof(ei));
+       int r = mtd_is_locked(&mtd, 4, eb);
+       assert_int_equal(r, 0);
+
+       (void) state;
+}
+
+static void test_mtd_regioninfo(void **state)
+{
+       struct region_info_user req;
+       struct region_info_user rr;
+       memset(&req, 0, sizeof(req));
+       memset(&rr, 0, sizeof(rr));
+       int mock_fd = 4;
+       int regidx = 0xAA;
+       rr.regionindex = regidx;
+       expect_ioctl(MEMGETREGIONINFO, 0, &rr, sizeof(rr));
+       int r = mtd_regioninfo(mock_fd, regidx, &req);
+       assert_int_equal(r, 0);
+
+       (void) state;
+}
+
+static void test_mtd_erase_multi(void **state)
+{
+       struct libmtd *lib = mock_libmtd_open();
+       struct mtd_dev_info mtd;
+       struct erase_info_user ei;
+       struct erase_info_user64 ei64;
+       int eb = 0x3C;
+       int blocks = 3;
+       memset(&ei, 0, sizeof(ei));
+       memset(&ei64, 0, sizeof(ei64));
+       memset(&mtd, 0, sizeof(mtd));
+       mtd.bb_allowed = 1;
+       mtd.eb_cnt = 1024;
+       mtd.eb_size = 128;
+       ei64.start = (uint64_t)eb * mtd.eb_size;
+       ei64.length = (uint64_t)mtd.eb_size * blocks;
+       ei.start = ei64.start;
+       ei.length = ei64.length;
+       /* non offs64 first */
+       lib->offs64_ioctls = OFFS64_IOCTLS_NOT_SUPPORTED;
+       expect_ioctl(MEMERASE, 0, &ei, sizeof(ei));
+       int r = mtd_erase_multi(lib, &mtd, 4, eb, blocks);
+       assert_int_equal(r, 0);
+
+       lib->offs64_ioctls = OFFS64_IOCTLS_SUPPORTED;
+       expect_ioctl(MEMERASE64, 0, &ei64, sizeof(ei64));
+       r = mtd_erase_multi(lib, &mtd, 4, eb, blocks);
+       assert_int_equal(r, 0);
+
+       libmtd_close(lib);
+       (void) state;
+}
+
+/* this is the same as above but with blocks == 1 and a
+ * different function call.
+ * libmtd is mapping mtd_erase to mtd_erase_multi with 1 block
+ */
+static void test_mtd_erase(void **state)
+{
+       struct libmtd *lib = mock_libmtd_open();
+       struct mtd_dev_info mtd;
+       struct erase_info_user ei;
+       struct erase_info_user64 ei64;
+       int eb = 0x3C;
+       int blocks = 1;
+       memset(&ei, 0, sizeof(ei));
+       memset(&ei64, 0, sizeof(ei64));
+       memset(&mtd, 0, sizeof(mtd));
+       mtd.bb_allowed = 1;
+       mtd.eb_cnt = 1024;
+       mtd.eb_size = 128;
+       ei64.start = (uint64_t)eb * mtd.eb_size;
+       ei64.length = (uint64_t)mtd.eb_size * blocks;
+       ei.start = ei64.start;
+       ei.length = ei64.length;
+       /* non offs64 first */
+       lib->offs64_ioctls = OFFS64_IOCTLS_NOT_SUPPORTED;
+       expect_ioctl(MEMERASE, 0, &ei, sizeof(ei));
+       int r = mtd_erase(lib, &mtd, 4, eb);
+       assert_int_equal(r, 0);
+
+       lib->offs64_ioctls = OFFS64_IOCTLS_SUPPORTED;
+       expect_ioctl(MEMERASE64, 0, &ei64, sizeof(ei64));
+       r = mtd_erase(lib, &mtd, 4, eb);
+       assert_int_equal(r, 0);
+
+       libmtd_close(lib);
+       (void) state;
+
+}
+
+static void test_mtd_read(void **state)
+{
+       int mock_fd = 4;
+       int eb = 0xE0;
+       int offs = 43;
+       int len = 28;
+       off_t seek;
+       char buf[28];
+       struct mtd_dev_info mtd;
+       memset(&mtd, 0, sizeof(mtd));
+       mtd.bb_allowed = 1;
+       mtd.eb_cnt = 1024;
+       mtd.eb_size = 128;
+       seek = (off_t)eb * mtd.eb_size + offs;
+       expect_lseek(seek, SEEK_SET, seek);
+       expect_read(len, len);
+       int r = mtd_read(&mtd, mock_fd, eb, offs, &buf, len);
+       assert_int_equal(r, 0);
+
+       (void) state;
+}
+
+static void test_mtd_write_nooob(void **state)
+{
+       struct libmtd *lib = mock_libmtd_open();
+       int mock_fd = 4;
+       int eb = 0xE0;
+       int offs = 64;
+       int len = 64;
+       off_t seek;
+       char buf[64];
+       memset(buf, 0xAA, len);
+       struct mtd_dev_info mtd;
+       memset(&mtd, 0, sizeof(mtd));
+       mtd.bb_allowed = 1;
+       mtd.eb_cnt = 1024;
+       mtd.eb_size = 128;
+       mtd.subpage_size = 64;
+       seek = (off_t)eb * mtd.eb_size + offs;
+       expect_lseek(seek, SEEK_SET, seek);
+       expect_write(buf, len, len);
+       int r = mtd_write(lib, &mtd, mock_fd, eb, offs, buf, len, NULL, 0, 0);
+       assert_int_equal(r, 0);
+
+       libmtd_close(lib);
+       (void)state;
+}
+
+static void test_mtd_write_withoob(void **state)
+{
+       struct libmtd *lib = mock_libmtd_open();
+       int mock_fd = 4;
+       int eb = 0xE0;
+       int offs = 64;
+       int len = 64;
+       int oob_len = 64;
+       uint8_t mode = 3;
+       off_t seek;
+       char buf[64], oob_data[64];
+       struct mtd_dev_info mtd;
+       struct mtd_write_req req;
+       memset(buf, 0xAA, len);
+       memset(oob_data, 0xBA, oob_len);
+       memset(&mtd, 0, sizeof(mtd));
+       memset(&req, 0, sizeof(req));
+       mtd.bb_allowed = 1;
+       mtd.eb_cnt = 1024;
+       mtd.eb_size = 128;
+       mtd.subpage_size = 64;
+       seek = (off_t)eb * mtd.eb_size + offs;
+       req.start = seek;
+       req.len = len;
+       req.ooblen = oob_len;
+       req.usr_data = (uint64_t)(unsigned long)buf;
+       req.usr_oob = (uint64_t)(unsigned long)oob_data;
+       req.mode = mode;
+       expect_ioctl(MEMWRITE, 0, &req, sizeof(req));
+       int r = mtd_write(lib, &mtd, mock_fd, eb, offs, buf, len, oob_data, oob_len, mode);
+       assert_int_equal(r, 0);
+
+       libmtd_close(lib);
+       (void) state;
+}
+
+static void test_mtd_read_oob(void **state)
+{
+       struct libmtd *lib = mock_libmtd_open();
+       struct mtd_dev_info mtd;
+       struct mtd_oob_buf64 oob64;
+       struct mtd_oob_buf oob;
+       int mock_fd = 4;
+       uint64_t start = 0, length = 64;
+       char buf[64];
+       memset(buf, 0xCD, 64);
+       memset(&oob, 0, sizeof(oob));
+       memset(&oob64, 0, sizeof(oob64));
+       memset(&mtd, 0, sizeof(mtd));
+       mtd.bb_allowed = 1;
+       mtd.eb_cnt = 1024;
+       mtd.eb_size = 128;
+       mtd.subpage_size = 64;
+       mtd.oob_size = 128;
+       oob64.start = start;
+       oob64.length = length;
+       oob64.usr_ptr = (uint64_t)(unsigned long)buf;
+       oob.start = oob64.start;
+       oob.length = oob64.length;
+       oob.ptr = buf;
+
+       lib->offs64_ioctls = OFFS64_IOCTLS_NOT_SUPPORTED;
+       expect_ioctl(MEMREADOOB, 0, &oob, sizeof(oob));
+       int r = mtd_read_oob(lib, &mtd, mock_fd, start, length, buf);
+       assert_int_equal(r, 0);
+
+       lib->offs64_ioctls = OFFS64_IOCTLS_SUPPORTED;
+       expect_ioctl(MEMREADOOB64, 0, &oob64, sizeof(oob64));
+       r = mtd_read_oob(lib, &mtd, mock_fd, start, length, buf);
+       assert_int_equal(r, 0);
+
+       libmtd_close(lib);
+       (void) state;
+}
+
+/* basically the same as above but write calls */
+static void test_mtd_write_oob(void **state)
+{
+       struct libmtd *lib = mock_libmtd_open();
+       struct mtd_dev_info mtd;
+       struct mtd_oob_buf64 oob64;
+       struct mtd_oob_buf oob;
+       int mock_fd = 4;
+       uint64_t start = 0, length = 64;
+       char buf[64];
+       memset(buf, 0xCD, 64);
+       memset(&oob, 0, sizeof(oob));
+       memset(&oob64, 0, sizeof(oob64));
+       memset(&mtd, 0, sizeof(mtd));
+       mtd.bb_allowed = 1;
+       mtd.eb_cnt = 1024;
+       mtd.eb_size = 128;
+       mtd.subpage_size = 64;
+       mtd.oob_size = 128;
+       oob64.start = start;
+       oob64.length = length;
+       oob64.usr_ptr = (uint64_t)(unsigned long)buf;
+       oob.start = oob64.start;
+       oob.length = oob64.length;
+       oob.ptr = buf;
+
+       lib->offs64_ioctls = OFFS64_IOCTLS_NOT_SUPPORTED;
+       expect_ioctl(MEMWRITEOOB, 0, &oob, sizeof(oob));
+       int r = mtd_write_oob(lib, &mtd, mock_fd, start, length, buf);
+       assert_int_equal(r, 0);
+
+       lib->offs64_ioctls = OFFS64_IOCTLS_SUPPORTED;
+       expect_ioctl(MEMWRITEOOB64, 0, &oob64, sizeof(oob64));
+       r = mtd_write_oob(lib, &mtd, mock_fd, start, length, buf);
+       assert_int_equal(r, 0);
+
+       libmtd_close(lib);
+       (void)state;
+}
+
+static void test_mtd_get_info(void **state)
+{
+       struct libmtd *lib = mock_libmtd_open();
+       struct mtd_info info;
+       memset(&info, 0, sizeof(info));
+       int r = mtd_get_info(lib, &info);
+       assert_int_equal(info.sysfs_supported, 1);
+       assert_int_equal(info.highest_mtd_num, 0);
+       assert_int_equal(info.lowest_mtd_num, 0);
+       assert_int_equal(info.mtd_dev_cnt, 1);
+       assert_int_equal(r, 0);
+
+       libmtd_close(lib);
+       (void)state;
+}
+
+static void test_mtd_get_dev_info1(void **state)
+{
+       struct libmtd *lib = mock_libmtd_open();
+       struct mtd_dev_info info;
+       int dev_num = 0;
+       memset(&info, 0, sizeof(info));
+       expect_stat(SYSFS_ROOT "/class/mtd/mtd0", 0);
+       expect_open(SYSFS_ROOT "/class/mtd/mtd0/dev", O_RDONLY, 0);
+       expect_read_real(50,0);
+       expect_read(1,0);
+       expect_close(3,1);
+       expect_open(SYSFS_ROOT "/class/mtd/mtd0/name", O_RDONLY, 0);
+       expect_read_real(128,0);
+       expect_read(1,0);
+       expect_close(3,1);
+       expect_open(SYSFS_ROOT "/class/mtd/mtd0/type", O_RDONLY, 4);
+       expect_read(65,0);
+       expect_read(1,0);
+       expect_close(4,0);
+       expect_open(SYSFS_ROOT "/class/mtd/mtd0/erasesize", O_RDONLY, 0);
+       expect_read_real(50, 0);
+       expect_close(3,1);
+       expect_open(SYSFS_ROOT "/class/mtd/mtd0/size", O_RDONLY, 0);
+       expect_read_real(50,0);
+       expect_close(3,1);
+       expect_open(SYSFS_ROOT "/class/mtd/mtd0/writesize", O_RDONLY, 0);
+       expect_read_real(50,0);
+       expect_close(3,1);
+       expect_open(SYSFS_ROOT "/class/mtd/mtd0/subpagesize", O_RDONLY, 0);
+       expect_read_real(50,0);
+       expect_close(3,1);
+       expect_open(SYSFS_ROOT "/class/mtd/mtd0/oobsize", O_RDONLY, 0);
+       expect_read_real(50,0);
+       expect_close(3,1);
+       expect_open(SYSFS_ROOT "/class/mtd/mtd0/numeraseregions", O_RDONLY, 0);
+       expect_read_real(50,0);
+       expect_close(3,1);
+       expect_open(SYSFS_ROOT "/class/mtd/mtd0/flags", O_RDONLY, 0);
+       expect_read_real(50,0);
+       expect_close(3,1);
+       int r = mtd_get_dev_info1(lib, dev_num, &info);
+       assert_int_equal(r, 0);
+       /* TODO check values */
+
+       libmtd_close(lib);
+       (void)state;
+}
+
+int main(void)
+{
+       const struct CMUnitTest tests[] = {
+               cmocka_unit_test(test_libmtd_open),
+               cmocka_unit_test(test_mtd_is_bad),
+               cmocka_unit_test(test_mtd_mark_bad),
+               cmocka_unit_test(test_mtd_lock),
+               cmocka_unit_test(test_mtd_unlock),
+               cmocka_unit_test(test_mtd_is_locked),
+               cmocka_unit_test(test_mtd_regioninfo),
+               cmocka_unit_test(test_mtd_erase_multi),
+               cmocka_unit_test(test_mtd_erase),
+               cmocka_unit_test(test_mtd_read),
+               cmocka_unit_test(test_mtd_write_nooob),
+               cmocka_unit_test(test_mtd_write_withoob),
+               cmocka_unit_test(test_mtd_read_oob),
+               cmocka_unit_test(test_mtd_write_oob),
+               cmocka_unit_test(test_mtd_dev_present),
+               cmocka_unit_test(test_mtd_get_info),
+               cmocka_unit_test(test_mtd_get_dev_info1),
+       };
+
+       return cmocka_run_group_tests(tests, NULL, NULL);
+}