[LTP] [PATCH v2 1/2] library: add cmd check handler in needs_cmds
Yang Xu
xuyang2018.jy@fujitsu.com
Tue Dec 7 09:08:02 CET 2021
Testcase ie statx05 needs mkfs.ext4 >= 1.43.0 because of encrypt feature.
As Cyril suggested, add cmd check handler in needs_cmd.
We don't use tst_ prefix ie tst_check_cmd since we don't export this api to user.
This check_cmd not only check cmd whether existed but also check the cmd version whether
meet test's requirement.
In check_cmd function, use strtok_r to split cmd_token,op_token,version_token.
It only supports six operations '>=' '<=' '>' '<' '==' '!='.
Currently, for the command version check, it only supports mkfs.ext4 command. If you
want to support more commands, just add your own .parser and .table_get methond in
version_parsers structure.
Suggested-by: Cyril Hrubis <chrubis@suse.cz>
Signed-off-by: Yang Xu <xuyang2018.jy@fujitsu.com>
---
v1->v2
1. rename tst_version_parser to check_cmd
2. For mkfs_ext4_version_table_get method, use sscanf instead of strtok_r
3. use enum for cmd op
4. fix description
5. add more newlib test for this
doc/c-test-api.txt | 14 +++
lib/newlib_tests/.gitignore | 8 ++
lib/newlib_tests/test_needs_cmds01.c | 25 ++++
lib/newlib_tests/test_needs_cmds02.c | 24 ++++
lib/newlib_tests/test_needs_cmds03.c | 24 ++++
lib/newlib_tests/test_needs_cmds04.c | 24 ++++
lib/newlib_tests/test_needs_cmds05.c | 24 ++++
lib/newlib_tests/test_needs_cmds06.c | 24 ++++
lib/newlib_tests/test_needs_cmds07.c | 24 ++++
lib/newlib_tests/test_needs_cmds08.c | 27 +++++
lib/tst_test.c | 169 ++++++++++++++++++++++++++-
11 files changed, 384 insertions(+), 3 deletions(-)
create mode 100644 lib/newlib_tests/test_needs_cmds01.c
create mode 100644 lib/newlib_tests/test_needs_cmds02.c
create mode 100644 lib/newlib_tests/test_needs_cmds03.c
create mode 100644 lib/newlib_tests/test_needs_cmds04.c
create mode 100644 lib/newlib_tests/test_needs_cmds05.c
create mode 100644 lib/newlib_tests/test_needs_cmds06.c
create mode 100644 lib/newlib_tests/test_needs_cmds07.c
create mode 100644 lib/newlib_tests/test_needs_cmds08.c
diff --git a/doc/c-test-api.txt b/doc/c-test-api.txt
index 64d0630ce..d35708516 100644
--- a/doc/c-test-api.txt
+++ b/doc/c-test-api.txt
@@ -2013,6 +2013,20 @@ terminated array of strings such as:
},
-------------------------------------------------------------------------------
+Also can check required commands version whether is satisfied by using 'needs_cmds',
+
+[source,c]
+-------------------------------------------------------------------------------
+.needs_cmds = (const char *const []) {
+ "mkfs.ext4 >= 1.43.0",
+ NULL
+},
++-------------------------------------------------------------------------------
+
+Currently, we only support mkfs.ext4 command. If you want to support more commands,
+please fill your own .parser and .table_get method in the version_parsers structure
+of lib/tst_test.c.
+
1.36 Assert sys or proc file value
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Using TST_ASSERT_INT/STR(path, val) to assert that integer value or string stored in
diff --git a/lib/newlib_tests/.gitignore b/lib/newlib_tests/.gitignore
index cf467b5a0..a19fa22e8 100644
--- a/lib/newlib_tests/.gitignore
+++ b/lib/newlib_tests/.gitignore
@@ -46,4 +46,12 @@ test_macros06
tst_fuzzy_sync01
tst_fuzzy_sync02
tst_fuzzy_sync03
+test_needs_cmds01
+test_needs_cmds02
+test_needs_cmds03
+test_needs_cmds04
+test_needs_cmds05
+test_needs_cmds06
+test_needs_cmds07
+test_needs_cmds08
test_zero_hugepage
diff --git a/lib/newlib_tests/test_needs_cmds01.c b/lib/newlib_tests/test_needs_cmds01.c
new file mode 100644
index 000000000..0ce69d61e
--- /dev/null
+++ b/lib/newlib_tests/test_needs_cmds01.c
@@ -0,0 +1,25 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) 2021 Yang Xu <xuyang2018.jy@fujitsu.com>
+ */
+
+#include <stdio.h>
+#include "tst_test.h"
+
+static void do_test(void)
+{
+ tst_res(TPASS, "Tesing check_cmd() functionality OK.");
+}
+
+static struct tst_test test = {
+ .test_all = do_test,
+ .needs_cmds = (const char *[]) {
+ "mkfs.ext4",
+ "mkfs.ext4 >= 1.43.0",
+ "mkfs.ext4 <= 2.0.0",
+ "mkfs.ext4 != 2.0.0",
+ "mkfs.ext4 > 1.43.0",
+ "mkfs.ext4 < 2.0.0",
+ NULL
+ }
+};
diff --git a/lib/newlib_tests/test_needs_cmds02.c b/lib/newlib_tests/test_needs_cmds02.c
new file mode 100644
index 000000000..1eeaf6351
--- /dev/null
+++ b/lib/newlib_tests/test_needs_cmds02.c
@@ -0,0 +1,24 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) 2021 Yang Xu <xuyang2018.jy@fujitsu.com>
+ */
+
+/*
+ * Test Illegal format by using non-existing cmd.
+ */
+
+#include <stdio.h>
+#include "tst_test.h"
+
+static void do_test(void)
+{
+ tst_res(TFAIL, "Nonexisting command is present!");
+}
+
+static struct tst_test test = {
+ .test_all = do_test,
+ .needs_cmds = (const char *[]) {
+ "mkfs.ext45 >= 1.43.0",
+ NULL
+ }
+};
diff --git a/lib/newlib_tests/test_needs_cmds03.c b/lib/newlib_tests/test_needs_cmds03.c
new file mode 100644
index 000000000..c50077f4e
--- /dev/null
+++ b/lib/newlib_tests/test_needs_cmds03.c
@@ -0,0 +1,24 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) 2021 Yang Xu <xuyang2018.jy@fujitsu.com>
+ */
+
+/*
+ * Test Illegal format by using Illegal operation.
+ */
+
+#include <stdio.h>
+#include "tst_test.h"
+
+static void do_test(void)
+{
+ tst_res(TFAIL, "Wrong operator was evaluated!");
+}
+
+static struct tst_test test = {
+ .test_all = do_test,
+ .needs_cmds = (const char *[]) {
+ "mkfs.ext4 ! 1.43.0",
+ NULL
+ }
+};
diff --git a/lib/newlib_tests/test_needs_cmds04.c b/lib/newlib_tests/test_needs_cmds04.c
new file mode 100644
index 000000000..5d05ed46d
--- /dev/null
+++ b/lib/newlib_tests/test_needs_cmds04.c
@@ -0,0 +1,24 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) 2021 Yang Xu <xuyang2018.jy@fujitsu.com>
+ */
+
+/*
+ * Test Illegal format by using incomplete version.
+ */
+
+#include <stdio.h>
+#include "tst_test.h"
+
+static void do_test(void)
+{
+ tst_res(TFAIL, "Incomplete version was parsed!");
+}
+
+static struct tst_test test = {
+ .test_all = do_test,
+ .needs_cmds = (const char *[]) {
+ "mkfs.ext4 > 1.43",
+ NULL
+ }
+};
diff --git a/lib/newlib_tests/test_needs_cmds05.c b/lib/newlib_tests/test_needs_cmds05.c
new file mode 100644
index 000000000..f4b509b68
--- /dev/null
+++ b/lib/newlib_tests/test_needs_cmds05.c
@@ -0,0 +1,24 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) 2021 Yang Xu <xuyang2018.jy@fujitsu.com>
+ */
+
+/*
+ * Test Illegal format by using version that has garbage.
+ */
+
+#include <stdio.h>
+#include "tst_test.h"
+
+static void do_test(void)
+{
+ tst_res(TFAIL, "Garbage version was parsed!");
+}
+
+static struct tst_test test = {
+ .test_all = do_test,
+ .needs_cmds = (const char *[]) {
+ "mkfs.ext4 > 1.43.0-1",
+ NULL
+ }
+};
diff --git a/lib/newlib_tests/test_needs_cmds06.c b/lib/newlib_tests/test_needs_cmds06.c
new file mode 100644
index 000000000..f1234820e
--- /dev/null
+++ b/lib/newlib_tests/test_needs_cmds06.c
@@ -0,0 +1,24 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) 2021 Yang Xu <xuyang2018.jy@fujitsu.com>
+ */
+
+/*
+ * Test Illegal format with garbage.
+ */
+
+#include <stdio.h>
+#include "tst_test.h"
+
+static void do_test(void)
+{
+ tst_res(TFAIL, "Garbage format was parsed!");
+}
+
+static struct tst_test test = {
+ .test_all = do_test,
+ .needs_cmds = (const char *[]) {
+ "mkfs.ext4 > 1.43.0 2",
+ NULL
+ }
+};
diff --git a/lib/newlib_tests/test_needs_cmds07.c b/lib/newlib_tests/test_needs_cmds07.c
new file mode 100644
index 000000000..e2d2643f4
--- /dev/null
+++ b/lib/newlib_tests/test_needs_cmds07.c
@@ -0,0 +1,24 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) 2021 Yang Xu <xuyang2018.jy@fujitsu.com>
+ */
+
+/*
+ * Test non-existed cmd whether still can be detected.
+ */
+
+#include <stdio.h>
+#include "tst_test.h"
+
+static void do_test(void)
+{
+ tst_res(TFAIL, "Nonexisting command is present!");
+}
+
+static struct tst_test test = {
+ .test_all = do_test,
+ .needs_cmds = (const char *[]) {
+ "mkfs.ext45",
+ NULL
+ }
+};
diff --git a/lib/newlib_tests/test_needs_cmds08.c b/lib/newlib_tests/test_needs_cmds08.c
new file mode 100644
index 000000000..342c3716c
--- /dev/null
+++ b/lib/newlib_tests/test_needs_cmds08.c
@@ -0,0 +1,27 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) 2021 Yang Xu <xuyang2018.jy@fujitsu.com>
+ */
+
+/*
+ * Test mkfs.xfs that it doesn't have own parser and table_get function
+ * at the version_parsers structure in lib/tst_test.c.
+ * So it should report parser function for this cmd is not implemented.
+ */
+
+#include <stdio.h>
+#include "tst_test.h"
+
+static void do_test(void)
+{
+ tst_res(TFAIL, "Nonexisting parser function for mkfs.xfs is present!");
+}
+
+static struct tst_test test = {
+ .test_all = do_test,
+ .needs_cmds = (const char *[]) {
+ "mkfs.xfs",
+ "mkfs.xfs >= 4.20.0",
+ NULL
+ }
+};
diff --git a/lib/tst_test.c b/lib/tst_test.c
index a79275722..7cca209ab 100644
--- a/lib/tst_test.c
+++ b/lib/tst_test.c
@@ -65,6 +65,15 @@ struct results {
unsigned int timeout;
};
+enum cmd_op {
+ OP_GE, /* >= */
+ OP_GT, /* > */
+ OP_LE, /* <= */
+ OP_LT, /* < */
+ OP_EQ, /* == */
+ OP_NE, /* != */
+};
+
static struct results *results;
static int ipc_fd;
@@ -950,6 +959,162 @@ static void prepare_device(void)
}
}
+static int mkfs_ext4_version_parser(void)
+{
+ FILE *f;
+ int rc, major, minor, patch;
+
+ f = popen("mkfs.ext4 -V 2>&1", "r");
+ if (!f) {
+ tst_res(TWARN, "Could not run mkfs.ext4 -V 2>&1 cmd");
+ return -1;
+ }
+ rc = fscanf(f, "mke2fs %d.%d.%d", &major, &minor, &patch);
+ pclose(f);
+ if (rc != 3) {
+ tst_res(TWARN, "Unable to parse mkfs.ext4 version");
+ return -1;
+ }
+
+ return major * 10000 + minor * 100 + patch;
+}
+
+static int mkfs_ext4_version_table_get(char *version)
+{
+ int major, minor, patch;
+ int len;
+
+ if (sscanf(version, "%u.%u.%u %n", &major, &minor, &patch, &len) != 3) {
+ tst_res(TWARN, "Illega version(%s), "
+ "should use format like 1.43.0", version);
+ return -1;
+ }
+
+ if (len != (int)strlen(version)) {
+ tst_res(TWARN, "Grabage after version");
+ return -1;
+ }
+
+ return major * 10000 + minor * 100 + patch;
+}
+
+static struct version_parser {
+ const char *cmd;
+ int (*parser)(void);
+ int (*table_get)(char *version);
+} version_parsers[] = {
+ {"mkfs.ext4", mkfs_ext4_version_parser, mkfs_ext4_version_table_get},
+ {},
+};
+
+static void check_cmd(const char *cmd)
+{
+ struct version_parser *p;
+ char *cmd_token, *op_token, *version_token, *next, *str;
+ char path[PATH_MAX];
+ char parser_cmd[100];
+ int ver_parser, ver_get;
+ int op_flag = 0;
+
+ strcpy(parser_cmd, cmd);
+
+ cmd_token = strtok_r(parser_cmd, " ", &next);
+ op_token = strtok_r(NULL, " ", &next);
+ version_token = strtok_r(NULL, " ", &next);
+ str = strtok_r(NULL, " ", &next);
+
+ if (tst_get_path(cmd_token, path, sizeof(path)))
+ tst_brk(TCONF, "Couldn't find '%s' in $PATH", cmd_token);
+
+ if (!op_token)
+ return;
+
+ if (!strcmp(op_token, ">="))
+ op_flag = OP_GE;
+ else if (!strcmp(op_token, ">"))
+ op_flag = OP_GT;
+ else if (!strcmp(op_token, "<="))
+ op_flag = OP_LE;
+ else if (!strcmp(op_token, "<"))
+ op_flag = OP_LT;
+ else if (!strcmp(op_token, "=="))
+ op_flag = OP_EQ;
+ else if (!strcmp(op_token, "!="))
+ op_flag = OP_NE;
+ else
+ tst_brk(TCONF, "Invalid op(%s)", op_token);
+
+ if (!version_token || str) {
+ tst_brk(TCONF, "Illegal format(%s), should use format like "
+ "mkfs.ext4 >= 1.43.0", cmd);
+ }
+
+ for (p = &version_parsers[0]; p->cmd; p++) {
+ if (!strcmp(p->cmd, cmd_token)) {
+ tst_res(TINFO, "Parsing %s version", p->cmd);
+ break;
+ }
+ }
+
+ if (!p->cmd) {
+ tst_brk(TBROK, "No version parser for %s implemented!",
+ cmd_token);
+ }
+
+ ver_parser = p->parser();
+ if (ver_parser < 0)
+ tst_brk(TBROK, "Failed to parse %s version", p->cmd);
+
+ ver_get = p->table_get(version_token);
+ if (ver_get < 0)
+ tst_brk(TBROK, "Failed to get %s version", p->cmd);
+
+ switch (op_flag) {
+ case OP_GE:
+ if (ver_parser < ver_get) {
+ tst_brk(TCONF, "%s required >= %d, but got %d, "
+ "the version is required in order run the test.",
+ cmd, ver_get, ver_parser);
+ }
+ break;
+ case OP_GT:
+ if (ver_parser <= ver_get) {
+ tst_brk(TCONF, "%s required > %d, but got %d, "
+ "the version is required in order run the test.",
+ cmd, ver_get, ver_parser);
+ }
+ break;
+ case OP_LE:
+ if (ver_parser > ver_get) {
+ tst_brk(TCONF, "%s required <= %d, but got %d, "
+ "the version is required in order run the test.",
+ cmd, ver_get, ver_parser);
+ }
+ break;
+ case OP_LT:
+ if (ver_parser >= ver_get) {
+ tst_brk(TCONF, "%s required < %d, but got %d, "
+ "the version is required in order run the test.",
+ cmd, ver_get, ver_parser);
+ }
+ break;
+ case OP_EQ:
+ if (ver_parser != ver_get) {
+ tst_brk(TCONF, "%s required == %d, but got %d, "
+ "the version is required in order run the test.",
+ cmd, ver_get, ver_parser);
+ }
+ break;
+ case OP_NE:
+ if (ver_parser == ver_get) {
+ tst_brk(TCONF, "%s required != %d, but got %d, "
+ "the version is required in order run the test.",
+ cmd, ver_get, ver_parser);
+ }
+ break;
+ }
+}
+
static void do_setup(int argc, char *argv[])
{
if (!tst_test)
@@ -987,12 +1152,10 @@ static void do_setup(int argc, char *argv[])
if (tst_test->needs_cmds) {
const char *cmd;
- char path[PATH_MAX];
int i;
for (i = 0; (cmd = tst_test->needs_cmds[i]); ++i)
- if (tst_get_path(cmd, path, sizeof(path)))
- tst_brk(TCONF, "Couldn't find '%s' in $PATH", cmd);
+ check_cmd(cmd);
}
if (tst_test->needs_drivers) {
--
2.23.0
More information about the ltp
mailing list