@@ -63,7 +63,10 @@ ndctl_SOURCES = ndctl.c \
util/wrapper.c
if ENABLE_TEST
-ndctl_SOURCES += lib/test-libndctl.c lib/test-dpa-alloc.c lib/test-parent-uuid.c
+ndctl_SOURCES += lib/test-libndctl.c \
+ lib/test-dpa-alloc.c \
+ lib/test-parent-uuid.c \
+ lib/test-core.c
endif
if ENABLE_DESTRUCTIVE
@@ -110,7 +113,7 @@ TESTS += lib/test-blk-ns lib/test-pmem-ns
check_PROGRAMS += lib/test-blk-ns lib/test-pmem-ns
endif
-lib_test_libndctl_SOURCES = lib/test-libndctl.c
+lib_test_libndctl_SOURCES = lib/test-libndctl.c lib/test-core.c
lib_test_libndctl_LDADD = lib/libndctl.la $(UUID_LIBS) $(KMOD_LIBS)
lib_test_blk_ns_SOURCES = lib/blk_namespaces.c
@@ -119,8 +122,8 @@ lib_test_blk_ns_LDADD = lib/libndctl.la $(KMOD_LIBS)
lib_test_pmem_ns_SOURCES = lib/pmem_namespaces.c
lib_test_pmem_ns_LDADD = lib/libndctl.la $(KMOD_LIBS)
-lib_test_dpa_alloc_SOURCES = lib/test-dpa-alloc.c
+lib_test_dpa_alloc_SOURCES = lib/test-dpa-alloc.c lib/test-core.c
lib_test_dpa_alloc_LDADD = lib/libndctl.la $(UUID_LIBS) $(KMOD_LIBS)
-lib_test_parent_uuid_SOURCES = lib/test-parent-uuid.c
+lib_test_parent_uuid_SOURCES = lib/test-parent-uuid.c lib/test-core.c
lib_test_parent_uuid_LDADD = lib/libndctl.la $(UUID_LIBS) $(KMOD_LIBS)
@@ -1,20 +1,36 @@
#include <stdio.h>
+#include <limits.h>
#include <syslog.h>
+#include <test-core.h>
#include <test-libndctl.h>
#include <test-dpa-alloc.h>
#include <test-parent-uuid.h>
#include <util/parse-options.h>
+static char *result(int rc)
+{
+ if (rc == 77)
+ return "SKIP";
+ else if (rc)
+ return "FAIL";
+ else
+ return "PASS";
+}
+
int cmd_test(int argc, const char **argv)
{
+ struct ndctl_test *test;
int loglevel = LOG_DEBUG, i, rc;
const char * const u[] = {
"ndctl test [<options>]",
NULL
};
+ bool force = false;
const struct option options[] = {
OPT_INTEGER('l', "loglevel", &loglevel,
"set the log level (default LOG_DEBUG)"),
+ OPT_BOOLEAN('f', "force", &force,
+ "force run all tests regardless of required kernel"),
OPT_END(),
};
@@ -26,17 +42,23 @@ int cmd_test(int argc, const char **argv)
if (argc)
usage_with_options(u, options);
- rc = test_libndctl(loglevel);
- fprintf(stderr, "test-libndctl: %s\n", rc ? "FAIL" : "PASS");
- if (rc)
+ if (force)
+ test = ndctl_test_new(UINT_MAX);
+ else
+ test = ndctl_test_new(0);
+
+ rc = test_libndctl(loglevel, test);
+ fprintf(stderr, "test-libndctl: %s\n", result(rc));
+ if (rc && rc != 77)
return rc;
- rc = test_dpa_alloc(loglevel);
- fprintf(stderr, "test-dpa-alloc: %s\n", rc ? "FAIL" : "PASS");
- if (rc)
+ rc = test_dpa_alloc(loglevel, test);
+ fprintf(stderr, "test-dpa-alloc: %s\n", result(rc));
+ if (rc && rc != 77)
return rc;
- rc = test_parent_uuid(loglevel);
- fprintf(stderr, "test-parent-uuid: %s\n", rc ? "FAIL" : "PASS");
- return rc;
+ rc = test_parent_uuid(loglevel, test);
+ fprintf(stderr, "test-parent-uuid: %s\n", result(rc));
+
+ return ndctl_test_result(test, rc);
}
@@ -76,7 +76,7 @@ AC_CHECK_HEADER([linux/ndctl.h],
[AC_DEFINE([HAVE_NDCTL_H], [1],
[Define to 1 if you have <linux/ndctl.h>.])],
[])
-
+AC_CHECK_HEADERS_ONCE([linux/version.h])
AC_CHECK_FUNCS([ \
__secure_getenv \
@@ -228,7 +228,7 @@ int test_blk_namespaces(int log_level)
bus = ndctl_bus_get_by_provider(ctx, provider);
if (!bus) {
fprintf(stderr, "%s: failed to find NFIT-provider\n", comm);
- rc = ENODEV;
+ rc = 77;
goto err_nobus;
} else
fprintf(stderr, "%s: found provider: %s\n", comm,
@@ -188,7 +188,7 @@ int test_pmem_namespaces(int log_level)
bus = ndctl_bus_get_by_provider(ctx, provider);
if (!bus) {
fprintf(stderr, "%s: failed to find NFIT-provider\n", comm);
- rc = ENODEV;
+ rc = 77;
goto err;
} else
fprintf(stderr, "%s: found provider: %s\n", comm,
new file mode 100644
@@ -0,0 +1,73 @@
+#include <linux/version.h>
+#include <test-core.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#define KVER_STRLEN 20
+
+struct ndctl_test {
+ unsigned int kver;
+ int attempt;
+ int skip;
+};
+
+struct ndctl_test *ndctl_test_new(unsigned int kver)
+{
+ struct ndctl_test *test = calloc(1, sizeof(*test));
+
+ if (!test)
+ return NULL;
+
+ if (!kver)
+ test->kver = LINUX_VERSION_CODE;
+ else
+ test->kver = kver;
+
+ return test;
+}
+
+int ndctl_test_result(struct ndctl_test *test, int rc)
+{
+ if (ndctl_test_get_skipped(test))
+ fprintf(stderr, "attempted: %d skipped: %d\n",
+ ndctl_test_get_attempted(test),
+ ndctl_test_get_skipped(test));
+ if (rc && rc != 77)
+ return rc;
+ if (ndctl_test_get_skipped(test) >= ndctl_test_get_attempted(test))
+ return 77;
+ /* return success if no failures and at least one test not skipped */
+ return 0;
+}
+
+static char *kver_str(char *buf, unsigned int kver)
+{
+ snprintf(buf, KVER_STRLEN, "%d.%d.%d", (kver >> 16) & 0xffff,
+ (kver >> 8) & 0xff, kver & 0xff);
+ return buf;
+}
+
+int __ndctl_test_attempt(struct ndctl_test *test, unsigned int kver,
+ const char *caller, int line)
+{
+ char requires[KVER_STRLEN], current[KVER_STRLEN];
+
+ test->attempt++;
+ if (kver <= test->kver)
+ return 1;
+ fprintf(stderr, "%s: skip %s:%d requires: %s current: %s\n",
+ __func__, caller, line, kver_str(requires, kver),
+ kver_str(current, test->kver));
+ test->skip++;
+ return 0;
+}
+
+int ndctl_test_get_attempted(struct ndctl_test *test)
+{
+ return test->attempt;
+}
+
+int ndctl_test_get_skipped(struct ndctl_test *test)
+{
+ return test->skip;
+}
new file mode 100644
@@ -0,0 +1,8 @@
+struct ndctl_test;
+struct ndctl_test *ndctl_test_new(unsigned int kver);
+int ndctl_test_result(struct ndctl_test *test, int rc);
+int ndctl_test_get_skipped(struct ndctl_test *test);
+int ndctl_test_get_attempted(struct ndctl_test *test);
+int __ndctl_test_attempt(struct ndctl_test *test, unsigned int kver,
+ const char *caller, int line);
+#define ndctl_test_attempt(t, v) __ndctl_test_attempt(t, v, __func__, __LINE__)
@@ -26,6 +26,8 @@
#include <libkmod.h>
#include <uuid/uuid.h>
+#include <test-core.h>
+#include <linux/version.h>
#include <ndctl/libndctl.h>
#include <test-dpa-alloc.h>
#include <ccan/array_size/array_size.h>
@@ -49,7 +51,7 @@ struct test_dpa_namespace {
uuid_t uuid;
} namespaces[NUM_NAMESPACES];
-static int do_test(struct ndctl_ctx *ctx)
+static int do_test(struct ndctl_ctx *ctx, struct ndctl_test *test)
{
struct ndctl_region *region, *blk_region = NULL;
unsigned int available_slots, i;
@@ -292,13 +294,16 @@ static int do_test(struct ndctl_ctx *ctx)
return 0;
}
-int test_dpa_alloc(int loglevel)
+int test_dpa_alloc(int loglevel, struct ndctl_test *test)
{
struct ndctl_ctx *ctx;
struct kmod_module *mod;
struct kmod_ctx *kmod_ctx;
int err, result = EXIT_FAILURE;
+ if (!ndctl_test_attempt(test, KERNEL_VERSION(4, 2, 0)))
+ return 77;
+
err = ndctl_new(&ctx);
if (err < 0)
exit(EXIT_FAILURE);
@@ -315,10 +320,14 @@ int test_dpa_alloc(int loglevel)
err = kmod_module_probe_insert_module(mod, KMOD_PROBE_APPLY_BLACKLIST,
NULL, NULL, NULL, NULL);
- if (err < 0)
+ if (err < 0) {
+ result = 77;
+ fprintf(stderr, "%s unavailable skipping tests\n",
+ NFIT_TEST_MODULE);
goto err_module;
+ }
- err = do_test(ctx);
+ err = do_test(ctx, test);
if (err == 0)
result = EXIT_SUCCESS;
kmod_module_remove_module(mod, 0);
@@ -332,5 +341,14 @@ int test_dpa_alloc(int loglevel)
int __attribute__((weak)) main(int argc, char *argv[])
{
- return test_dpa_alloc(LOG_DEBUG);
+ struct ndctl_test *test = ndctl_test_new(0);
+ int rc;
+
+ if (!test) {
+ fprintf(stderr, "failed to initialize test\n");
+ return EXIT_FAILURE;
+ }
+
+ rc = test_dpa_alloc(LOG_DEBUG, test);
+ return ndctl_test_result(test, rc);
}
@@ -26,6 +26,7 @@
#include <libkmod.h>
#include <uuid/uuid.h>
#include <sys/ioctl.h>
+#include <linux/version.h>
#include <ccan/array_size/array_size.h>
#include <ndctl/libndctl.h>
@@ -35,6 +36,7 @@
#include <ndctl.h>
#endif
#include <test-libndctl.h>
+#include <test-core.h>
#define BLKROGET _IO(0x12,94) /* get read-only status (0 = read_write) */
#define BLKROSET _IO(0x12,93) /* set device read-only (0 = read-write) */
@@ -1362,7 +1364,8 @@ static int check_ars_status(struct ndctl_bus *bus, struct ndctl_dimm *dimm,
#define BITS_PER_LONG 32
static int check_commands(struct ndctl_bus *bus, struct ndctl_dimm *dimm,
- unsigned long bus_commands, unsigned long dimm_commands)
+ unsigned long bus_commands, unsigned long dimm_commands,
+ struct ndctl_test *test)
{
/*
* For now, by coincidence, these are indexed in test execution
@@ -1416,6 +1419,9 @@ static int check_commands(struct ndctl_bus *bus, struct ndctl_dimm *dimm,
if (rc)
goto out;
+ if (!ndctl_test_attempt(test, KERNEL_VERSION(4, 3, 0)))
+ goto out;
+
/* Check Bus commands */
check_cmds = __check_bus_cmds;
for (i = 1; i < BITS_PER_LONG; i++) {
@@ -1449,7 +1455,8 @@ static int check_commands(struct ndctl_bus *bus, struct ndctl_dimm *dimm,
}
static int check_dimms(struct ndctl_bus *bus, struct dimm *dimms, int n,
- unsigned long bus_commands, unsigned long dimm_commands)
+ unsigned long bus_commands, unsigned long dimm_commands,
+ struct ndctl_test *test)
{
int i, rc;
@@ -1495,7 +1502,7 @@ static int check_dimms(struct ndctl_bus *bus, struct dimm *dimms, int n,
return -ENXIO;
}
- rc = check_commands(bus, dimm, bus_commands, dimm_commands);
+ rc = check_commands(bus, dimm, bus_commands, dimm_commands, test);
if (rc)
return rc;
}
@@ -1503,7 +1510,7 @@ static int check_dimms(struct ndctl_bus *bus, struct dimm *dimms, int n,
return 0;
}
-static int do_test0(struct ndctl_ctx *ctx)
+static int do_test0(struct ndctl_ctx *ctx, struct ndctl_test *test)
{
struct ndctl_bus *bus = ndctl_bus_get_by_provider(ctx, NFIT_PROVIDER0);
struct ndctl_region *region;
@@ -1517,7 +1524,7 @@ static int do_test0(struct ndctl_ctx *ctx)
ndctl_region_disable_invalidate(region);
rc = check_dimms(bus, dimms0, ARRAY_SIZE(dimms0), bus_commands0,
- dimm_commands0);
+ dimm_commands0, test);
if (rc)
return rc;
@@ -1528,7 +1535,7 @@ static int do_test0(struct ndctl_ctx *ctx)
return check_regions(bus, regions0, ARRAY_SIZE(regions0));
}
-static int do_test1(struct ndctl_ctx *ctx)
+static int do_test1(struct ndctl_ctx *ctx, struct ndctl_test *test)
{
struct ndctl_bus *bus = ndctl_bus_get_by_provider(ctx, NFIT_PROVIDER1);
int rc;
@@ -1536,20 +1543,20 @@ static int do_test1(struct ndctl_ctx *ctx)
if (!bus)
return -ENXIO;
- rc = check_dimms(bus, dimms1, ARRAY_SIZE(dimms1), 0, 0);
+ rc = check_dimms(bus, dimms1, ARRAY_SIZE(dimms1), 0, 0, test);
if (rc)
return rc;
return check_regions(bus, regions1, ARRAY_SIZE(regions1));
}
-typedef int (*do_test_fn)(struct ndctl_ctx *ctx);
+typedef int (*do_test_fn)(struct ndctl_ctx *ctx, struct ndctl_test *test);
static do_test_fn do_test[] = {
do_test0,
do_test1,
};
-int test_libndctl(int loglevel)
+int test_libndctl(int loglevel, struct ndctl_test *test)
{
unsigned int i;
struct ndctl_ctx *ctx;
@@ -1557,6 +1564,9 @@ int test_libndctl(int loglevel)
struct kmod_ctx *kmod_ctx;
int err, result = EXIT_FAILURE;
+ if (!ndctl_test_attempt(test, KERNEL_VERSION(4, 2, 0)))
+ return 77;
+
err = ndctl_new(&ctx);
if (err < 0)
exit(EXIT_FAILURE);
@@ -1574,11 +1584,15 @@ int test_libndctl(int loglevel)
err = kmod_module_probe_insert_module(mod, KMOD_PROBE_APPLY_BLACKLIST,
NULL, NULL, NULL, NULL);
- if (err < 0)
+ if (err < 0) {
+ result = 77;
+ fprintf(stderr, "%s unavailable skipping tests\n",
+ NFIT_TEST_MODULE);
goto err_module;
+ }
for (i = 0; i < ARRAY_SIZE(do_test); i++) {
- err = do_test[i](ctx);
+ err = do_test[i](ctx, test);
if (err < 0) {
fprintf(stderr, "ndctl-test%d failed: %d\n", i, err);
break;
@@ -1598,5 +1612,14 @@ int test_libndctl(int loglevel)
int __attribute__((weak)) main(int argc, char *argv[])
{
- return test_libndctl(LOG_DEBUG);
+ struct ndctl_test *test = ndctl_test_new(0);
+ int rc;
+
+ if (!test) {
+ fprintf(stderr, "failed to initialize test\n");
+ return EXIT_FAILURE;
+ }
+
+ rc = test_libndctl(LOG_DEBUG, test);
+ return ndctl_test_result(test, rc);
}
@@ -24,6 +24,8 @@
#include <syslog.h>
#include <libkmod.h>
#include <uuid/uuid.h>
+#include <linux/version.h>
+#include <test-core.h>
#include <test-parent-uuid.h>
#include <ndctl/libndctl.h>
@@ -129,7 +131,6 @@ static struct ndctl_btt *check_valid_btt(struct ndctl_region *region,
return NULL;
}
-
static int do_test(struct ndctl_ctx *ctx)
{
int rc;
@@ -230,13 +231,16 @@ static int do_test(struct ndctl_ctx *ctx)
return 0;
}
-int test_parent_uuid(int loglevel)
+int test_parent_uuid(int loglevel, struct ndctl_test *test)
{
struct ndctl_ctx *ctx;
struct kmod_module *mod;
struct kmod_ctx *kmod_ctx;
int err, result = EXIT_FAILURE;
+ if (!ndctl_test_attempt(test, KERNEL_VERSION(4, 3, 0)))
+ return 77;
+
err = ndctl_new(&ctx);
if (err < 0)
exit(EXIT_FAILURE);
@@ -253,8 +257,12 @@ int test_parent_uuid(int loglevel)
err = kmod_module_probe_insert_module(mod, KMOD_PROBE_APPLY_BLACKLIST,
NULL, NULL, NULL, NULL);
- if (err < 0)
+ if (err < 0) {
+ result = 77;
+ fprintf(stderr, "%s unavailable skipping tests\n",
+ NFIT_TEST_MODULE);
goto err_module;
+ }
err = do_test(ctx);
if (err == 0)
@@ -270,5 +278,14 @@ int test_parent_uuid(int loglevel)
int __attribute__((weak)) main(int argc, char *argv[])
{
- return test_parent_uuid(LOG_DEBUG);
+ struct ndctl_test *test = ndctl_test_new(0);
+ int rc;
+
+ if (!test) {
+ fprintf(stderr, "failed to initialize test\n");
+ return EXIT_FAILURE;
+ }
+
+ rc = test_parent_uuid(LOG_DEBUG, test);
+ return ndctl_test_result(test, rc);
}
@@ -1,4 +1,5 @@
#ifndef __TEST_DPA_ALLOC__
#define __TEST_DPA_ALLOC__
-int test_dpa_alloc(int loglevel);
+struct ndctl_test;
+int test_dpa_alloc(int loglevel, struct ndctl_test *test);
#endif
@@ -1,4 +1,5 @@
#ifndef __TEST_LIBNDCTL__
#define __TEST_LIBNDCTL__
-int test_libndctl(int loglevel);
+struct ndctl_test;
+int test_libndctl(int loglevel, struct ndctl_test *test);
#endif
@@ -1,4 +1,5 @@
#ifndef __TEST_PARENT_UUID__
#define __TEST_PARENT_UUID__
-int test_parent_uuid(int loglevel);
+struct ndctl_test;
+int test_parent_uuid(int loglevel, struct ndctl_test *test);
#endif
Attempts to run the unit tests on kernels that do not have the unit test modules available, or do not support a given test should be skipped. by default. The baseline assumption is a minimal kernel version of 4.2. Signed-off-by: Dan Williams <dan.j.williams@intel.com> --- Makefile.am | 11 +++++-- builtin-test.c | 40 ++++++++++++++++++++------ configure.ac | 2 + lib/blk_namespaces.c | 2 + lib/pmem_namespaces.c | 2 + lib/test-core.c | 73 ++++++++++++++++++++++++++++++++++++++++++++++++ lib/test-core.h | 8 +++++ lib/test-dpa-alloc.c | 28 +++++++++++++++--- lib/test-libndctl.c | 47 +++++++++++++++++++++++-------- lib/test-parent-uuid.c | 25 ++++++++++++++-- test-dpa-alloc.h | 3 +- test-libndctl.h | 3 +- test-parent-uuid.h | 3 +- 13 files changed, 207 insertions(+), 40 deletions(-) create mode 100644 lib/test-core.c create mode 100644 lib/test-core.h