* [LTP] [PATCH v1 0/2] new cmd support option for needs_cmds
@ 2025-09-26 8:50 Wei Gao via ltp
2025-09-26 8:50 ` [LTP] [PATCH v1 1/2] lib: Add support option for .needs_cmds Wei Gao via ltp
` (2 more replies)
0 siblings, 3 replies; 100+ messages in thread
From: Wei Gao via ltp @ 2025-09-26 8:50 UTC (permalink / raw)
To: ltp
NOTE:This patchset is draft for review not final one.
Since not include update .needs_cmds for all related testcases.
Wei Gao (2):
lib: Add support option for .needs_cmds
ioctl_loop01.c: Update to new .needs_cmds struct
include/tst_cmd.h | 15 +++
include/tst_private.h | 2 +
include/tst_test.h | 2 +-
lib/tst_cmd.c | 98 +++++++++++++++++++
lib/tst_test.c | 9 +-
.../kernel/syscalls/ioctl/ioctl_loop01.c | 23 ++---
6 files changed, 130 insertions(+), 19 deletions(-)
--
2.51.0
--
Mailing list info: https://lists.linux.it/listinfo/ltp
^ permalink raw reply [flat|nested] 100+ messages in thread* [LTP] [PATCH v1 1/2] lib: Add support option for .needs_cmds 2025-09-26 8:50 [LTP] [PATCH v1 0/2] new cmd support option for needs_cmds Wei Gao via ltp @ 2025-09-26 8:50 ` Wei Gao via ltp 2025-09-26 9:31 ` Cyril Hrubis 2025-09-26 8:50 ` [LTP] [PATCH v1 2/2] ioctl_loop01.c: Update to new .needs_cmds struct Wei Gao via ltp 2025-09-28 23:26 ` [LTP] [PATCH v1 0/2] new cmd support option for needs_cmds Wei Gao via ltp 2 siblings, 1 reply; 100+ messages in thread From: Wei Gao via ltp @ 2025-09-26 8:50 UTC (permalink / raw) To: ltp NOTE:This patchset is draft for review not final one. Since not include update .needs_cmds for all related testcases. Suggested-by: Cyril Hrubis <chrubis@suse.cz> Signed-off-by: Wei Gao <wegao@suse.com> --- include/tst_cmd.h | 15 +++++++ include/tst_private.h | 2 + include/tst_test.h | 2 +- lib/tst_cmd.c | 98 +++++++++++++++++++++++++++++++++++++++++++ lib/tst_test.c | 9 ++-- 5 files changed, 121 insertions(+), 5 deletions(-) diff --git a/include/tst_cmd.h b/include/tst_cmd.h index 939825646..c7e7e56c1 100644 --- a/include/tst_cmd.h +++ b/include/tst_cmd.h @@ -5,6 +5,8 @@ #ifndef TST_CMD_H__ #define TST_CMD_H__ +#include <stdbool.h> + enum tst_cmd_flags { /* * return the program exit code, otherwise it will call cleanup_fn() if the @@ -16,6 +18,19 @@ enum tst_cmd_flags { TST_CMD_TCONF_ON_MISSING = 2, }; +struct tst_cmd { + const char *cmd; + unsigned int required:1; + unsigned int support:1; +}; + + +/* + * tst_cmd_present would loop over the tst_cmd array and return the supported flag + * value. + */ +bool tst_cmd_present(struct tst_cmd *pcmd, const char *cmd); + /* * vfork() + execvp() specified program. * diff --git a/include/tst_private.h b/include/tst_private.h index 4c6479f4b..d549cf968 100644 --- a/include/tst_private.h +++ b/include/tst_private.h @@ -47,4 +47,6 @@ char tst_kconfig_get(const char *confname); */ int tst_check_cmd(const char *cmd, const int brk_nosupp); +int tst_check_needs_cmds(struct tst_cmd *cmd, const int brk_nosupp); + #endif diff --git a/include/tst_test.h b/include/tst_test.h index 9c21c1728..8fb7cd86c 100644 --- a/include/tst_test.h +++ b/include/tst_test.h @@ -617,7 +617,7 @@ struct tst_fs { const struct tst_tag *tags; - const char *const *needs_cmds; + struct tst_cmd *needs_cmds; const enum tst_cg_ver needs_cgroup_ver; diff --git a/lib/tst_cmd.c b/lib/tst_cmd.c index 82d60497a..7457d17c4 100644 --- a/lib/tst_cmd.c +++ b/lib/tst_cmd.c @@ -330,3 +330,101 @@ error: return 1; } + +int tst_check_needs_cmds(struct tst_cmd *cmd, const int brk_nosupp) +{ + 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; + + strcpy(parser_cmd, 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))) + if (brk_nosupp) + tst_brkm(TCONF, NULL, "Couldn't find '%s' in $PATH", cmd_token); + else + goto error; + + if (!op_token) + goto pass; + + if (!version_token || str) { + tst_brkm(TCONF, NULL, + "Illegal format(%s), should use format like mkfs.ext4 >= 1.43.0", + cmd->cmd); + } + + for (p = &version_parsers[0]; p->cmd; p++) { + if (!strcmp(p->cmd, cmd_token)) { + tst_resm(TINFO, "Parsing %s version", p->cmd); + break; + } + } + + if (!p->cmd) { + tst_brkm(TBROK, NULL, "No version parser for %s implemented!", + cmd_token); + } + + ver_parser = p->parser(); + if (ver_parser < 0) + tst_brkm(TBROK, NULL, "Failed to parse %s version", p->cmd); + + ver_get = p->table_get(version_token); + if (ver_get < 0) + tst_brkm(TBROK, NULL, "Failed to get %s version", p->cmd); + + if (!strcmp(op_token, ">=")) { + if (ver_parser < ver_get) + goto error; + } else if (!strcmp(op_token, ">")) { + if (ver_parser <= ver_get) + goto error; + } else if (!strcmp(op_token, "<=")) { + if (ver_parser > ver_get) + goto error; + } else if (!strcmp(op_token, "<")) { + if (ver_parser >= ver_get) + goto error; + } else if (!strcmp(op_token, "==")) { + if (ver_parser != ver_get) + goto error; + } else if (!strcmp(op_token, "!=")) { + if (ver_parser == ver_get) + goto error; + } else { + tst_brkm(TCONF, NULL, "Invalid op(%s)", op_token); + } +pass: + cmd->support = 1; + return 0; +error: + cmd->support = 0; + if (brk_nosupp) { + tst_brkm(TCONF, NULL, "%s requires %s %d, but got %d", + cmd, op_token, ver_get, ver_parser); + } else { + tst_resm(TCONF, "%s requires %s %d, but got %d", + cmd, op_token, ver_get, ver_parser); + } + + return 1; +} + +bool tst_cmd_present(struct tst_cmd *pcmd, const char *cmd) +{ + while (pcmd->cmd) { + if (!strcmp(pcmd->cmd, cmd)) + return pcmd->support; + + pcmd++; + } + return false; +} diff --git a/lib/tst_test.c b/lib/tst_test.c index b8894f782..41519d4e1 100644 --- a/lib/tst_test.c +++ b/lib/tst_test.c @@ -1422,11 +1422,12 @@ static void do_setup(int argc, char *argv[]) tst_brk(TCONF, "%dbit ABI is not supported", tst_test->needs_abi_bits); if (tst_test->needs_cmds) { - const char *cmd; - int i; + struct tst_cmd *cmd = tst_test->needs_cmds; - for (i = 0; (cmd = tst_test->needs_cmds[i]); ++i) - tst_check_cmd(cmd, 1); + while (cmd->cmd) { + tst_check_needs_cmds(cmd,cmd->required); + cmd++; + } } if (tst_test->needs_drivers) { -- 2.51.0 -- Mailing list info: https://lists.linux.it/listinfo/ltp ^ permalink raw reply related [flat|nested] 100+ messages in thread
* Re: [LTP] [PATCH v1 1/2] lib: Add support option for .needs_cmds 2025-09-26 8:50 ` [LTP] [PATCH v1 1/2] lib: Add support option for .needs_cmds Wei Gao via ltp @ 2025-09-26 9:31 ` Cyril Hrubis 0 siblings, 0 replies; 100+ messages in thread From: Cyril Hrubis @ 2025-09-26 9:31 UTC (permalink / raw) To: Wei Gao; +Cc: ltp Hi! > Suggested-by: Cyril Hrubis <chrubis@suse.cz> > Signed-off-by: Wei Gao <wegao@suse.com> > --- > include/tst_cmd.h | 15 +++++++ > include/tst_private.h | 2 + > include/tst_test.h | 2 +- > lib/tst_cmd.c | 98 +++++++++++++++++++++++++++++++++++++++++++ > lib/tst_test.c | 9 ++-- > 5 files changed, 121 insertions(+), 5 deletions(-) > > diff --git a/include/tst_cmd.h b/include/tst_cmd.h > index 939825646..c7e7e56c1 100644 > --- a/include/tst_cmd.h > +++ b/include/tst_cmd.h > @@ -5,6 +5,8 @@ > #ifndef TST_CMD_H__ > #define TST_CMD_H__ > > +#include <stdbool.h> > + > enum tst_cmd_flags { > /* > * return the program exit code, otherwise it will call cleanup_fn() if the > @@ -16,6 +18,19 @@ enum tst_cmd_flags { > TST_CMD_TCONF_ON_MISSING = 2, > }; > > +struct tst_cmd { > + const char *cmd; > + unsigned int required:1; Maybe it would make more sense to flip the logic and add an 'optional' flag here instead. So that for most of the cases we just need to initialize the cmd member. > + unsigned int support:1; ^ This should be named 'present' to match the function name. > +}; > + > + > +/* > + * tst_cmd_present would loop over the tst_cmd array and return the supported flag > + * value. > + */ > +bool tst_cmd_present(struct tst_cmd *pcmd, const char *cmd); > + > /* > * vfork() + execvp() specified program. > * > diff --git a/include/tst_private.h b/include/tst_private.h > index 4c6479f4b..d549cf968 100644 > --- a/include/tst_private.h > +++ b/include/tst_private.h > @@ -47,4 +47,6 @@ char tst_kconfig_get(const char *confname); > */ > int tst_check_cmd(const char *cmd, const int brk_nosupp); > > +int tst_check_needs_cmds(struct tst_cmd *cmd, const int brk_nosupp); > + > #endif > diff --git a/include/tst_test.h b/include/tst_test.h > index 9c21c1728..8fb7cd86c 100644 > --- a/include/tst_test.h > +++ b/include/tst_test.h > @@ -617,7 +617,7 @@ struct tst_fs { > > const struct tst_tag *tags; > > - const char *const *needs_cmds; > + struct tst_cmd *needs_cmds; > > const enum tst_cg_ver needs_cgroup_ver; > > diff --git a/lib/tst_cmd.c b/lib/tst_cmd.c > index 82d60497a..7457d17c4 100644 > --- a/lib/tst_cmd.c > +++ b/lib/tst_cmd.c > @@ -330,3 +330,101 @@ error: > > return 1; > } > + > +int tst_check_needs_cmds(struct tst_cmd *cmd, const int brk_nosupp) > +{ > + 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; > + > + strcpy(parser_cmd, 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))) > + if (brk_nosupp) > + tst_brkm(TCONF, NULL, "Couldn't find '%s' in $PATH", cmd_token); > + else > + goto error; > + > + if (!op_token) > + goto pass; > + > + if (!version_token || str) { > + tst_brkm(TCONF, NULL, > + "Illegal format(%s), should use format like mkfs.ext4 >= 1.43.0", > + cmd->cmd); > + } > + > + for (p = &version_parsers[0]; p->cmd; p++) { > + if (!strcmp(p->cmd, cmd_token)) { > + tst_resm(TINFO, "Parsing %s version", p->cmd); > + break; > + } > + } > + > + if (!p->cmd) { > + tst_brkm(TBROK, NULL, "No version parser for %s implemented!", > + cmd_token); > + } > + > + ver_parser = p->parser(); > + if (ver_parser < 0) > + tst_brkm(TBROK, NULL, "Failed to parse %s version", p->cmd); > + > + ver_get = p->table_get(version_token); > + if (ver_get < 0) > + tst_brkm(TBROK, NULL, "Failed to get %s version", p->cmd); > + > + if (!strcmp(op_token, ">=")) { > + if (ver_parser < ver_get) > + goto error; > + } else if (!strcmp(op_token, ">")) { > + if (ver_parser <= ver_get) > + goto error; > + } else if (!strcmp(op_token, "<=")) { > + if (ver_parser > ver_get) > + goto error; > + } else if (!strcmp(op_token, "<")) { > + if (ver_parser >= ver_get) > + goto error; > + } else if (!strcmp(op_token, "==")) { > + if (ver_parser != ver_get) > + goto error; > + } else if (!strcmp(op_token, "!=")) { > + if (ver_parser == ver_get) > + goto error; > + } else { > + tst_brkm(TCONF, NULL, "Invalid op(%s)", op_token); > + } > +pass: > + cmd->support = 1; > + return 0; > +error: > + cmd->support = 0; > + if (brk_nosupp) { > + tst_brkm(TCONF, NULL, "%s requires %s %d, but got %d", > + cmd, op_token, ver_get, ver_parser); > + } else { > + tst_resm(TCONF, "%s requires %s %d, but got %d", > + cmd, op_token, ver_get, ver_parser); > + } > + > + return 1; > +} There is no reason add this function at all, we can just call with the right arguments and get the return value from tst_check_cmd() in the tst_test.c instead. > +bool tst_cmd_present(struct tst_cmd *pcmd, const char *cmd) No need to pass the struct tst_cmd here, we can access it through the global tst_test pointer instead. Also this function should go to the tst_test.c. > +{ > + while (pcmd->cmd) { > + if (!strcmp(pcmd->cmd, cmd)) > + return pcmd->support; > + > + pcmd++; > + } > + return false; If we got here we asked for something that wasn't defined in tst_test structure so here we should do: tst_res(TBROK, "Invalid cmd request '%s'", cmd); > +} > diff --git a/lib/tst_test.c b/lib/tst_test.c > index b8894f782..41519d4e1 100644 > --- a/lib/tst_test.c > +++ b/lib/tst_test.c > @@ -1422,11 +1422,12 @@ static void do_setup(int argc, char *argv[]) > tst_brk(TCONF, "%dbit ABI is not supported", tst_test->needs_abi_bits); > > if (tst_test->needs_cmds) { > - const char *cmd; > - int i; > + struct tst_cmd *cmd = tst_test->needs_cmds; > > - for (i = 0; (cmd = tst_test->needs_cmds[i]); ++i) > - tst_check_cmd(cmd, 1); > + while (cmd->cmd) { > + tst_check_needs_cmds(cmd,cmd->required); > + cmd++; > + } > } > > if (tst_test->needs_drivers) { > -- > 2.51.0 > -- Cyril Hrubis chrubis@suse.cz -- Mailing list info: https://lists.linux.it/listinfo/ltp ^ permalink raw reply [flat|nested] 100+ messages in thread
* [LTP] [PATCH v1 2/2] ioctl_loop01.c: Update to new .needs_cmds struct 2025-09-26 8:50 [LTP] [PATCH v1 0/2] new cmd support option for needs_cmds Wei Gao via ltp 2025-09-26 8:50 ` [LTP] [PATCH v1 1/2] lib: Add support option for .needs_cmds Wei Gao via ltp @ 2025-09-26 8:50 ` Wei Gao via ltp 2025-09-26 9:32 ` Cyril Hrubis 2025-09-28 23:26 ` [LTP] [PATCH v1 0/2] new cmd support option for needs_cmds Wei Gao via ltp 2 siblings, 1 reply; 100+ messages in thread From: Wei Gao via ltp @ 2025-09-26 8:50 UTC (permalink / raw) To: ltp NOTE:This patchset is draft for review not final one. Since not include update .needs_cmds for all related testcases. Suggested-by: Cyril Hrubis <chrubis@suse.cz> Signed-off-by: Wei Gao <wegao@suse.com> --- .../kernel/syscalls/ioctl/ioctl_loop01.c | 23 ++++++++----------- 1 file changed, 9 insertions(+), 14 deletions(-) diff --git a/testcases/kernel/syscalls/ioctl/ioctl_loop01.c b/testcases/kernel/syscalls/ioctl/ioctl_loop01.c index c9137bf1e..a3f0857e3 100644 --- a/testcases/kernel/syscalls/ioctl/ioctl_loop01.c +++ b/testcases/kernel/syscalls/ioctl/ioctl_loop01.c @@ -97,9 +97,10 @@ static void verify_ioctl_loop(void) static void setup(void) { - int ret; + parted_sup = tst_cmd_present(test.needs_cmds, "parted"); + const char *const cmd_parted[] = {"parted", "-s", "test.img", "mklabel", "msdos", "mkpart", - "primary", "ext4", "1M", "10M", NULL}; + "primary", "ext4", "1M", "10M", NULL}; dev_num = tst_find_free_loopdev(dev_path, sizeof(dev_path)); if (dev_num < 0) @@ -107,18 +108,8 @@ static void setup(void) tst_fill_file("test.img", 0, 1024 * 1024, 10); - ret = tst_cmd(cmd_parted, NULL, NULL, TST_CMD_PASS_RETVAL); - switch (ret) { - case 0: - parted_sup = 1; - break; - case 255: - tst_res(TCONF, "parted binary not installed or failed"); - break; - default: - tst_res(TCONF, "parted exited with %i", ret); - break; - } + if (parted_sup) + SAFE_CMD(cmd_parted, NULL, NULL); sprintf(partscan_path, "/sys/block/loop%d/loop/partscan", dev_num); sprintf(autoclear_path, "/sys/block/loop%d/loop/autoclear", dev_num); @@ -152,5 +143,9 @@ static struct tst_test test = { {"linux-git", "6ac92fb5cdff"}, {} }, + .needs_cmds = (struct tst_cmd[]) { + {"parted", 0, 0}, + {} + }, .needs_tmpdir = 1, }; -- 2.51.0 -- Mailing list info: https://lists.linux.it/listinfo/ltp ^ permalink raw reply related [flat|nested] 100+ messages in thread
* Re: [LTP] [PATCH v1 2/2] ioctl_loop01.c: Update to new .needs_cmds struct 2025-09-26 8:50 ` [LTP] [PATCH v1 2/2] ioctl_loop01.c: Update to new .needs_cmds struct Wei Gao via ltp @ 2025-09-26 9:32 ` Cyril Hrubis 0 siblings, 0 replies; 100+ messages in thread From: Cyril Hrubis @ 2025-09-26 9:32 UTC (permalink / raw) To: Wei Gao; +Cc: ltp On Fri, Sep 26, 2025 at 08:50:12AM +0000, Wei Gao wrote: > NOTE:This patchset is draft for review not final one. > Since not include update .needs_cmds for all related testcases. > > Suggested-by: Cyril Hrubis <chrubis@suse.cz> > Signed-off-by: Wei Gao <wegao@suse.com> > --- > .../kernel/syscalls/ioctl/ioctl_loop01.c | 23 ++++++++----------- > 1 file changed, 9 insertions(+), 14 deletions(-) > > diff --git a/testcases/kernel/syscalls/ioctl/ioctl_loop01.c b/testcases/kernel/syscalls/ioctl/ioctl_loop01.c > index c9137bf1e..a3f0857e3 100644 > --- a/testcases/kernel/syscalls/ioctl/ioctl_loop01.c > +++ b/testcases/kernel/syscalls/ioctl/ioctl_loop01.c > @@ -97,9 +97,10 @@ static void verify_ioctl_loop(void) > > static void setup(void) > { > - int ret; > + parted_sup = tst_cmd_present(test.needs_cmds, "parted"); > + > const char *const cmd_parted[] = {"parted", "-s", "test.img", "mklabel", "msdos", "mkpart", > - "primary", "ext4", "1M", "10M", NULL}; > + "primary", "ext4", "1M", "10M", NULL}; > > dev_num = tst_find_free_loopdev(dev_path, sizeof(dev_path)); > if (dev_num < 0) > @@ -107,18 +108,8 @@ static void setup(void) > > tst_fill_file("test.img", 0, 1024 * 1024, 10); > > - ret = tst_cmd(cmd_parted, NULL, NULL, TST_CMD_PASS_RETVAL); > - switch (ret) { > - case 0: > - parted_sup = 1; > - break; > - case 255: > - tst_res(TCONF, "parted binary not installed or failed"); > - break; > - default: > - tst_res(TCONF, "parted exited with %i", ret); > - break; > - } > + if (parted_sup) > + SAFE_CMD(cmd_parted, NULL, NULL); > > sprintf(partscan_path, "/sys/block/loop%d/loop/partscan", dev_num); > sprintf(autoclear_path, "/sys/block/loop%d/loop/autoclear", dev_num); > @@ -152,5 +143,9 @@ static struct tst_test test = { > {"linux-git", "6ac92fb5cdff"}, > {} > }, > + .needs_cmds = (struct tst_cmd[]) { > + {"parted", 0, 0}, No need to pass the zeros if we just initialize the cmd part. Also I would use the named initializers as: {.cmd = "parted", .optional = 1}, > + {} > + }, > .needs_tmpdir = 1, > }; > -- > 2.51.0 > -- Cyril Hrubis chrubis@suse.cz -- Mailing list info: https://lists.linux.it/listinfo/ltp ^ permalink raw reply [flat|nested] 100+ messages in thread
* [LTP] [PATCH v1 0/2] new cmd support option for needs_cmds 2025-09-26 8:50 [LTP] [PATCH v1 0/2] new cmd support option for needs_cmds Wei Gao via ltp 2025-09-26 8:50 ` [LTP] [PATCH v1 1/2] lib: Add support option for .needs_cmds Wei Gao via ltp 2025-09-26 8:50 ` [LTP] [PATCH v1 2/2] ioctl_loop01.c: Update to new .needs_cmds struct Wei Gao via ltp @ 2025-09-28 23:26 ` Wei Gao via ltp 2025-09-28 23:26 ` [LTP] [PATCH v2 1/2] lib: Add support option for .needs_cmds Wei Gao via ltp 2025-09-28 23:26 ` [LTP] [PATCH v2 2/2] ioctl_loop01.c: Update to new .needs_cmds struct Wei Gao via ltp 2 siblings, 2 replies; 100+ messages in thread From: Wei Gao via ltp @ 2025-09-28 23:26 UTC (permalink / raw) To: ltp Changes in v2: - update base Cyril's comments Wei Gao (2): lib: Add support option for .needs_cmds ioctl_loop01.c: Update to new .needs_cmds struct include/tst_cmd.h | 6 +++++ include/tst_test.h | 8 +++++- lib/tst_cmd.c | 7 +++++- lib/tst_test.c | 25 ++++++++++++++++--- .../kernel/syscalls/ioctl/ioctl_loop01.c | 23 +++++++---------- 5 files changed, 49 insertions(+), 20 deletions(-) -- 2.51.0 -- Mailing list info: https://lists.linux.it/listinfo/ltp ^ permalink raw reply [flat|nested] 100+ messages in thread
* [LTP] [PATCH v2 1/2] lib: Add support option for .needs_cmds 2025-09-28 23:26 ` [LTP] [PATCH v1 0/2] new cmd support option for needs_cmds Wei Gao via ltp @ 2025-09-28 23:26 ` Wei Gao via ltp 2025-09-30 13:36 ` Petr Vorel 2025-10-10 6:45 ` [LTP] [PATCH v3 0/4] new cmd support option for needs_cmds Wei Gao via ltp 2025-09-28 23:26 ` [LTP] [PATCH v2 2/2] ioctl_loop01.c: Update to new .needs_cmds struct Wei Gao via ltp 1 sibling, 2 replies; 100+ messages in thread From: Wei Gao via ltp @ 2025-09-28 23:26 UTC (permalink / raw) To: ltp Signed-off-by: Wei Gao <wegao@suse.com> Suggested-by: Cyril Hrubis <chrubis@suse.cz> --- include/tst_cmd.h | 6 ++++++ include/tst_test.h | 8 +++++++- lib/tst_cmd.c | 7 ++++++- lib/tst_test.c | 25 +++++++++++++++++++++---- 4 files changed, 40 insertions(+), 6 deletions(-) diff --git a/include/tst_cmd.h b/include/tst_cmd.h index 939825646..148afc49c 100644 --- a/include/tst_cmd.h +++ b/include/tst_cmd.h @@ -16,6 +16,12 @@ enum tst_cmd_flags { TST_CMD_TCONF_ON_MISSING = 2, }; +struct tst_cmd { + const char *cmd; + unsigned int optional:1; + unsigned int present:1; +}; + /* * vfork() + execvp() specified program. * diff --git a/include/tst_test.h b/include/tst_test.h index 9c21c1728..bef836525 100644 --- a/include/tst_test.h +++ b/include/tst_test.h @@ -617,7 +617,7 @@ struct tst_fs { const struct tst_tag *tags; - const char *const *needs_cmds; + struct tst_cmd *needs_cmds; const enum tst_cg_ver needs_cgroup_ver; @@ -721,6 +721,12 @@ int tst_creat_unlinked(const char *path, int flags, mode_t mode); */ const char *tst_get_tmpdir_root(void); +/* + * tst_cmd_present would loop over the tst_cmd array and return the supported flag + * value. + */ +bool tst_cmd_present(const char *cmd); + /* * Validates exit status of child processes */ diff --git a/lib/tst_cmd.c b/lib/tst_cmd.c index 82d60497a..cfd38c31a 100644 --- a/lib/tst_cmd.c +++ b/lib/tst_cmd.c @@ -265,7 +265,12 @@ int tst_check_cmd(const char *cmd, const int brk_nosupp) str = strtok_r(NULL, " ", &next); if (tst_get_path(cmd_token, path, sizeof(path))) - tst_brkm(TCONF, NULL, "Couldn't find '%s' in $PATH", cmd_token); + if (brk_nosupp) { + tst_brkm(TCONF, NULL, "Couldn't find '%s' in $PATH", cmd_token); + } else { + tst_resm(TCONF, "Couldn't find '%s' in $PATH", cmd_token); + return 1; + } if (!op_token) return 0; diff --git a/lib/tst_test.c b/lib/tst_test.c index b8894f782..ed9459e2f 100644 --- a/lib/tst_test.c +++ b/lib/tst_test.c @@ -1353,6 +1353,19 @@ static const char *default_fs_type(void) return tst_dev_fs_type(); } +bool tst_cmd_present(const char *cmd) +{ + struct tst_cmd *pcmd = tst_test->needs_cmds; + + while (pcmd->cmd) { + if (!strcmp(pcmd->cmd, cmd)) + return pcmd->present; + + pcmd++; + } + return false; +} + static void do_setup(int argc, char *argv[]) { char *tdebug_env = getenv("LTP_ENABLE_DEBUG"); @@ -1422,11 +1435,15 @@ static void do_setup(int argc, char *argv[]) tst_brk(TCONF, "%dbit ABI is not supported", tst_test->needs_abi_bits); if (tst_test->needs_cmds) { - const char *cmd; - int i; + struct tst_cmd *pcmd = tst_test->needs_cmds; - for (i = 0; (cmd = tst_test->needs_cmds[i]); ++i) - tst_check_cmd(cmd, 1); + while (pcmd->cmd) { + if (tst_check_cmd(pcmd->cmd, !pcmd->optional)) + pcmd->present = 0; + else + pcmd->present = 1; + pcmd++; + } } if (tst_test->needs_drivers) { -- 2.51.0 -- Mailing list info: https://lists.linux.it/listinfo/ltp ^ permalink raw reply related [flat|nested] 100+ messages in thread
* Re: [LTP] [PATCH v2 1/2] lib: Add support option for .needs_cmds 2025-09-28 23:26 ` [LTP] [PATCH v2 1/2] lib: Add support option for .needs_cmds Wei Gao via ltp @ 2025-09-30 13:36 ` Petr Vorel 2025-10-10 6:32 ` Wei Gao via ltp 2025-10-10 6:45 ` [LTP] [PATCH v3 0/4] new cmd support option for needs_cmds Wei Gao via ltp 1 sibling, 1 reply; 100+ messages in thread From: Petr Vorel @ 2025-09-30 13:36 UTC (permalink / raw) To: Wei Gao; +Cc: ltp Hi Wei, ... > +++ b/include/tst_cmd.h > @@ -16,6 +16,12 @@ enum tst_cmd_flags { > TST_CMD_TCONF_ON_MISSING = 2, > }; > +struct tst_cmd { > + const char *cmd; > + unsigned int optional:1; > + unsigned int present:1; Maybe s/present/available/ ? > +}; Could you please add doc? Whole include/tst_cmd.h is documented, it's obvious that new functionality should be documented. And best would be if you use kerneldoc syntax. https://docs.kernel.org/doc-guide/kernel-doc.html https://www.sphinx-doc.org/en/master/usage/domains/c.html > + > /* > * vfork() + execvp() specified program. > * > diff --git a/include/tst_test.h b/include/tst_test.h > index 9c21c1728..bef836525 100644 > --- a/include/tst_test.h > +++ b/include/tst_test.h > @@ -617,7 +617,7 @@ struct tst_fs { > const struct tst_tag *tags; > - const char *const *needs_cmds; > + struct tst_cmd *needs_cmds; This effectively breaks build, because you haven't update any of these users (24 tests + 2 doc files. > const enum tst_cg_ver needs_cgroup_ver; > @@ -721,6 +721,12 @@ int tst_creat_unlinked(const char *path, int flags, mode_t mode); > */ > const char *tst_get_tmpdir_root(void); > +/* > + * tst_cmd_present would loop over the tst_cmd array and return the supported flag I'm not a native speaker, but I think: s/would loop/loops/ > + * value. > + */ Please use kernel doc syntax (see links above). > +bool tst_cmd_present(const char *cmd); > + > /* > * Validates exit status of child processes > */ > diff --git a/lib/tst_cmd.c b/lib/tst_cmd.c > index 82d60497a..cfd38c31a 100644 > --- a/lib/tst_cmd.c > +++ b/lib/tst_cmd.c > @@ -265,7 +265,12 @@ int tst_check_cmd(const char *cmd, const int brk_nosupp) > str = strtok_r(NULL, " ", &next); > if (tst_get_path(cmd_token, path, sizeof(path))) > - tst_brkm(TCONF, NULL, "Couldn't find '%s' in $PATH", cmd_token); > + if (brk_nosupp) { > + tst_brkm(TCONF, NULL, "Couldn't find '%s' in $PATH", cmd_token); > + } else { > + tst_resm(TCONF, "Couldn't find '%s' in $PATH", cmd_token); > + return 1; > + } +1 ... > +++ b/lib/tst_test.c > @@ -1353,6 +1353,19 @@ static const char *default_fs_type(void) > return tst_dev_fs_type(); > } > +bool tst_cmd_present(const char *cmd) > +{ > + struct tst_cmd *pcmd = tst_test->needs_cmds; > + > + while (pcmd->cmd) { > + if (!strcmp(pcmd->cmd, cmd)) > + return pcmd->present; > + > + pcmd++; > + } > + return false; > +} > + > static void do_setup(int argc, char *argv[]) > { > char *tdebug_env = getenv("LTP_ENABLE_DEBUG"); > @@ -1422,11 +1435,15 @@ static void do_setup(int argc, char *argv[]) > tst_brk(TCONF, "%dbit ABI is not supported", tst_test->needs_abi_bits); > if (tst_test->needs_cmds) { > - const char *cmd; > - int i; > + struct tst_cmd *pcmd = tst_test->needs_cmds; > - for (i = 0; (cmd = tst_test->needs_cmds[i]); ++i) > - tst_check_cmd(cmd, 1); > + while (pcmd->cmd) { > + if (tst_check_cmd(pcmd->cmd, !pcmd->optional)) > + pcmd->present = 0; > + else > + pcmd->present = 1; very nit: use ternary operator? pcmd->present = tst_check_cmd(pcmd->cmd, !pcmd->optional) ? 0 : 1; Kind regards, Petr > + pcmd++; > + } -- Mailing list info: https://lists.linux.it/listinfo/ltp ^ permalink raw reply [flat|nested] 100+ messages in thread
* Re: [LTP] [PATCH v2 1/2] lib: Add support option for .needs_cmds 2025-09-30 13:36 ` Petr Vorel @ 2025-10-10 6:32 ` Wei Gao via ltp 0 siblings, 0 replies; 100+ messages in thread From: Wei Gao via ltp @ 2025-10-10 6:32 UTC (permalink / raw) To: Petr Vorel; +Cc: ltp On Tue, Sep 30, 2025 at 03:36:23PM +0200, Petr Vorel wrote: > Hi Wei, > > ... > > +++ b/include/tst_cmd.h > > @@ -16,6 +16,12 @@ enum tst_cmd_flags { > > TST_CMD_TCONF_ON_MISSING = 2, > > }; > > > +struct tst_cmd { > > + const char *cmd; > > + unsigned int optional:1; > > + unsigned int present:1; > > Maybe s/present/available/ ? This is suggested by Cyril Hrubis during v1 review. -- Mailing list info: https://lists.linux.it/listinfo/ltp ^ permalink raw reply [flat|nested] 100+ messages in thread
* [LTP] [PATCH v3 0/4] new cmd support option for needs_cmds 2025-09-28 23:26 ` [LTP] [PATCH v2 1/2] lib: Add support option for .needs_cmds Wei Gao via ltp 2025-09-30 13:36 ` Petr Vorel @ 2025-10-10 6:45 ` Wei Gao via ltp 2025-10-10 6:45 ` [LTP] [PATCH v3 1/4] lib: Add support option for .needs_cmds Wei Gao via ltp ` (5 more replies) 1 sibling, 6 replies; 100+ messages in thread From: Wei Gao via ltp @ 2025-10-10 6:45 UTC (permalink / raw) To: ltp Changes in v2: - update base Cyril's comments Changes in v3: - update all new needs_cmds related test cases - fix Ci issue for tst_run_shell.c Wei Gao (4): lib: Add support option for .needs_cmds ioctl_loop01.c: Update to new .needs_cmds struct Update test cases use new needs_cmds tst_run_shell.c: Add new function handle new needs_cmds include/tst_cmd.h | 13 ++++ include/tst_test.h | 15 ++++- lib/newlib_tests/tst_needs_cmds01.c | 16 ++--- lib/newlib_tests/tst_needs_cmds02.c | 6 +- lib/newlib_tests/tst_needs_cmds03.c | 6 +- lib/newlib_tests/tst_needs_cmds04.c | 6 +- lib/newlib_tests/tst_needs_cmds05.c | 6 +- lib/newlib_tests/tst_needs_cmds06.c | 6 +- lib/newlib_tests/tst_needs_cmds07.c | 6 +- lib/newlib_tests/tst_needs_cmds08.c | 8 +-- lib/tst_cmd.c | 7 ++- lib/tst_test.c | 22 +++++-- testcases/kernel/device-drivers/zram/zram03.c | 8 +-- testcases/kernel/fs/squashfs/squashfs01.c | 6 +- testcases/kernel/security/aslr/aslr01.c | 6 +- testcases/kernel/syscalls/add_key/add_key05.c | 10 +-- .../kernel/syscalls/fanotify/fanotify22.c | 6 +- testcases/kernel/syscalls/ioctl/ioctl09.c | 6 +- .../kernel/syscalls/ioctl/ioctl_loop01.c | 28 ++++----- testcases/kernel/syscalls/madvise/madvise11.c | 8 +-- .../kernel/syscalls/quotactl/quotactl01.c | 6 +- .../kernel/syscalls/quotactl/quotactl04.c | 6 +- .../kernel/syscalls/quotactl/quotactl06.c | 6 +- .../kernel/syscalls/quotactl/quotactl08.c | 6 +- .../kernel/syscalls/quotactl/quotactl09.c | 6 +- testcases/kernel/syscalls/statx/statx05.c | 8 +-- testcases/kernel/syscalls/statx/statx07.c | 6 +- testcases/kernel/syscalls/statx/statx09.c | 6 +- testcases/lib/tst_run_shell.c | 61 ++++++++++++++++++- 29 files changed, 204 insertions(+), 102 deletions(-) -- 2.51.0 -- Mailing list info: https://lists.linux.it/listinfo/ltp ^ permalink raw reply [flat|nested] 100+ messages in thread
* [LTP] [PATCH v3 1/4] lib: Add support option for .needs_cmds 2025-10-10 6:45 ` [LTP] [PATCH v3 0/4] new cmd support option for needs_cmds Wei Gao via ltp @ 2025-10-10 6:45 ` Wei Gao via ltp 2025-10-10 9:13 ` Petr Vorel 2025-10-10 6:45 ` [LTP] [PATCH v3 2/4] ioctl_loop01.c: Update to new .needs_cmds struct Wei Gao via ltp ` (4 subsequent siblings) 5 siblings, 1 reply; 100+ messages in thread From: Wei Gao via ltp @ 2025-10-10 6:45 UTC (permalink / raw) To: ltp Signed-off-by: Wei Gao <wegao@suse.com> Suggested-by: Cyril Hrubis <chrubis@suse.cz> --- include/tst_cmd.h | 13 +++++++++++++ include/tst_test.h | 15 +++++++++++++-- lib/tst_cmd.c | 7 ++++++- lib/tst_test.c | 22 ++++++++++++++++++---- 4 files changed, 50 insertions(+), 7 deletions(-) diff --git a/include/tst_cmd.h b/include/tst_cmd.h index 939825646..703589019 100644 --- a/include/tst_cmd.h +++ b/include/tst_cmd.h @@ -16,6 +16,19 @@ enum tst_cmd_flags { TST_CMD_TCONF_ON_MISSING = 2, }; +/** + * struct tst_cmd - This structure provides details about a command needed by LTP test + * @cmd: The name of the command. + * @optional: A flag indicating if the command is optional. + * @present: A flag indicating if the command was found at runtime, this is an output + * parameter, set by the LTP library during the test setup. + */ +struct tst_cmd { + const char *cmd; + unsigned int optional:1; + unsigned int present:1; +}; + /* * vfork() + execvp() specified program. * diff --git a/include/tst_test.h b/include/tst_test.h index 9c21c1728..2730d22c1 100644 --- a/include/tst_test.h +++ b/include/tst_test.h @@ -524,7 +524,7 @@ struct tst_fs { * * @tags: A {} terminated array of test tags. See struct tst_tag for details. * - * @needs_cmds: A NULL terminated array of commands required for the test to run. + * @needs_cmds: A NULL terminated array of struct tst_cmd required for the test to run. * * @needs_cgroup_ver: If set the test will run only if the specified cgroup * version is present on the system. @@ -617,7 +617,7 @@ struct tst_fs { const struct tst_tag *tags; - const char *const *needs_cmds; + struct tst_cmd *needs_cmds; const enum tst_cg_ver needs_cgroup_ver; @@ -721,6 +721,17 @@ int tst_creat_unlinked(const char *path, int flags, mode_t mode); */ const char *tst_get_tmpdir_root(void); +/** + * tst_cmd_present() - Check if a command is present + * @cmd: The name of the command to check for. + * + * This function iterates through the 'needs_cmds' array. It compares the given command name + * with each entry in the array and returns the 'present' flag for the matching command. + * + * Return: `true` if the command is present, `false` otherwise. + */ +bool tst_cmd_present(const char *cmd); + /* * Validates exit status of child processes */ diff --git a/lib/tst_cmd.c b/lib/tst_cmd.c index 82d60497a..cfd38c31a 100644 --- a/lib/tst_cmd.c +++ b/lib/tst_cmd.c @@ -265,7 +265,12 @@ int tst_check_cmd(const char *cmd, const int brk_nosupp) str = strtok_r(NULL, " ", &next); if (tst_get_path(cmd_token, path, sizeof(path))) - tst_brkm(TCONF, NULL, "Couldn't find '%s' in $PATH", cmd_token); + if (brk_nosupp) { + tst_brkm(TCONF, NULL, "Couldn't find '%s' in $PATH", cmd_token); + } else { + tst_resm(TCONF, "Couldn't find '%s' in $PATH", cmd_token); + return 1; + } if (!op_token) return 0; diff --git a/lib/tst_test.c b/lib/tst_test.c index 53b53af1a..6bd0ea44a 100644 --- a/lib/tst_test.c +++ b/lib/tst_test.c @@ -1365,6 +1365,19 @@ static const char *default_fs_type(void) return tst_dev_fs_type(); } +bool tst_cmd_present(const char *cmd) +{ + struct tst_cmd *pcmd = tst_test->needs_cmds; + + while (pcmd->cmd) { + if (!strcmp(pcmd->cmd, cmd)) + return pcmd->present; + + pcmd++; + } + return false; +} + static void do_setup(int argc, char *argv[]) { char *tdebug_env = getenv("LTP_ENABLE_DEBUG"); @@ -1439,11 +1452,12 @@ static void do_setup(int argc, char *argv[]) tst_brk(TCONF, "%dbit ABI is not supported", tst_test->needs_abi_bits); if (tst_test->needs_cmds) { - const char *cmd; - int i; + struct tst_cmd *pcmd = tst_test->needs_cmds; - for (i = 0; (cmd = tst_test->needs_cmds[i]); ++i) - tst_check_cmd(cmd, 1); + while (pcmd->cmd) { + pcmd->present = tst_check_cmd(pcmd->cmd, !pcmd->optional) ? 0 : 1; + pcmd++; + } } if (tst_test->needs_drivers) { -- 2.51.0 -- Mailing list info: https://lists.linux.it/listinfo/ltp ^ permalink raw reply related [flat|nested] 100+ messages in thread
* Re: [LTP] [PATCH v3 1/4] lib: Add support option for .needs_cmds 2025-10-10 6:45 ` [LTP] [PATCH v3 1/4] lib: Add support option for .needs_cmds Wei Gao via ltp @ 2025-10-10 9:13 ` Petr Vorel 2025-10-10 9:45 ` Petr Vorel 0 siblings, 1 reply; 100+ messages in thread From: Petr Vorel @ 2025-10-10 9:13 UTC (permalink / raw) To: Wei Gao; +Cc: ltp Hi Wei, > --- > include/tst_cmd.h | 13 +++++++++++++ > include/tst_test.h | 15 +++++++++++++-- > lib/tst_cmd.c | 7 ++++++- > lib/tst_test.c | 22 ++++++++++++++++++---- > 4 files changed, 50 insertions(+), 7 deletions(-) tst_needs_cmds01.c:15:23: error: initialization of ‘struct tst_cmd *’ from incompatible pointer type ‘const char **’ [-Wincompatible-pointer-types] 15 | .needs_cmds = (const char *[]) { | ^ tst_needs_cmds01.c:15:23: note: (near initialization for ‘test.needs_cmds’) make[1]: *** [../../include/mk/rules.mk:48: tst_needs_cmds01] Error 1 I asked on v2 not to break build [1], but you didn't reflected that. The reason for this requirement is that all commits need to built due ability to bisect (quite obvious requirement). This mean you need in this commit also modify all the tests which use .needs_cmds, i.e. 3rd commit "Update test cases use new needs_cmds" needs to be squashed into this 1st commit. [1] https://lore.kernel.org/ltp/20250930133623.GB238065@pevik/ > diff --git a/include/tst_cmd.h b/include/tst_cmd.h > index 939825646..703589019 100644 > --- a/include/tst_cmd.h > +++ b/include/tst_cmd.h > @@ -16,6 +16,19 @@ enum tst_cmd_flags { > TST_CMD_TCONF_ON_MISSING = 2, > }; > +/** > + * struct tst_cmd - This structure provides details about a command needed by LTP test I would personally avoid "This structure" / "This function". Missing dot at the end. > + * @cmd: The name of the command. > + * @optional: A flag indicating if the command is optional. > + * @present: A flag indicating if the command was found at runtime, this is an output Maybe use 2 sentences: * @present: A flag indicating if the command was found at runtime. This is an output > + * parameter, set by the LTP library during the test setup. > + */ > +struct tst_cmd { > + const char *cmd; > + unsigned int optional:1; > + unsigned int present:1; Hopefully nobody misuses this to set it in the test. > +}; > + > /* > * vfork() + execvp() specified program. > * > diff --git a/include/tst_test.h b/include/tst_test.h > index 9c21c1728..2730d22c1 100644 > --- a/include/tst_test.h > +++ b/include/tst_test.h > @@ -524,7 +524,7 @@ struct tst_fs { > * > * @tags: A {} terminated array of test tags. See struct tst_tag for details. > * > - * @needs_cmds: A NULL terminated array of commands required for the test to run. > + * @needs_cmds: A NULL terminated array of struct tst_cmd required for the test to run. > * > * @needs_cgroup_ver: If set the test will run only if the specified cgroup > * version is present on the system. > @@ -617,7 +617,7 @@ struct tst_fs { > const struct tst_tag *tags; > - const char *const *needs_cmds; > + struct tst_cmd *needs_cmds; > const enum tst_cg_ver needs_cgroup_ver; > @@ -721,6 +721,17 @@ int tst_creat_unlinked(const char *path, int flags, mode_t mode); > */ > const char *tst_get_tmpdir_root(void); > +/** > + * tst_cmd_present() - Check if a command is present > + * @cmd: The name of the command to check for. > + * > + * This function iterates through the 'needs_cmds' array. It compares the given command name Please use &tst_test->needs_cmds: * This function iterates through the &tst_test->needs_cmds array. It compares * the given command name with each entry in the array and returns the 'present' * flag for the matching command. That helps struct to be linkable. > + * with each entry in the array and returns the 'present' flag for the matching command. > + * > + * Return: `true` if the command is present, `false` otherwise. This needs to be Returns: (missing s) https://docs.kernel.org/doc-guide/kernel-doc.html Kind regards, Petr -- Mailing list info: https://lists.linux.it/listinfo/ltp ^ permalink raw reply [flat|nested] 100+ messages in thread
* Re: [LTP] [PATCH v3 1/4] lib: Add support option for .needs_cmds 2025-10-10 9:13 ` Petr Vorel @ 2025-10-10 9:45 ` Petr Vorel 0 siblings, 0 replies; 100+ messages in thread From: Petr Vorel @ 2025-10-10 9:45 UTC (permalink / raw) To: Wei Gao, ltp, Cyril Hrubis > Hi Wei, > > + * with each entry in the array and returns the 'present' flag for the matching command. > > + * > > + * Return: `true` if the command is present, `false` otherwise. > This needs to be Returns: (missing s) > https://docs.kernel.org/doc-guide/kernel-doc.html I'm sorry, I was wrong, it should be 'Return:', kerneldoc is wrong. Kind regards, Petr > Kind regards, > Petr -- Mailing list info: https://lists.linux.it/listinfo/ltp ^ permalink raw reply [flat|nested] 100+ messages in thread
* [LTP] [PATCH v3 2/4] ioctl_loop01.c: Update to new .needs_cmds struct 2025-10-10 6:45 ` [LTP] [PATCH v3 0/4] new cmd support option for needs_cmds Wei Gao via ltp 2025-10-10 6:45 ` [LTP] [PATCH v3 1/4] lib: Add support option for .needs_cmds Wei Gao via ltp @ 2025-10-10 6:45 ` Wei Gao via ltp 2025-10-10 6:45 ` [LTP] [PATCH v3 3/4] Update test cases use new needs_cmds Wei Gao via ltp ` (3 subsequent siblings) 5 siblings, 0 replies; 100+ messages in thread From: Wei Gao via ltp @ 2025-10-10 6:45 UTC (permalink / raw) To: ltp Suggested-by: Cyril Hrubis <chrubis@suse.cz> Signed-off-by: Wei Gao <wegao@suse.com> Reviewed-by: Petr Vorel <pvorel@suse.cz> --- .../kernel/syscalls/ioctl/ioctl_loop01.c | 28 +++++++++---------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/testcases/kernel/syscalls/ioctl/ioctl_loop01.c b/testcases/kernel/syscalls/ioctl/ioctl_loop01.c index cb1b506d2..fe62e7e5a 100644 --- a/testcases/kernel/syscalls/ioctl/ioctl_loop01.c +++ b/testcases/kernel/syscalls/ioctl/ioctl_loop01.c @@ -78,21 +78,7 @@ static void check_loop_value(int set_flag, int get_flag, int autoclear_field) static void verify_ioctl_loop(void) { - int ret; - const char *const cmd_parted[] = {"parted", "-s", dev_path, "mklabel", "msdos", "mkpart", - "primary", "ext4", "1M", "10M", NULL}; - - tst_fill_file("test.img", 0, 1024 * 1024, 10); tst_attach_device(dev_path, "test.img"); - - ret = tst_cmd(cmd_parted, NULL, NULL, TST_CMD_PASS_RETVAL); - if (!ret) - parted_sup = 1; - else if (ret == 255) - tst_res(TCONF, "parted binary not installed or failed"); - else - tst_res(TCONF, "parted exited with %i", ret); - attach_flag = 1; TST_ASSERT_INT(partscan_path, 0); @@ -112,10 +98,20 @@ static void verify_ioctl_loop(void) static void setup(void) { + parted_sup = tst_cmd_present("parted"); + + const char *const cmd_parted[] = {"parted", "-s", "test.img", "mklabel", "msdos", "mkpart", + "primary", "ext4", "1M", "10M", NULL}; + dev_num = tst_find_free_loopdev(dev_path, sizeof(dev_path)); if (dev_num < 0) tst_brk(TBROK, "Failed to find free loop device"); + tst_fill_file("test.img", 0, 1024 * 1024, 10); + + if (parted_sup) + SAFE_CMD(cmd_parted, NULL, NULL); + sprintf(partscan_path, "/sys/block/loop%d/loop/partscan", dev_num); sprintf(autoclear_path, "/sys/block/loop%d/loop/autoclear", dev_num); sprintf(backing_path, "/sys/block/loop%d/loop/backing_file", dev_num); @@ -148,5 +144,9 @@ static struct tst_test test = { {"linux-git", "6ac92fb5cdff"}, {} }, + .needs_cmds = (struct tst_cmd[]) { + {.cmd = "parted", .optional = 1}, + {} + }, .needs_tmpdir = 1, }; -- 2.51.0 -- Mailing list info: https://lists.linux.it/listinfo/ltp ^ permalink raw reply related [flat|nested] 100+ messages in thread
* [LTP] [PATCH v3 3/4] Update test cases use new needs_cmds 2025-10-10 6:45 ` [LTP] [PATCH v3 0/4] new cmd support option for needs_cmds Wei Gao via ltp 2025-10-10 6:45 ` [LTP] [PATCH v3 1/4] lib: Add support option for .needs_cmds Wei Gao via ltp 2025-10-10 6:45 ` [LTP] [PATCH v3 2/4] ioctl_loop01.c: Update to new .needs_cmds struct Wei Gao via ltp @ 2025-10-10 6:45 ` Wei Gao via ltp 2025-10-10 6:45 ` [LTP] [PATCH v3 4/4] tst_run_shell.c: Add new function handle " Wei Gao via ltp ` (2 subsequent siblings) 5 siblings, 0 replies; 100+ messages in thread From: Wei Gao via ltp @ 2025-10-10 6:45 UTC (permalink / raw) To: ltp Signed-off-by: Wei Gao <wegao@suse.com> --- lib/newlib_tests/tst_needs_cmds01.c | 16 ++++++++-------- lib/newlib_tests/tst_needs_cmds02.c | 6 +++--- lib/newlib_tests/tst_needs_cmds03.c | 6 +++--- lib/newlib_tests/tst_needs_cmds04.c | 6 +++--- lib/newlib_tests/tst_needs_cmds05.c | 6 +++--- lib/newlib_tests/tst_needs_cmds06.c | 6 +++--- lib/newlib_tests/tst_needs_cmds07.c | 6 +++--- lib/newlib_tests/tst_needs_cmds08.c | 8 ++++---- testcases/kernel/device-drivers/zram/zram03.c | 8 ++++---- testcases/kernel/fs/squashfs/squashfs01.c | 6 +++--- testcases/kernel/security/aslr/aslr01.c | 6 +++--- testcases/kernel/syscalls/add_key/add_key05.c | 10 +++++----- testcases/kernel/syscalls/fanotify/fanotify22.c | 6 +++--- testcases/kernel/syscalls/ioctl/ioctl09.c | 6 +++--- testcases/kernel/syscalls/madvise/madvise11.c | 8 ++++---- testcases/kernel/syscalls/quotactl/quotactl01.c | 6 +++--- testcases/kernel/syscalls/quotactl/quotactl04.c | 6 +++--- testcases/kernel/syscalls/quotactl/quotactl06.c | 6 +++--- testcases/kernel/syscalls/quotactl/quotactl08.c | 6 +++--- testcases/kernel/syscalls/quotactl/quotactl09.c | 6 +++--- testcases/kernel/syscalls/statx/statx05.c | 8 ++++---- testcases/kernel/syscalls/statx/statx07.c | 6 +++--- testcases/kernel/syscalls/statx/statx09.c | 6 +++--- 23 files changed, 80 insertions(+), 80 deletions(-) diff --git a/lib/newlib_tests/tst_needs_cmds01.c b/lib/newlib_tests/tst_needs_cmds01.c index 777c69505..592456da6 100644 --- a/lib/newlib_tests/tst_needs_cmds01.c +++ b/lib/newlib_tests/tst_needs_cmds01.c @@ -12,13 +12,13 @@ static void do_test(void) static struct tst_test test = { .test_all = do_test, - .needs_cmds = (const char *[]) { - "mkfs.ext4", - "mkfs.ext4 >= 1.0.0", - "mkfs.ext4 <= 2.0.0", - "mkfs.ext4 != 2.0.0", - "mkfs.ext4 > 1.0.0", - "mkfs.ext4 < 2.0.0", - NULL + .needs_cmds = (struct tst_cmd[]) { + {.cmd = "mkfs.ext4"}, + {.cmd = "mkfs.ext4 >= 1.0.0"}, + {.cmd = "mkfs.ext4 <= 2.0.0"}, + {.cmd = "mkfs.ext4 != 2.0.0"}, + {.cmd = "mkfs.ext4 > 1.0.0"}, + {.cmd = "mkfs.ext4 < 2.0.0"}, + {} } }; diff --git a/lib/newlib_tests/tst_needs_cmds02.c b/lib/newlib_tests/tst_needs_cmds02.c index 455a275ea..f1d6105c2 100644 --- a/lib/newlib_tests/tst_needs_cmds02.c +++ b/lib/newlib_tests/tst_needs_cmds02.c @@ -16,8 +16,8 @@ static void do_test(void) static struct tst_test test = { .test_all = do_test, - .needs_cmds = (const char *[]) { - "mkfs.ext45 >= 1.43.0", - NULL + .needs_cmds = (struct tst_cmd[]) { + {.cmd = "mkfs.ext45 >= 1.43.0"}, + {} } }; diff --git a/lib/newlib_tests/tst_needs_cmds03.c b/lib/newlib_tests/tst_needs_cmds03.c index bdc1cdf6a..ac5f368e2 100644 --- a/lib/newlib_tests/tst_needs_cmds03.c +++ b/lib/newlib_tests/tst_needs_cmds03.c @@ -16,8 +16,8 @@ static void do_test(void) static struct tst_test test = { .test_all = do_test, - .needs_cmds = (const char *[]) { - "mkfs.ext4 ! 1.43.0", - NULL + .needs_cmds = (struct tst_cmd[]) { + {.cmd = "mkfs.ext4 ! 1.43.0"}, + {} } }; diff --git a/lib/newlib_tests/tst_needs_cmds04.c b/lib/newlib_tests/tst_needs_cmds04.c index de10b8f3e..2aea51772 100644 --- a/lib/newlib_tests/tst_needs_cmds04.c +++ b/lib/newlib_tests/tst_needs_cmds04.c @@ -16,8 +16,8 @@ static void do_test(void) static struct tst_test test = { .test_all = do_test, - .needs_cmds = (const char *[]) { - "mkfs.ext4 > 1.43", - NULL + .needs_cmds = (struct tst_cmd[]) { + {.cmd = "mkfs.ext4 > 1.43"}, + {} } }; diff --git a/lib/newlib_tests/tst_needs_cmds05.c b/lib/newlib_tests/tst_needs_cmds05.c index c3b2b3b9a..969d4e2f5 100644 --- a/lib/newlib_tests/tst_needs_cmds05.c +++ b/lib/newlib_tests/tst_needs_cmds05.c @@ -16,8 +16,8 @@ static void do_test(void) static struct tst_test test = { .test_all = do_test, - .needs_cmds = (const char *[]) { - "mkfs.ext4 > 1.43.0-1", - NULL + .needs_cmds = (struct tst_cmd[]) { + {.cmd = "mkfs.ext4 > 1.43.0-1"}, + {} } }; diff --git a/lib/newlib_tests/tst_needs_cmds06.c b/lib/newlib_tests/tst_needs_cmds06.c index 40b1cf09c..91470ccf9 100644 --- a/lib/newlib_tests/tst_needs_cmds06.c +++ b/lib/newlib_tests/tst_needs_cmds06.c @@ -16,8 +16,8 @@ static void do_test(void) static struct tst_test test = { .test_all = do_test, - .needs_cmds = (const char *[]) { - "mkfs.ext4 > 1.43.0 2", - NULL + .needs_cmds = (struct tst_cmd[]) { + {.cmd = "mkfs.ext4 > 1.43.0 2"}, + {} } }; diff --git a/lib/newlib_tests/tst_needs_cmds07.c b/lib/newlib_tests/tst_needs_cmds07.c index d0b4ce2ff..371bbdc1b 100644 --- a/lib/newlib_tests/tst_needs_cmds07.c +++ b/lib/newlib_tests/tst_needs_cmds07.c @@ -16,8 +16,8 @@ static void do_test(void) static struct tst_test test = { .test_all = do_test, - .needs_cmds = (const char *[]) { - "mkfs.ext45", - NULL + .needs_cmds = (struct tst_cmd[]) { + {.cmd = "mkfs.ext45"}, + {} } }; diff --git a/lib/newlib_tests/tst_needs_cmds08.c b/lib/newlib_tests/tst_needs_cmds08.c index 38df2ef6d..412f9f293 100644 --- a/lib/newlib_tests/tst_needs_cmds08.c +++ b/lib/newlib_tests/tst_needs_cmds08.c @@ -18,9 +18,9 @@ static void do_test(void) static struct tst_test test = { .test_all = do_test, - .needs_cmds = (const char *[]) { - "mkfs.xfs", - "mkfs.xfs >= 4.20.0", - NULL + .needs_cmds = (struct tst_cmd[]) { + {.cmd = "mkfs.xfs"}, + {.cmd = "mkfs.xfs >= 4.20.0"}, + {} } }; diff --git a/testcases/kernel/device-drivers/zram/zram03.c b/testcases/kernel/device-drivers/zram/zram03.c index 8cf26de4c..4dcf23b4e 100644 --- a/testcases/kernel/device-drivers/zram/zram03.c +++ b/testcases/kernel/device-drivers/zram/zram03.c @@ -240,9 +240,9 @@ static struct tst_test test = { "zram", NULL }, - .needs_cmds = (const char *[]) { - "modprobe", - "rmmod", - NULL + .needs_cmds = (struct tst_cmd[]) { + {.cmd = "modprobe"}, + {.cmd = "rmmod"}, + {} } }; diff --git a/testcases/kernel/fs/squashfs/squashfs01.c b/testcases/kernel/fs/squashfs/squashfs01.c index fbcb76582..7a548d62c 100644 --- a/testcases/kernel/fs/squashfs/squashfs01.c +++ b/testcases/kernel/fs/squashfs/squashfs01.c @@ -102,9 +102,9 @@ static struct tst_test test = { .needs_root = 1, .needs_device = 1, .dev_min_size = 1, - .needs_cmds = (const char *const []) { - "mksquashfs", - NULL + .needs_cmds = (struct tst_cmd[]) { + {.cmd = "mksquashfs"}, + {} }, .needs_drivers = (const char *const []) { "squashfs", diff --git a/testcases/kernel/security/aslr/aslr01.c b/testcases/kernel/security/aslr/aslr01.c index 6a396e29d..e6feb2d3c 100644 --- a/testcases/kernel/security/aslr/aslr01.c +++ b/testcases/kernel/security/aslr/aslr01.c @@ -277,8 +277,8 @@ static struct tst_test test = { "CONFIG_HAVE_ARCH_MMAP_RND_BITS=y", NULL }, - .needs_cmds = (const char *[]) { - "ldd", - NULL + .needs_cmds = (struct tst_cmd[]) { + {.cmd = "ldd"}, + {} }, }; diff --git a/testcases/kernel/syscalls/add_key/add_key05.c b/testcases/kernel/syscalls/add_key/add_key05.c index c9a2f840e..b51a84b97 100644 --- a/testcases/kernel/syscalls/add_key/add_key05.c +++ b/testcases/kernel/syscalls/add_key/add_key05.c @@ -231,11 +231,11 @@ static struct tst_test test = { {&user_buf, .size = 64}, {} }, - .needs_cmds = (const char *const []) { - "useradd", - "userdel", - "groupdel", - NULL + .needs_cmds = (struct tst_cmd[]) { + {.cmd = "useradd"}, + {.cmd = "userdel"}, + {.cmd = "groupdel"}, + {} }, .tags = (const struct tst_tag[]) { {"linux-git", "a08bf91ce28"}, diff --git a/testcases/kernel/syscalls/fanotify/fanotify22.c b/testcases/kernel/syscalls/fanotify/fanotify22.c index 357e74dbc..6578474a7 100644 --- a/testcases/kernel/syscalls/fanotify/fanotify22.c +++ b/testcases/kernel/syscalls/fanotify/fanotify22.c @@ -327,9 +327,9 @@ static struct tst_test test = { {"linux-git", "76486b104168"}, {} }, - .needs_cmds = (const char *[]) { - "debugfs", - NULL + .needs_cmds = (struct tst_cmd[]) { + {.cmd = "debugfs"}, + {} } }; diff --git a/testcases/kernel/syscalls/ioctl/ioctl09.c b/testcases/kernel/syscalls/ioctl/ioctl09.c index f86355f2c..1bd60fc84 100644 --- a/testcases/kernel/syscalls/ioctl/ioctl09.c +++ b/testcases/kernel/syscalls/ioctl/ioctl09.c @@ -108,9 +108,9 @@ static struct tst_test test = { "loop", NULL }, - .needs_cmds = (const char *const []) { - "parted", - NULL + .needs_cmds = (struct tst_cmd[]) { + {.cmd = "parted"}, + {} }, .needs_tmpdir = 1, }; diff --git a/testcases/kernel/syscalls/madvise/madvise11.c b/testcases/kernel/syscalls/madvise/madvise11.c index 422589f5b..73d2d4294 100644 --- a/testcases/kernel/syscalls/madvise/madvise11.c +++ b/testcases/kernel/syscalls/madvise/madvise11.c @@ -421,10 +421,10 @@ static struct tst_test test = { HW_MODULE, NULL }, - .needs_cmds = (const char *[]) { - "modprobe", - "rmmod", - NULL + .needs_cmds = (struct tst_cmd[]) { + {.cmd = "modprobe"}, + {.cmd = "rmmod"}, + {} }, .needs_kconfigs = (const char *[]) { "CONFIG_MEMORY_FAILURE=y", diff --git a/testcases/kernel/syscalls/quotactl/quotactl01.c b/testcases/kernel/syscalls/quotactl/quotactl01.c index 9dcf74ceb..3091ac5bf 100644 --- a/testcases/kernel/syscalls/quotactl/quotactl01.c +++ b/testcases/kernel/syscalls/quotactl/quotactl01.c @@ -223,9 +223,9 @@ static struct tst_test test = { {} }, .mntpoint = MNTPOINT, - .needs_cmds = (const char *const []) { - "quotacheck", - NULL + .needs_cmds = (struct tst_cmd[]) { + {.cmd = "quotacheck"}, + {} }, .setup = setup, .cleanup = cleanup, diff --git a/testcases/kernel/syscalls/quotactl/quotactl04.c b/testcases/kernel/syscalls/quotactl/quotactl04.c index d2d7b3f3e..a70903330 100644 --- a/testcases/kernel/syscalls/quotactl/quotactl04.c +++ b/testcases/kernel/syscalls/quotactl/quotactl04.c @@ -165,8 +165,8 @@ static struct tst_test test = { }, .mntpoint = MNTPOINT, .test_variants = QUOTACTL_SYSCALL_VARIANTS, - .needs_cmds = (const char *[]) { - "mkfs.ext4 >= 1.43.0", - NULL + .needs_cmds = (struct tst_cmd[]) { + {.cmd = "mkfs.ext4 >= 1.43.0"}, + {} } }; diff --git a/testcases/kernel/syscalls/quotactl/quotactl06.c b/testcases/kernel/syscalls/quotactl/quotactl06.c index 110a3aa9b..333f5720d 100644 --- a/testcases/kernel/syscalls/quotactl/quotactl06.c +++ b/testcases/kernel/syscalls/quotactl/quotactl06.c @@ -226,9 +226,9 @@ static struct tst_test test = { }, .mntpoint = MNTPOINT, .mount_device = 1, - .needs_cmds = (const char *const []) { - "quotacheck", - NULL + .needs_cmds = (struct tst_cmd[]) { + {.cmd = "quotacheck"}, + {} }, .needs_root = 1, .test_variants = QUOTACTL_FMT_VARIANTS, diff --git a/testcases/kernel/syscalls/quotactl/quotactl08.c b/testcases/kernel/syscalls/quotactl/quotactl08.c index 63087345f..ce7a8b008 100644 --- a/testcases/kernel/syscalls/quotactl/quotactl08.c +++ b/testcases/kernel/syscalls/quotactl/quotactl08.c @@ -220,8 +220,8 @@ static struct tst_test test = { .setup = setup, .cleanup = cleanup, .test_variants = QUOTACTL_SYSCALL_VARIANTS, - .needs_cmds = (const char *[]) { - "mkfs.ext4 >= 1.43.0", - NULL + .needs_cmds = (struct tst_cmd[]) { + {.cmd = "mkfs.ext4 >= 1.43.0"}, + {} } }; diff --git a/testcases/kernel/syscalls/quotactl/quotactl09.c b/testcases/kernel/syscalls/quotactl/quotactl09.c index 673666347..fd6629c0c 100644 --- a/testcases/kernel/syscalls/quotactl/quotactl09.c +++ b/testcases/kernel/syscalls/quotactl/quotactl09.c @@ -185,8 +185,8 @@ static struct tst_test test = { .mount_device = 1, .needs_root = 1, .test_variants = QUOTACTL_SYSCALL_VARIANTS, - .needs_cmds = (const char *[]) { - "mkfs.ext4 >= 1.43.0", - NULL + .needs_cmds = (struct tst_cmd[]) { + {.cmd = "mkfs.ext4 >= 1.43.0"}, + {} } }; diff --git a/testcases/kernel/syscalls/statx/statx05.c b/testcases/kernel/syscalls/statx/statx05.c index 2a4603226..07b5e7b94 100644 --- a/testcases/kernel/syscalls/statx/statx05.c +++ b/testcases/kernel/syscalls/statx/statx05.c @@ -123,9 +123,9 @@ static struct tst_test test = { {.type = "ext4"}, {} }, - .needs_cmds = (const char *[]) { - "mkfs.ext4 >= 1.43.0", - "e4crypt", - NULL + .needs_cmds = (struct tst_cmd[]) { + {.cmd = "mkfs.ext4 >= 1.43.0"}, + {.cmd = "e4crypt"}, + {} } }; diff --git a/testcases/kernel/syscalls/statx/statx07.c b/testcases/kernel/syscalls/statx/statx07.c index bab64591f..755644cf9 100644 --- a/testcases/kernel/syscalls/statx/statx07.c +++ b/testcases/kernel/syscalls/statx/statx07.c @@ -171,8 +171,8 @@ static struct tst_test test = { {} }, .needs_root = 1, - .needs_cmds = (const char *[]) { - "exportfs", - NULL + .needs_cmds = (struct tst_cmd[]) { + {.cmd = "exportfs"}, + {} } }; diff --git a/testcases/kernel/syscalls/statx/statx09.c b/testcases/kernel/syscalls/statx/statx09.c index ee4be4250..8838d5450 100644 --- a/testcases/kernel/syscalls/statx/statx09.c +++ b/testcases/kernel/syscalls/statx/statx09.c @@ -162,8 +162,8 @@ static struct tst_test test = { "CONFIG_FS_VERITY", NULL }, - .needs_cmds = (const char *[]) { - "mkfs.ext4 >= 1.45.2", - NULL + .needs_cmds = (struct tst_cmd[]) { + {.cmd = "mkfs.ext4 >= 1.45.2"}, + {} } }; -- 2.51.0 -- Mailing list info: https://lists.linux.it/listinfo/ltp ^ permalink raw reply related [flat|nested] 100+ messages in thread
* [LTP] [PATCH v3 4/4] tst_run_shell.c: Add new function handle new needs_cmds 2025-10-10 6:45 ` [LTP] [PATCH v3 0/4] new cmd support option for needs_cmds Wei Gao via ltp ` (2 preceding siblings ...) 2025-10-10 6:45 ` [LTP] [PATCH v3 3/4] Update test cases use new needs_cmds Wei Gao via ltp @ 2025-10-10 6:45 ` Wei Gao via ltp 2025-10-17 10:09 ` [LTP] [PATCH v4 0/3] new cmd support option for needs_cmds Wei Gao via ltp 2025-11-07 0:30 ` [LTP] [PATCH v4 0/4] new cmd support option for needs_cmds Wei Gao via ltp 5 siblings, 0 replies; 100+ messages in thread From: Wei Gao via ltp @ 2025-10-10 6:45 UTC (permalink / raw) To: ltp Signed-off-by: Wei Gao <wegao@suse.com> --- testcases/lib/tst_run_shell.c | 61 ++++++++++++++++++++++++++++++++++- 1 file changed, 60 insertions(+), 1 deletion(-) diff --git a/testcases/lib/tst_run_shell.c b/testcases/lib/tst_run_shell.c index 7a446e004..a6e0d1d29 100644 --- a/testcases/lib/tst_run_shell.c +++ b/testcases/lib/tst_run_shell.c @@ -175,6 +175,23 @@ static ujson_obj fs_obj = { .attr_cnt = UJSON_ARRAY_SIZE(fs_attrs), }; +enum cmd_ids { + CMD, + OPTIONAL, + PRESENT, +}; + +static ujson_obj_attr cmd_attrs[] = { + UJSON_OBJ_ATTR_IDX(CMD, "cmd", UJSON_STR), + UJSON_OBJ_ATTR_IDX(OPTIONAL, "optional", UJSON_INT), + UJSON_OBJ_ATTR_IDX(PRESENT, "present", UJSON_INT), +}; + +static ujson_obj cmd_obj = { + .attrs = cmd_attrs, + .attr_cnt = UJSON_ARRAY_SIZE(cmd_attrs), +}; + static int parse_mnt_flags(ujson_reader *reader, ujson_val *val) { int ret = 0; @@ -252,6 +269,48 @@ static struct tst_fs *parse_filesystems(ujson_reader *reader, ujson_val *val) return ret; } +static struct tst_cmd *parse_cmds(ujson_reader *reader, ujson_val *val) +{ + unsigned int i = 0, cnt = 0; + struct tst_cmd *ret; + + ujson_reader_state state = ujson_reader_state_save(reader); + + UJSON_ARR_FOREACH(reader, val) { + if (val->type != UJSON_ARR) { + ujson_err(reader, "Expected array!"); + return NULL; + } + ujson_arr_skip(reader); + cnt++; + } + + ujson_reader_state_load(reader, state); + + ret = SAFE_MALLOC(sizeof(struct tst_cmd) * (cnt + 1)); + memset(&ret[cnt], 0, sizeof(ret[cnt])); + + UJSON_ARR_FOREACH(reader, val) { + UJSON_OBJ_FOREACH_FILTER(reader, val, &cmd_obj, ujson_empty_obj) { + switch ((enum cmd_ids)val->idx) { + case CMD: + ret[i].cmd = strdup(val->val_str); + break; + case OPTIONAL: + ret[i].optional = val->val_int; + break; + case MKFS_VER: + ret[i].present = val->val_int; + break; + } + } + + i++; + } + + return ret; +} + static struct tst_tag *parse_tags(ujson_reader *reader, ujson_val *val) { unsigned int i = 0, cnt = 0; @@ -440,7 +499,7 @@ static void parse_metadata(void) ujson_err(&reader, "ABI bits must be 32 or 64"); break; case NEEDS_CMDS: - test.needs_cmds = parse_strarr(&reader, &val); + test.needs_cmds = parse_cmds(&reader, &val); break; case NEEDS_DEVFS: test.needs_devfs = val.val_bool; -- 2.51.0 -- Mailing list info: https://lists.linux.it/listinfo/ltp ^ permalink raw reply related [flat|nested] 100+ messages in thread
* [LTP] [PATCH v4 0/3] new cmd support option for needs_cmds 2025-10-10 6:45 ` [LTP] [PATCH v3 0/4] new cmd support option for needs_cmds Wei Gao via ltp ` (3 preceding siblings ...) 2025-10-10 6:45 ` [LTP] [PATCH v3 4/4] tst_run_shell.c: Add new function handle " Wei Gao via ltp @ 2025-10-17 10:09 ` Wei Gao via ltp 2025-10-17 10:09 ` [LTP] [PATCH v4 1/3] lib: Add support option for .needs_cmds Wei Gao via ltp ` (2 more replies) 2025-11-07 0:30 ` [LTP] [PATCH v4 0/4] new cmd support option for needs_cmds Wei Gao via ltp 5 siblings, 3 replies; 100+ messages in thread From: Wei Gao via ltp @ 2025-10-17 10:09 UTC (permalink / raw) To: ltp Wei Gao (3): lib: Add support option for .needs_cmds Update test cases use new needs_cmds tst_run_shell.c: Add new function handle new needs_cmds include/tst_cmd.h | 13 ++++ include/tst_test.h | 16 ++++- lib/newlib_tests/tst_needs_cmds01.c | 16 ++--- lib/newlib_tests/tst_needs_cmds02.c | 6 +- lib/newlib_tests/tst_needs_cmds03.c | 6 +- lib/newlib_tests/tst_needs_cmds04.c | 6 +- lib/newlib_tests/tst_needs_cmds05.c | 6 +- lib/newlib_tests/tst_needs_cmds06.c | 6 +- lib/newlib_tests/tst_needs_cmds07.c | 6 +- lib/newlib_tests/tst_needs_cmds08.c | 8 +-- lib/tst_cmd.c | 7 ++- lib/tst_test.c | 22 +++++-- testcases/kernel/device-drivers/zram/zram03.c | 8 +-- testcases/kernel/fs/squashfs/squashfs01.c | 6 +- testcases/kernel/security/aslr/aslr01.c | 6 +- testcases/kernel/syscalls/add_key/add_key05.c | 10 +-- .../kernel/syscalls/fanotify/fanotify22.c | 6 +- testcases/kernel/syscalls/ioctl/ioctl09.c | 6 +- .../kernel/syscalls/ioctl/ioctl_loop01.c | 28 ++++----- testcases/kernel/syscalls/madvise/madvise11.c | 8 +-- .../kernel/syscalls/quotactl/quotactl01.c | 6 +- .../kernel/syscalls/quotactl/quotactl04.c | 6 +- .../kernel/syscalls/quotactl/quotactl06.c | 6 +- .../kernel/syscalls/quotactl/quotactl08.c | 6 +- .../kernel/syscalls/quotactl/quotactl09.c | 6 +- testcases/kernel/syscalls/statx/statx05.c | 8 +-- testcases/kernel/syscalls/statx/statx07.c | 6 +- testcases/kernel/syscalls/statx/statx09.c | 6 +- testcases/lib/tst_run_shell.c | 61 ++++++++++++++++++- 29 files changed, 205 insertions(+), 102 deletions(-) -- 2.51.0 -- Mailing list info: https://lists.linux.it/listinfo/ltp ^ permalink raw reply [flat|nested] 100+ messages in thread
* [LTP] [PATCH v4 1/3] lib: Add support option for .needs_cmds 2025-10-17 10:09 ` [LTP] [PATCH v4 0/3] new cmd support option for needs_cmds Wei Gao via ltp @ 2025-10-17 10:09 ` Wei Gao via ltp 2025-10-17 14:35 ` Petr Vorel ` (2 more replies) 2025-10-17 10:09 ` [LTP] [PATCH v4 2/3] Update test cases use new needs_cmds Wei Gao via ltp 2025-10-17 10:09 ` [LTP] [PATCH v4 3/3] tst_run_shell.c: Add new function handle " Wei Gao via ltp 2 siblings, 3 replies; 100+ messages in thread From: Wei Gao via ltp @ 2025-10-17 10:09 UTC (permalink / raw) To: ltp Signed-off-by: Wei Gao <wegao@suse.com> Suggested-by: Cyril Hrubis <chrubis@suse.cz> --- include/tst_cmd.h | 13 +++++++++++++ include/tst_test.h | 16 ++++++++++++++-- lib/tst_cmd.c | 7 ++++++- lib/tst_test.c | 22 ++++++++++++++++++---- 4 files changed, 51 insertions(+), 7 deletions(-) diff --git a/include/tst_cmd.h b/include/tst_cmd.h index 939825646..3c3668eff 100644 --- a/include/tst_cmd.h +++ b/include/tst_cmd.h @@ -16,6 +16,19 @@ enum tst_cmd_flags { TST_CMD_TCONF_ON_MISSING = 2, }; +/** + * struct tst_cmd - Provides details about a command struct needed by LTP test. + * @cmd: The name of the command. + * @optional: A flag indicating if the command is optional. + * @present: A flag indicating if the command was found at runtime. This is an output + * parameter, set by the LTP library during the test setup. + */ +struct tst_cmd { + const char *cmd; + unsigned int optional:1; + unsigned int present:1; +}; + /* * vfork() + execvp() specified program. * diff --git a/include/tst_test.h b/include/tst_test.h index 9c21c1728..9305cf39d 100644 --- a/include/tst_test.h +++ b/include/tst_test.h @@ -524,7 +524,7 @@ struct tst_fs { * * @tags: A {} terminated array of test tags. See struct tst_tag for details. * - * @needs_cmds: A NULL terminated array of commands required for the test to run. + * @needs_cmds: A NULL terminated array of struct tst_cmd required for the test to run. * * @needs_cgroup_ver: If set the test will run only if the specified cgroup * version is present on the system. @@ -617,7 +617,7 @@ struct tst_fs { const struct tst_tag *tags; - const char *const *needs_cmds; + struct tst_cmd *needs_cmds; const enum tst_cg_ver needs_cgroup_ver; @@ -721,6 +721,18 @@ int tst_creat_unlinked(const char *path, int flags, mode_t mode); */ const char *tst_get_tmpdir_root(void); +/** + * tst_cmd_present() - Check if a command is present + * @cmd: The name of the command to check for. + * + * This function iterates through the &tst_test->needs_cmds array. It compares + * the given command name with each entry in the array and returns the 'present' + * flag for the matching command. + * + * Return: `true` if the command is present, `false` otherwise. + */ +bool tst_cmd_present(const char *cmd); + /* * Validates exit status of child processes */ diff --git a/lib/tst_cmd.c b/lib/tst_cmd.c index 82d60497a..cfd38c31a 100644 --- a/lib/tst_cmd.c +++ b/lib/tst_cmd.c @@ -265,7 +265,12 @@ int tst_check_cmd(const char *cmd, const int brk_nosupp) str = strtok_r(NULL, " ", &next); if (tst_get_path(cmd_token, path, sizeof(path))) - tst_brkm(TCONF, NULL, "Couldn't find '%s' in $PATH", cmd_token); + if (brk_nosupp) { + tst_brkm(TCONF, NULL, "Couldn't find '%s' in $PATH", cmd_token); + } else { + tst_resm(TCONF, "Couldn't find '%s' in $PATH", cmd_token); + return 1; + } if (!op_token) return 0; diff --git a/lib/tst_test.c b/lib/tst_test.c index 53b53af1a..6bd0ea44a 100644 --- a/lib/tst_test.c +++ b/lib/tst_test.c @@ -1365,6 +1365,19 @@ static const char *default_fs_type(void) return tst_dev_fs_type(); } +bool tst_cmd_present(const char *cmd) +{ + struct tst_cmd *pcmd = tst_test->needs_cmds; + + while (pcmd->cmd) { + if (!strcmp(pcmd->cmd, cmd)) + return pcmd->present; + + pcmd++; + } + return false; +} + static void do_setup(int argc, char *argv[]) { char *tdebug_env = getenv("LTP_ENABLE_DEBUG"); @@ -1439,11 +1452,12 @@ static void do_setup(int argc, char *argv[]) tst_brk(TCONF, "%dbit ABI is not supported", tst_test->needs_abi_bits); if (tst_test->needs_cmds) { - const char *cmd; - int i; + struct tst_cmd *pcmd = tst_test->needs_cmds; - for (i = 0; (cmd = tst_test->needs_cmds[i]); ++i) - tst_check_cmd(cmd, 1); + while (pcmd->cmd) { + pcmd->present = tst_check_cmd(pcmd->cmd, !pcmd->optional) ? 0 : 1; + pcmd++; + } } if (tst_test->needs_drivers) { -- 2.51.0 -- Mailing list info: https://lists.linux.it/listinfo/ltp ^ permalink raw reply related [flat|nested] 100+ messages in thread
* Re: [LTP] [PATCH v4 1/3] lib: Add support option for .needs_cmds 2025-10-17 10:09 ` [LTP] [PATCH v4 1/3] lib: Add support option for .needs_cmds Wei Gao via ltp @ 2025-10-17 14:35 ` Petr Vorel 2025-10-20 1:22 ` Wei Gao via ltp 2025-10-17 15:37 ` Petr Vorel 2025-10-20 13:33 ` Petr Vorel 2 siblings, 1 reply; 100+ messages in thread From: Petr Vorel @ 2025-10-17 14:35 UTC (permalink / raw) To: Wei Gao; +Cc: ltp Hi Wei, > +++ b/include/tst_test.h > @@ -524,7 +524,7 @@ struct tst_fs { > * > * @tags: A {} terminated array of test tags. See struct tst_tag for details. > * > - * @needs_cmds: A NULL terminated array of commands required for the test to run. > + * @needs_cmds: A NULL terminated array of struct tst_cmd required for the test to run. > * > * @needs_cgroup_ver: If set the test will run only if the specified cgroup > * version is present on the system. > @@ -617,7 +617,7 @@ struct tst_fs { > const struct tst_tag *tags; > - const char *const *needs_cmds; > + struct tst_cmd *needs_cmds; As I wrote in all previous versions, changing struct used in struct tst_test alone without changing will break this particular commit. See when I apply just this commit.: https://github.com/pevik/ltp/actions/runs/18595891586 https://github.com/pevik/ltp/commits/refs/heads/wei/needs_cmds.v4.first-commit-broken/ CC lib/newlib_tests/tst_expiration_timer tst_needs_cmds01.c:15:23: error: initialization of ‘struct tst_cmd *’ from incompatible pointer type ‘const char **’ [-Wincompatible-pointer-types] 15 | .needs_cmds = (const char *[]) { | ^ tst_needs_cmds01.c:15:23: note: (near initialization for ‘test.needs_cmds’) ... quotactl01.c:226:23: error: initialization of ‘struct tst_cmd *’ from incompatible pointer type ‘const char * const*’ [-Wincompatible-pointer-types] 226 | .needs_cmds = (const char *const []) { | ^ Please you need to have this commit together with "Update test cases use new needs_cmds" commit into single commit (squash these two into a single commit). Or am I missing something? Kind regards, Petr -- Mailing list info: https://lists.linux.it/listinfo/ltp ^ permalink raw reply [flat|nested] 100+ messages in thread
* Re: [LTP] [PATCH v4 1/3] lib: Add support option for .needs_cmds 2025-10-17 14:35 ` Petr Vorel @ 2025-10-20 1:22 ` Wei Gao via ltp 2025-10-20 13:21 ` Petr Vorel 0 siblings, 1 reply; 100+ messages in thread From: Wei Gao via ltp @ 2025-10-20 1:22 UTC (permalink / raw) To: Petr Vorel; +Cc: ltp On Fri, Oct 17, 2025 at 04:35:24PM +0200, Petr Vorel wrote: > Hi Wei, > > > +++ b/include/tst_test.h > > @@ -524,7 +524,7 @@ struct tst_fs { > > * > > * @tags: A {} terminated array of test tags. See struct tst_tag for details. > > * > > - * @needs_cmds: A NULL terminated array of commands required for the test to run. > > + * @needs_cmds: A NULL terminated array of struct tst_cmd required for the test to run. > > * > > * @needs_cgroup_ver: If set the test will run only if the specified cgroup > > * version is present on the system. > > @@ -617,7 +617,7 @@ struct tst_fs { > > > const struct tst_tag *tags; > > > - const char *const *needs_cmds; > > + struct tst_cmd *needs_cmds; > > As I wrote in all previous versions, changing struct used in struct tst_test > alone without changing will break this particular commit. > > See when I apply just this commit.: > https://github.com/pevik/ltp/actions/runs/18595891586 > https://github.com/pevik/ltp/commits/refs/heads/wei/needs_cmds.v4.first-commit-broken/ > > CC lib/newlib_tests/tst_expiration_timer > tst_needs_cmds01.c:15:23: error: initialization of ‘struct tst_cmd *’ from incompatible pointer type ‘const char **’ [-Wincompatible-pointer-types] > 15 | .needs_cmds = (const char *[]) { > | ^ > tst_needs_cmds01.c:15:23: note: (near initialization for ‘test.needs_cmds’) > > ... > > quotactl01.c:226:23: error: initialization of ‘struct tst_cmd *’ from incompatible pointer type ‘const char * const*’ [-Wincompatible-pointer-types] > 226 | .needs_cmds = (const char *const []) { > | ^ > > Please you need to have this commit together with "Update test cases use new > needs_cmds" commit into single commit (squash these two into a single commit). > > Or am I missing something? Thanks for your time do verify test can review. The reason i split this patch to small commits is easy for review, if you need every commits can pass compile phase then i have to combine all commits into a single big one, is that your request? > > Kind regards, > Petr -- Mailing list info: https://lists.linux.it/listinfo/ltp ^ permalink raw reply [flat|nested] 100+ messages in thread
* Re: [LTP] [PATCH v4 1/3] lib: Add support option for .needs_cmds 2025-10-20 1:22 ` Wei Gao via ltp @ 2025-10-20 13:21 ` Petr Vorel 2025-10-21 3:42 ` Wei Gao via ltp 2025-10-22 9:23 ` Li Wang via ltp 0 siblings, 2 replies; 100+ messages in thread From: Petr Vorel @ 2025-10-20 13:21 UTC (permalink / raw) To: Wei Gao; +Cc: ltp Hi Wei, > > > - const char *const *needs_cmds; > > > + struct tst_cmd *needs_cmds; > > As I wrote in all previous versions, changing struct used in struct tst_test > > alone without changing will break this particular commit. > > See when I apply just this commit.: > > https://github.com/pevik/ltp/actions/runs/18595891586 > > https://github.com/pevik/ltp/commits/refs/heads/wei/needs_cmds.v4.first-commit-broken/ > > CC lib/newlib_tests/tst_expiration_timer > > tst_needs_cmds01.c:15:23: error: initialization of ‘struct tst_cmd *’ from incompatible pointer type ‘const char **’ [-Wincompatible-pointer-types] > > 15 | .needs_cmds = (const char *[]) { > > | ^ > > tst_needs_cmds01.c:15:23: note: (near initialization for ‘test.needs_cmds’) > > ... > > quotactl01.c:226:23: error: initialization of ‘struct tst_cmd *’ from incompatible pointer type ‘const char * const*’ [-Wincompatible-pointer-types] > > 226 | .needs_cmds = (const char *const []) { > > | ^ > > Please you need to have this commit together with "Update test cases use new > > needs_cmds" commit into single commit (squash these two into a single commit). > > Or am I missing something? > Thanks for your time do verify test can review. yw :). > The reason i split this patch to small commits is easy for review, if you Yes, it's desired that changes are split into smaller logical parts if *possible*. Yes, this really helps readability. But if possible means at lest 1) not breaking compilation (the worst case) 2) not breaking test functionality. Therefore it's much easier to split into more commits some new library functionality (i.e. add some library functionality and enable it in separate commits, enable tests in a separate commit) But modifying the functionality like this (when it breaks compilation) is worse than a bit more complex commit. This is the rule in many open source projects. > need every commits can pass compile phase then i have to combine all > commits into a single big one, is that your request? No, that's other extreme :). There is something in between, right? You did not get me correct, therefore in v4 you not only kept broken functionality, but you also joined the part which could be separated. At least "ioctl_loop01.c: Update to new .needs_cmds struct" from v3 could have been added as a separate commit (after the main change, not before). Or am I missing something? Unfortunately "lib: Add support option for .needs_cmds" and "Update test cases use new needs_cmds" and "tst_run_shell.c: Add new function handle new needs_cmds" needs to be in a single commit, but maybe you could add functions which implement it in a separate commits (e.g. preparation for a new change) and do the change (when it's actually used) in the last commit). I'm not sure if it's worth of a separation, maybe not (hopefully we get a feedback from others). If yes: 1) commit (lib preparation) would have: struct tst_cmd, bool tst_cmd_present(const char *cmd) 2) commit (shell loader preparation) would have: enum cmd_ids, static ujson_obj_attr cmd_attrs[], static ujson_obj cmd_obj, static struct tst_cmd *parse_cmds(ujson_reader *reader, ujson_val *val). 3) commit (use new functionality) would have: from "lib: Add support option for .needs_cmds": - const char *const *needs_cmds; + struct tst_cmd *needs_cmds; and use of tst_check_cmd() from "tst_run_shell.c: Add new function handle new needs_cmds" - test.needs_cmds = parse_strarr(&reader, &val); + test.needs_cmds = parse_cmds(&reader, &val); all code changes in "Update test cases use new needs_cmds" 4) "ioctl_loop01.c: Update to new .needs_cmds struct" from v3 can be separate, it just have to be after library function changed. 5) commit: modify some test to actually use some of new functionality. If we are ok to do too many separate commits, then: 1) commit: everything from this v4 in a single commit, but separate at least "ioctl_loop01.c: Update to new .needs_cmds struct" from v3. 2) "ioctl_loop01.c: Update to new .needs_cmds struct" from v3. 3) commit: modify some test to actually use some of new functionality. Kind regards, Petr > > Kind regards, > > Petr -- Mailing list info: https://lists.linux.it/listinfo/ltp ^ permalink raw reply [flat|nested] 100+ messages in thread
* Re: [LTP] [PATCH v4 1/3] lib: Add support option for .needs_cmds 2025-10-20 13:21 ` Petr Vorel @ 2025-10-21 3:42 ` Wei Gao via ltp 2025-10-22 9:23 ` Li Wang via ltp 1 sibling, 0 replies; 100+ messages in thread From: Wei Gao via ltp @ 2025-10-21 3:42 UTC (permalink / raw) To: Petr Vorel; +Cc: ltp On Mon, Oct 20, 2025 at 03:21:40PM +0200, Petr Vorel wrote: > Hi Wei, > > > > > - const char *const *needs_cmds; > > > > + struct tst_cmd *needs_cmds; > > > > As I wrote in all previous versions, changing struct used in struct tst_test > > > alone without changing will break this particular commit. > > > > See when I apply just this commit.: > > > https://github.com/pevik/ltp/actions/runs/18595891586 > > > https://github.com/pevik/ltp/commits/refs/heads/wei/needs_cmds.v4.first-commit-broken/ > > > > CC lib/newlib_tests/tst_expiration_timer > > > tst_needs_cmds01.c:15:23: error: initialization of ‘struct tst_cmd *’ from incompatible pointer type ‘const char **’ [-Wincompatible-pointer-types] > > > 15 | .needs_cmds = (const char *[]) { > > > | ^ > > > tst_needs_cmds01.c:15:23: note: (near initialization for ‘test.needs_cmds’) > > > > ... > > > > quotactl01.c:226:23: error: initialization of ‘struct tst_cmd *’ from incompatible pointer type ‘const char * const*’ [-Wincompatible-pointer-types] > > > 226 | .needs_cmds = (const char *const []) { > > > | ^ > > > > Please you need to have this commit together with "Update test cases use new > > > needs_cmds" commit into single commit (squash these two into a single commit). > > > > Or am I missing something? > > Thanks for your time do verify test can review. > yw :). > > > The reason i split this patch to small commits is easy for review, if you > > Yes, it's desired that changes are split into smaller logical parts if *possible*. > Yes, this really helps readability. But if possible means at lest 1) not > breaking compilation (the worst case) 2) not breaking test functionality. > > Therefore it's much easier to split into more commits some new library > functionality (i.e. add some library functionality and enable it in separate > commits, enable tests in a separate commit) > > But modifying the functionality like this (when it breaks compilation) is worse > than a bit more complex commit. This is the rule in many open source projects. > > > need every commits can pass compile phase then i have to combine all > > commits into a single big one, is that your request? > > No, that's other extreme :). There is something in between, right? > You did not get me correct, therefore in v4 you not only kept broken > functionality, but you also joined the part which could be separated. At least > "ioctl_loop01.c: Update to new .needs_cmds struct" from v3 could have been added > as a separate commit (after the main change, not before). Or am I missing > something? > > Unfortunately "lib: Add support option for .needs_cmds" and "Update test cases use > new needs_cmds" and "tst_run_shell.c: Add new function handle new > needs_cmds" needs to be in a single commit, but maybe you could add functions > which implement it in a separate commits (e.g. preparation for a new change) and > do the change (when it's actually used) in the last commit). I'm not sure if > it's worth of a separation, maybe not (hopefully we get a feedback from others). > If yes: > > 1) commit (lib preparation) would have: struct tst_cmd, bool > tst_cmd_present(const char *cmd) > > 2) commit (shell loader preparation) would have: enum cmd_ids, static > ujson_obj_attr cmd_attrs[], static ujson_obj cmd_obj, static struct tst_cmd > *parse_cmds(ujson_reader *reader, ujson_val *val). > > 3) commit (use new functionality) would have: from "lib: Add support option for > .needs_cmds": > > - const char *const *needs_cmds; > + struct tst_cmd *needs_cmds; > > and use of tst_check_cmd() > > from "tst_run_shell.c: Add new function handle new needs_cmds" > - test.needs_cmds = parse_strarr(&reader, &val); > + test.needs_cmds = parse_cmds(&reader, &val); > > all code changes in "Update test cases use new needs_cmds" > > 4) "ioctl_loop01.c: Update to new .needs_cmds struct" from v3 can be separate, > it just have to be after library function changed. > > 5) commit: modify some test to actually use some of new functionality. > > If we are ok to do too many separate commits, then: > > 1) commit: everything from this v4 in a single commit, but separate at least > "ioctl_loop01.c: Update to new .needs_cmds struct" from v3. > > 2) "ioctl_loop01.c: Update to new .needs_cmds struct" from v3. > > 3) commit: modify some test to actually use some of new functionality. Thanks for such detail explaination :) Let's wait one more day for feedback from others, i prefer second solution squash core changes into one commit without break from function level. BTW: Absent timely feedback, I will automatically begin creating the next patch with the second solution. > > Kind regards, > Petr > > > > Kind regards, > > > Petr -- Mailing list info: https://lists.linux.it/listinfo/ltp ^ permalink raw reply [flat|nested] 100+ messages in thread
* Re: [LTP] [PATCH v4 1/3] lib: Add support option for .needs_cmds 2025-10-20 13:21 ` Petr Vorel 2025-10-21 3:42 ` Wei Gao via ltp @ 2025-10-22 9:23 ` Li Wang via ltp 2025-10-22 14:19 ` Wei Gao via ltp 1 sibling, 1 reply; 100+ messages in thread From: Li Wang via ltp @ 2025-10-22 9:23 UTC (permalink / raw) To: Wei Gao; +Cc: ltp Hi Wei, Petr Vorel <pvorel@suse.cz> wrote: > > > need every commits can pass compile phase then i have to combine all > > commits into a single big one, is that your request? > > No, that's other extreme :). There is something in between, right? > You did not get me correct, therefore in v4 you not only kept broken > functionality, but you also joined the part which could be separated. At > least > "ioctl_loop01.c: Update to new .needs_cmds struct" from v3 could have been > added > as a separate commit (after the main change, not before). Or am I missing > something? > > Unfortunately "lib: Add support option for .needs_cmds" and "Update test > cases use > new needs_cmds" and "tst_run_shell.c: Add new function handle new > needs_cmds" needs to be in a single commit, but maybe you could add > functions > which implement it in a separate commits (e.g. preparation for a new > change) and > do the change (when it's actually used) in the last commit). I'm not sure > if > it's worth of a separation, maybe not (hopefully we get a feedback from > others). > If yes: > Yes. > 1) commit (lib preparation) would have: struct tst_cmd, bool > tst_cmd_present(const char *cmd) > > 2) commit (shell loader preparation) would have: enum cmd_ids, static > ujson_obj_attr cmd_attrs[], static ujson_obj cmd_obj, static struct tst_cmd > *parse_cmds(ujson_reader *reader, ujson_val *val). > > 3) commit (use new functionality) would have: from "lib: Add support > option for > .needs_cmds": > > - const char *const *needs_cmds; > + struct tst_cmd *needs_cmds; > > and use of tst_check_cmd() > > from "tst_run_shell.c: Add new function handle new needs_cmds" > - test.needs_cmds = parse_strarr(&reader, &val); > + test.needs_cmds = parse_cmds(&reader, &val); > > all code changes in "Update test cases use new needs_cmds" > > 4) "ioctl_loop01.c: Update to new .needs_cmds struct" from v3 can be > separate, > it just have to be after library function changed. > > 5) commit: modify some test to actually use some of new functionality. > Obviously, this is a good suggestion. Wei, if you take a look at the git-history of LTP feature change, most patchset organizations follow this principle. We must keep a clean code and compile pass at the same time, I have roughly gone through your patches, and they are seems not so hard to rebase. > > If we are ok to do too many separate commits, then: > > 1) commit: everything from this v4 in a single commit, but separate at > least > "ioctl_loop01.c: Update to new .needs_cmds struct" from v3. > > 2) "ioctl_loop01.c: Update to new .needs_cmds struct" from v3. > > 3) commit: modify some test to actually use some of new functionality. > Yes, this is also acceptable to me. -- Regards, Li Wang -- Mailing list info: https://lists.linux.it/listinfo/ltp ^ permalink raw reply [flat|nested] 100+ messages in thread
* Re: [LTP] [PATCH v4 1/3] lib: Add support option for .needs_cmds 2025-10-22 9:23 ` Li Wang via ltp @ 2025-10-22 14:19 ` Wei Gao via ltp 0 siblings, 0 replies; 100+ messages in thread From: Wei Gao via ltp @ 2025-10-22 14:19 UTC (permalink / raw) To: Li Wang; +Cc: ltp On Wed, Oct 22, 2025 at 05:23:16PM +0800, Li Wang wrote: > Hi Wei, > > Petr Vorel <pvorel@suse.cz> wrote: > > > > > > > need every commits can pass compile phase then i have to combine all > > > commits into a single big one, is that your request? > > > > No, that's other extreme :). There is something in between, right? > > You did not get me correct, therefore in v4 you not only kept broken > > functionality, but you also joined the part which could be separated. At > > least > > "ioctl_loop01.c: Update to new .needs_cmds struct" from v3 could have been > > added > > as a separate commit (after the main change, not before). Or am I missing > > something? > > > > Unfortunately "lib: Add support option for .needs_cmds" and "Update test > > cases use > > new needs_cmds" and "tst_run_shell.c: Add new function handle new > > needs_cmds" needs to be in a single commit, but maybe you could add > > functions > > which implement it in a separate commits (e.g. preparation for a new > > change) and > > do the change (when it's actually used) in the last commit). I'm not sure > > if > > it's worth of a separation, maybe not (hopefully we get a feedback from > > others). > > If yes: > > > > Yes. > > > > 1) commit (lib preparation) would have: struct tst_cmd, bool > > tst_cmd_present(const char *cmd) > > > > 2) commit (shell loader preparation) would have: enum cmd_ids, static > > ujson_obj_attr cmd_attrs[], static ujson_obj cmd_obj, static struct tst_cmd > > *parse_cmds(ujson_reader *reader, ujson_val *val). > > > > 3) commit (use new functionality) would have: from "lib: Add support > > option for > > .needs_cmds": > > > > - const char *const *needs_cmds; > > + struct tst_cmd *needs_cmds; > > > > and use of tst_check_cmd() > > > > from "tst_run_shell.c: Add new function handle new needs_cmds" > > - test.needs_cmds = parse_strarr(&reader, &val); > > + test.needs_cmds = parse_cmds(&reader, &val); > > > > all code changes in "Update test cases use new needs_cmds" > > > > 4) "ioctl_loop01.c: Update to new .needs_cmds struct" from v3 can be > > separate, > > it just have to be after library function changed. > > > > 5) commit: modify some test to actually use some of new functionality. > > > > Obviously, this is a good suggestion. > > Wei, if you take a look at the git-history of LTP feature change, > most patchset organizations follow this principle. > > We must keep a clean code and compile pass at the same time, > I have roughly gone through your patches, and they are seems > not so hard to rebase. > > > > > > > If we are ok to do too many separate commits, then: > > > > 1) commit: everything from this v4 in a single commit, but separate at > > least > > "ioctl_loop01.c: Update to new .needs_cmds struct" from v3. > > > > 2) "ioctl_loop01.c: Update to new .needs_cmds struct" from v3. > > > > 3) commit: modify some test to actually use some of new functionality. > > > > Yes, this is also acceptable to me. Li, Thanks for your feedback, will plan next patch. > > -- > Regards, > Li Wang -- Mailing list info: https://lists.linux.it/listinfo/ltp ^ permalink raw reply [flat|nested] 100+ messages in thread
* Re: [LTP] [PATCH v4 1/3] lib: Add support option for .needs_cmds 2025-10-17 10:09 ` [LTP] [PATCH v4 1/3] lib: Add support option for .needs_cmds Wei Gao via ltp 2025-10-17 14:35 ` Petr Vorel @ 2025-10-17 15:37 ` Petr Vorel 2025-10-20 1:24 ` Wei Gao via ltp 2025-10-20 13:33 ` Petr Vorel 2 siblings, 1 reply; 100+ messages in thread From: Petr Vorel @ 2025-10-17 15:37 UTC (permalink / raw) To: Wei Gao; +Cc: ltp Wei, .. > +/** > + * struct tst_cmd - Provides details about a command struct needed by LTP test. > + * @cmd: The name of the command. > + * @optional: A flag indicating if the command is optional. > + * @present: A flag indicating if the command was found at runtime. This is an output > + * parameter, set by the LTP library during the test setup. > + */ > +struct tst_cmd { > + const char *cmd; > + unsigned int optional:1; Any change you would modify one of lib/newlib_tests/tst_needs_cmds*.c to use tst_cmd->optional? Kind regards, Petr -- Mailing list info: https://lists.linux.it/listinfo/ltp ^ permalink raw reply [flat|nested] 100+ messages in thread
* Re: [LTP] [PATCH v4 1/3] lib: Add support option for .needs_cmds 2025-10-17 15:37 ` Petr Vorel @ 2025-10-20 1:24 ` Wei Gao via ltp 0 siblings, 0 replies; 100+ messages in thread From: Wei Gao via ltp @ 2025-10-20 1:24 UTC (permalink / raw) To: Petr Vorel; +Cc: ltp On Fri, Oct 17, 2025 at 05:37:46PM +0200, Petr Vorel wrote: > Wei, > > .. > > +/** > > + * struct tst_cmd - Provides details about a command struct needed by LTP test. > > + * @cmd: The name of the command. > > + * @optional: A flag indicating if the command is optional. > > + * @present: A flag indicating if the command was found at runtime. This is an output > > + * parameter, set by the LTP library during the test setup. > > + */ > > +struct tst_cmd { > > + const char *cmd; > > + unsigned int optional:1; > Any change you would modify one of lib/newlib_tests/tst_needs_cmds*.c > to use tst_cmd->optional? Good idea, will add test for this new parameter. > > Kind regards, > Petr -- Mailing list info: https://lists.linux.it/listinfo/ltp ^ permalink raw reply [flat|nested] 100+ messages in thread
* Re: [LTP] [PATCH v4 1/3] lib: Add support option for .needs_cmds 2025-10-17 10:09 ` [LTP] [PATCH v4 1/3] lib: Add support option for .needs_cmds Wei Gao via ltp 2025-10-17 14:35 ` Petr Vorel 2025-10-17 15:37 ` Petr Vorel @ 2025-10-20 13:33 ` Petr Vorel 2025-10-21 3:17 ` Wei Gao via ltp 2 siblings, 1 reply; 100+ messages in thread From: Petr Vorel @ 2025-10-20 13:33 UTC (permalink / raw) To: Wei Gao; +Cc: ltp Hi Wei, ... > +++ b/lib/tst_cmd.c > @@ -265,7 +265,12 @@ int tst_check_cmd(const char *cmd, const int brk_nosupp) > str = strtok_r(NULL, " ", &next); > if (tst_get_path(cmd_token, path, sizeof(path))) > - tst_brkm(TCONF, NULL, "Couldn't find '%s' in $PATH", cmd_token); > + if (brk_nosupp) { > + tst_brkm(TCONF, NULL, "Couldn't find '%s' in $PATH", cmd_token); > + } else { > + tst_resm(TCONF, "Couldn't find '%s' in $PATH", cmd_token); > + return 1; > + } You ask me how you could split changes to be compilable and yet not in a single commit. This is a completely unrelated change, it should be in a separate commit, with: Fixes: 257394e4e3 ("Filter mkfs version in tst_fs") Kind regards, Petr > if (!op_token) > return 0; -- Mailing list info: https://lists.linux.it/listinfo/ltp ^ permalink raw reply [flat|nested] 100+ messages in thread
* Re: [LTP] [PATCH v4 1/3] lib: Add support option for .needs_cmds 2025-10-20 13:33 ` Petr Vorel @ 2025-10-21 3:17 ` Wei Gao via ltp 0 siblings, 0 replies; 100+ messages in thread From: Wei Gao via ltp @ 2025-10-21 3:17 UTC (permalink / raw) To: Petr Vorel; +Cc: ltp On Mon, Oct 20, 2025 at 03:33:29PM +0200, Petr Vorel wrote: > Hi Wei, > > ... > > +++ b/lib/tst_cmd.c > > @@ -265,7 +265,12 @@ int tst_check_cmd(const char *cmd, const int brk_nosupp) > > str = strtok_r(NULL, " ", &next); > > > if (tst_get_path(cmd_token, path, sizeof(path))) > > - tst_brkm(TCONF, NULL, "Couldn't find '%s' in $PATH", cmd_token); > > + if (brk_nosupp) { > > + tst_brkm(TCONF, NULL, "Couldn't find '%s' in $PATH", cmd_token); > > + } else { > > + tst_resm(TCONF, "Couldn't find '%s' in $PATH", cmd_token); > > + return 1; > > + } > > You ask me how you could split changes to be compilable and yet not in a single > commit. This is a completely unrelated change, it should be in a separate > commit, with: > > Fixes: 257394e4e3 ("Filter mkfs version in tst_fs") Thanks, will use separte commit next patch. > > Kind regards, > Petr > > > if (!op_token) > > return 0; -- Mailing list info: https://lists.linux.it/listinfo/ltp ^ permalink raw reply [flat|nested] 100+ messages in thread
* [LTP] [PATCH v4 2/3] Update test cases use new needs_cmds 2025-10-17 10:09 ` [LTP] [PATCH v4 0/3] new cmd support option for needs_cmds Wei Gao via ltp 2025-10-17 10:09 ` [LTP] [PATCH v4 1/3] lib: Add support option for .needs_cmds Wei Gao via ltp @ 2025-10-17 10:09 ` Wei Gao via ltp 2025-10-17 10:09 ` [LTP] [PATCH v4 3/3] tst_run_shell.c: Add new function handle " Wei Gao via ltp 2 siblings, 0 replies; 100+ messages in thread From: Wei Gao via ltp @ 2025-10-17 10:09 UTC (permalink / raw) To: ltp Suggested-by: Cyril Hrubis <chrubis@suse.cz> Signed-off-by: Wei Gao <wegao@suse.com> --- lib/newlib_tests/tst_needs_cmds01.c | 16 +++++------ lib/newlib_tests/tst_needs_cmds02.c | 6 ++-- lib/newlib_tests/tst_needs_cmds03.c | 6 ++-- lib/newlib_tests/tst_needs_cmds04.c | 6 ++-- lib/newlib_tests/tst_needs_cmds05.c | 6 ++-- lib/newlib_tests/tst_needs_cmds06.c | 6 ++-- lib/newlib_tests/tst_needs_cmds07.c | 6 ++-- lib/newlib_tests/tst_needs_cmds08.c | 8 +++--- testcases/kernel/device-drivers/zram/zram03.c | 8 +++--- testcases/kernel/fs/squashfs/squashfs01.c | 6 ++-- testcases/kernel/security/aslr/aslr01.c | 6 ++-- testcases/kernel/syscalls/add_key/add_key05.c | 10 +++---- .../kernel/syscalls/fanotify/fanotify22.c | 6 ++-- testcases/kernel/syscalls/ioctl/ioctl09.c | 6 ++-- .../kernel/syscalls/ioctl/ioctl_loop01.c | 28 +++++++++---------- testcases/kernel/syscalls/madvise/madvise11.c | 8 +++--- .../kernel/syscalls/quotactl/quotactl01.c | 6 ++-- .../kernel/syscalls/quotactl/quotactl04.c | 6 ++-- .../kernel/syscalls/quotactl/quotactl06.c | 6 ++-- .../kernel/syscalls/quotactl/quotactl08.c | 6 ++-- .../kernel/syscalls/quotactl/quotactl09.c | 6 ++-- testcases/kernel/syscalls/statx/statx05.c | 8 +++--- testcases/kernel/syscalls/statx/statx07.c | 6 ++-- testcases/kernel/syscalls/statx/statx09.c | 6 ++-- 24 files changed, 94 insertions(+), 94 deletions(-) diff --git a/lib/newlib_tests/tst_needs_cmds01.c b/lib/newlib_tests/tst_needs_cmds01.c index 777c69505..592456da6 100644 --- a/lib/newlib_tests/tst_needs_cmds01.c +++ b/lib/newlib_tests/tst_needs_cmds01.c @@ -12,13 +12,13 @@ static void do_test(void) static struct tst_test test = { .test_all = do_test, - .needs_cmds = (const char *[]) { - "mkfs.ext4", - "mkfs.ext4 >= 1.0.0", - "mkfs.ext4 <= 2.0.0", - "mkfs.ext4 != 2.0.0", - "mkfs.ext4 > 1.0.0", - "mkfs.ext4 < 2.0.0", - NULL + .needs_cmds = (struct tst_cmd[]) { + {.cmd = "mkfs.ext4"}, + {.cmd = "mkfs.ext4 >= 1.0.0"}, + {.cmd = "mkfs.ext4 <= 2.0.0"}, + {.cmd = "mkfs.ext4 != 2.0.0"}, + {.cmd = "mkfs.ext4 > 1.0.0"}, + {.cmd = "mkfs.ext4 < 2.0.0"}, + {} } }; diff --git a/lib/newlib_tests/tst_needs_cmds02.c b/lib/newlib_tests/tst_needs_cmds02.c index 455a275ea..f1d6105c2 100644 --- a/lib/newlib_tests/tst_needs_cmds02.c +++ b/lib/newlib_tests/tst_needs_cmds02.c @@ -16,8 +16,8 @@ static void do_test(void) static struct tst_test test = { .test_all = do_test, - .needs_cmds = (const char *[]) { - "mkfs.ext45 >= 1.43.0", - NULL + .needs_cmds = (struct tst_cmd[]) { + {.cmd = "mkfs.ext45 >= 1.43.0"}, + {} } }; diff --git a/lib/newlib_tests/tst_needs_cmds03.c b/lib/newlib_tests/tst_needs_cmds03.c index bdc1cdf6a..ac5f368e2 100644 --- a/lib/newlib_tests/tst_needs_cmds03.c +++ b/lib/newlib_tests/tst_needs_cmds03.c @@ -16,8 +16,8 @@ static void do_test(void) static struct tst_test test = { .test_all = do_test, - .needs_cmds = (const char *[]) { - "mkfs.ext4 ! 1.43.0", - NULL + .needs_cmds = (struct tst_cmd[]) { + {.cmd = "mkfs.ext4 ! 1.43.0"}, + {} } }; diff --git a/lib/newlib_tests/tst_needs_cmds04.c b/lib/newlib_tests/tst_needs_cmds04.c index de10b8f3e..2aea51772 100644 --- a/lib/newlib_tests/tst_needs_cmds04.c +++ b/lib/newlib_tests/tst_needs_cmds04.c @@ -16,8 +16,8 @@ static void do_test(void) static struct tst_test test = { .test_all = do_test, - .needs_cmds = (const char *[]) { - "mkfs.ext4 > 1.43", - NULL + .needs_cmds = (struct tst_cmd[]) { + {.cmd = "mkfs.ext4 > 1.43"}, + {} } }; diff --git a/lib/newlib_tests/tst_needs_cmds05.c b/lib/newlib_tests/tst_needs_cmds05.c index c3b2b3b9a..969d4e2f5 100644 --- a/lib/newlib_tests/tst_needs_cmds05.c +++ b/lib/newlib_tests/tst_needs_cmds05.c @@ -16,8 +16,8 @@ static void do_test(void) static struct tst_test test = { .test_all = do_test, - .needs_cmds = (const char *[]) { - "mkfs.ext4 > 1.43.0-1", - NULL + .needs_cmds = (struct tst_cmd[]) { + {.cmd = "mkfs.ext4 > 1.43.0-1"}, + {} } }; diff --git a/lib/newlib_tests/tst_needs_cmds06.c b/lib/newlib_tests/tst_needs_cmds06.c index 40b1cf09c..91470ccf9 100644 --- a/lib/newlib_tests/tst_needs_cmds06.c +++ b/lib/newlib_tests/tst_needs_cmds06.c @@ -16,8 +16,8 @@ static void do_test(void) static struct tst_test test = { .test_all = do_test, - .needs_cmds = (const char *[]) { - "mkfs.ext4 > 1.43.0 2", - NULL + .needs_cmds = (struct tst_cmd[]) { + {.cmd = "mkfs.ext4 > 1.43.0 2"}, + {} } }; diff --git a/lib/newlib_tests/tst_needs_cmds07.c b/lib/newlib_tests/tst_needs_cmds07.c index d0b4ce2ff..371bbdc1b 100644 --- a/lib/newlib_tests/tst_needs_cmds07.c +++ b/lib/newlib_tests/tst_needs_cmds07.c @@ -16,8 +16,8 @@ static void do_test(void) static struct tst_test test = { .test_all = do_test, - .needs_cmds = (const char *[]) { - "mkfs.ext45", - NULL + .needs_cmds = (struct tst_cmd[]) { + {.cmd = "mkfs.ext45"}, + {} } }; diff --git a/lib/newlib_tests/tst_needs_cmds08.c b/lib/newlib_tests/tst_needs_cmds08.c index 38df2ef6d..412f9f293 100644 --- a/lib/newlib_tests/tst_needs_cmds08.c +++ b/lib/newlib_tests/tst_needs_cmds08.c @@ -18,9 +18,9 @@ static void do_test(void) static struct tst_test test = { .test_all = do_test, - .needs_cmds = (const char *[]) { - "mkfs.xfs", - "mkfs.xfs >= 4.20.0", - NULL + .needs_cmds = (struct tst_cmd[]) { + {.cmd = "mkfs.xfs"}, + {.cmd = "mkfs.xfs >= 4.20.0"}, + {} } }; diff --git a/testcases/kernel/device-drivers/zram/zram03.c b/testcases/kernel/device-drivers/zram/zram03.c index 8cf26de4c..4dcf23b4e 100644 --- a/testcases/kernel/device-drivers/zram/zram03.c +++ b/testcases/kernel/device-drivers/zram/zram03.c @@ -240,9 +240,9 @@ static struct tst_test test = { "zram", NULL }, - .needs_cmds = (const char *[]) { - "modprobe", - "rmmod", - NULL + .needs_cmds = (struct tst_cmd[]) { + {.cmd = "modprobe"}, + {.cmd = "rmmod"}, + {} } }; diff --git a/testcases/kernel/fs/squashfs/squashfs01.c b/testcases/kernel/fs/squashfs/squashfs01.c index fbcb76582..7a548d62c 100644 --- a/testcases/kernel/fs/squashfs/squashfs01.c +++ b/testcases/kernel/fs/squashfs/squashfs01.c @@ -102,9 +102,9 @@ static struct tst_test test = { .needs_root = 1, .needs_device = 1, .dev_min_size = 1, - .needs_cmds = (const char *const []) { - "mksquashfs", - NULL + .needs_cmds = (struct tst_cmd[]) { + {.cmd = "mksquashfs"}, + {} }, .needs_drivers = (const char *const []) { "squashfs", diff --git a/testcases/kernel/security/aslr/aslr01.c b/testcases/kernel/security/aslr/aslr01.c index 6a396e29d..e6feb2d3c 100644 --- a/testcases/kernel/security/aslr/aslr01.c +++ b/testcases/kernel/security/aslr/aslr01.c @@ -277,8 +277,8 @@ static struct tst_test test = { "CONFIG_HAVE_ARCH_MMAP_RND_BITS=y", NULL }, - .needs_cmds = (const char *[]) { - "ldd", - NULL + .needs_cmds = (struct tst_cmd[]) { + {.cmd = "ldd"}, + {} }, }; diff --git a/testcases/kernel/syscalls/add_key/add_key05.c b/testcases/kernel/syscalls/add_key/add_key05.c index c9a2f840e..b51a84b97 100644 --- a/testcases/kernel/syscalls/add_key/add_key05.c +++ b/testcases/kernel/syscalls/add_key/add_key05.c @@ -231,11 +231,11 @@ static struct tst_test test = { {&user_buf, .size = 64}, {} }, - .needs_cmds = (const char *const []) { - "useradd", - "userdel", - "groupdel", - NULL + .needs_cmds = (struct tst_cmd[]) { + {.cmd = "useradd"}, + {.cmd = "userdel"}, + {.cmd = "groupdel"}, + {} }, .tags = (const struct tst_tag[]) { {"linux-git", "a08bf91ce28"}, diff --git a/testcases/kernel/syscalls/fanotify/fanotify22.c b/testcases/kernel/syscalls/fanotify/fanotify22.c index 357e74dbc..6578474a7 100644 --- a/testcases/kernel/syscalls/fanotify/fanotify22.c +++ b/testcases/kernel/syscalls/fanotify/fanotify22.c @@ -327,9 +327,9 @@ static struct tst_test test = { {"linux-git", "76486b104168"}, {} }, - .needs_cmds = (const char *[]) { - "debugfs", - NULL + .needs_cmds = (struct tst_cmd[]) { + {.cmd = "debugfs"}, + {} } }; diff --git a/testcases/kernel/syscalls/ioctl/ioctl09.c b/testcases/kernel/syscalls/ioctl/ioctl09.c index f86355f2c..1bd60fc84 100644 --- a/testcases/kernel/syscalls/ioctl/ioctl09.c +++ b/testcases/kernel/syscalls/ioctl/ioctl09.c @@ -108,9 +108,9 @@ static struct tst_test test = { "loop", NULL }, - .needs_cmds = (const char *const []) { - "parted", - NULL + .needs_cmds = (struct tst_cmd[]) { + {.cmd = "parted"}, + {} }, .needs_tmpdir = 1, }; diff --git a/testcases/kernel/syscalls/ioctl/ioctl_loop01.c b/testcases/kernel/syscalls/ioctl/ioctl_loop01.c index cb1b506d2..fe62e7e5a 100644 --- a/testcases/kernel/syscalls/ioctl/ioctl_loop01.c +++ b/testcases/kernel/syscalls/ioctl/ioctl_loop01.c @@ -78,21 +78,7 @@ static void check_loop_value(int set_flag, int get_flag, int autoclear_field) static void verify_ioctl_loop(void) { - int ret; - const char *const cmd_parted[] = {"parted", "-s", dev_path, "mklabel", "msdos", "mkpart", - "primary", "ext4", "1M", "10M", NULL}; - - tst_fill_file("test.img", 0, 1024 * 1024, 10); tst_attach_device(dev_path, "test.img"); - - ret = tst_cmd(cmd_parted, NULL, NULL, TST_CMD_PASS_RETVAL); - if (!ret) - parted_sup = 1; - else if (ret == 255) - tst_res(TCONF, "parted binary not installed or failed"); - else - tst_res(TCONF, "parted exited with %i", ret); - attach_flag = 1; TST_ASSERT_INT(partscan_path, 0); @@ -112,10 +98,20 @@ static void verify_ioctl_loop(void) static void setup(void) { + parted_sup = tst_cmd_present("parted"); + + const char *const cmd_parted[] = {"parted", "-s", "test.img", "mklabel", "msdos", "mkpart", + "primary", "ext4", "1M", "10M", NULL}; + dev_num = tst_find_free_loopdev(dev_path, sizeof(dev_path)); if (dev_num < 0) tst_brk(TBROK, "Failed to find free loop device"); + tst_fill_file("test.img", 0, 1024 * 1024, 10); + + if (parted_sup) + SAFE_CMD(cmd_parted, NULL, NULL); + sprintf(partscan_path, "/sys/block/loop%d/loop/partscan", dev_num); sprintf(autoclear_path, "/sys/block/loop%d/loop/autoclear", dev_num); sprintf(backing_path, "/sys/block/loop%d/loop/backing_file", dev_num); @@ -148,5 +144,9 @@ static struct tst_test test = { {"linux-git", "6ac92fb5cdff"}, {} }, + .needs_cmds = (struct tst_cmd[]) { + {.cmd = "parted", .optional = 1}, + {} + }, .needs_tmpdir = 1, }; diff --git a/testcases/kernel/syscalls/madvise/madvise11.c b/testcases/kernel/syscalls/madvise/madvise11.c index 422589f5b..73d2d4294 100644 --- a/testcases/kernel/syscalls/madvise/madvise11.c +++ b/testcases/kernel/syscalls/madvise/madvise11.c @@ -421,10 +421,10 @@ static struct tst_test test = { HW_MODULE, NULL }, - .needs_cmds = (const char *[]) { - "modprobe", - "rmmod", - NULL + .needs_cmds = (struct tst_cmd[]) { + {.cmd = "modprobe"}, + {.cmd = "rmmod"}, + {} }, .needs_kconfigs = (const char *[]) { "CONFIG_MEMORY_FAILURE=y", diff --git a/testcases/kernel/syscalls/quotactl/quotactl01.c b/testcases/kernel/syscalls/quotactl/quotactl01.c index 9dcf74ceb..3091ac5bf 100644 --- a/testcases/kernel/syscalls/quotactl/quotactl01.c +++ b/testcases/kernel/syscalls/quotactl/quotactl01.c @@ -223,9 +223,9 @@ static struct tst_test test = { {} }, .mntpoint = MNTPOINT, - .needs_cmds = (const char *const []) { - "quotacheck", - NULL + .needs_cmds = (struct tst_cmd[]) { + {.cmd = "quotacheck"}, + {} }, .setup = setup, .cleanup = cleanup, diff --git a/testcases/kernel/syscalls/quotactl/quotactl04.c b/testcases/kernel/syscalls/quotactl/quotactl04.c index d2d7b3f3e..a70903330 100644 --- a/testcases/kernel/syscalls/quotactl/quotactl04.c +++ b/testcases/kernel/syscalls/quotactl/quotactl04.c @@ -165,8 +165,8 @@ static struct tst_test test = { }, .mntpoint = MNTPOINT, .test_variants = QUOTACTL_SYSCALL_VARIANTS, - .needs_cmds = (const char *[]) { - "mkfs.ext4 >= 1.43.0", - NULL + .needs_cmds = (struct tst_cmd[]) { + {.cmd = "mkfs.ext4 >= 1.43.0"}, + {} } }; diff --git a/testcases/kernel/syscalls/quotactl/quotactl06.c b/testcases/kernel/syscalls/quotactl/quotactl06.c index 110a3aa9b..333f5720d 100644 --- a/testcases/kernel/syscalls/quotactl/quotactl06.c +++ b/testcases/kernel/syscalls/quotactl/quotactl06.c @@ -226,9 +226,9 @@ static struct tst_test test = { }, .mntpoint = MNTPOINT, .mount_device = 1, - .needs_cmds = (const char *const []) { - "quotacheck", - NULL + .needs_cmds = (struct tst_cmd[]) { + {.cmd = "quotacheck"}, + {} }, .needs_root = 1, .test_variants = QUOTACTL_FMT_VARIANTS, diff --git a/testcases/kernel/syscalls/quotactl/quotactl08.c b/testcases/kernel/syscalls/quotactl/quotactl08.c index 63087345f..ce7a8b008 100644 --- a/testcases/kernel/syscalls/quotactl/quotactl08.c +++ b/testcases/kernel/syscalls/quotactl/quotactl08.c @@ -220,8 +220,8 @@ static struct tst_test test = { .setup = setup, .cleanup = cleanup, .test_variants = QUOTACTL_SYSCALL_VARIANTS, - .needs_cmds = (const char *[]) { - "mkfs.ext4 >= 1.43.0", - NULL + .needs_cmds = (struct tst_cmd[]) { + {.cmd = "mkfs.ext4 >= 1.43.0"}, + {} } }; diff --git a/testcases/kernel/syscalls/quotactl/quotactl09.c b/testcases/kernel/syscalls/quotactl/quotactl09.c index 673666347..fd6629c0c 100644 --- a/testcases/kernel/syscalls/quotactl/quotactl09.c +++ b/testcases/kernel/syscalls/quotactl/quotactl09.c @@ -185,8 +185,8 @@ static struct tst_test test = { .mount_device = 1, .needs_root = 1, .test_variants = QUOTACTL_SYSCALL_VARIANTS, - .needs_cmds = (const char *[]) { - "mkfs.ext4 >= 1.43.0", - NULL + .needs_cmds = (struct tst_cmd[]) { + {.cmd = "mkfs.ext4 >= 1.43.0"}, + {} } }; diff --git a/testcases/kernel/syscalls/statx/statx05.c b/testcases/kernel/syscalls/statx/statx05.c index 2a4603226..07b5e7b94 100644 --- a/testcases/kernel/syscalls/statx/statx05.c +++ b/testcases/kernel/syscalls/statx/statx05.c @@ -123,9 +123,9 @@ static struct tst_test test = { {.type = "ext4"}, {} }, - .needs_cmds = (const char *[]) { - "mkfs.ext4 >= 1.43.0", - "e4crypt", - NULL + .needs_cmds = (struct tst_cmd[]) { + {.cmd = "mkfs.ext4 >= 1.43.0"}, + {.cmd = "e4crypt"}, + {} } }; diff --git a/testcases/kernel/syscalls/statx/statx07.c b/testcases/kernel/syscalls/statx/statx07.c index bab64591f..755644cf9 100644 --- a/testcases/kernel/syscalls/statx/statx07.c +++ b/testcases/kernel/syscalls/statx/statx07.c @@ -171,8 +171,8 @@ static struct tst_test test = { {} }, .needs_root = 1, - .needs_cmds = (const char *[]) { - "exportfs", - NULL + .needs_cmds = (struct tst_cmd[]) { + {.cmd = "exportfs"}, + {} } }; diff --git a/testcases/kernel/syscalls/statx/statx09.c b/testcases/kernel/syscalls/statx/statx09.c index ee4be4250..8838d5450 100644 --- a/testcases/kernel/syscalls/statx/statx09.c +++ b/testcases/kernel/syscalls/statx/statx09.c @@ -162,8 +162,8 @@ static struct tst_test test = { "CONFIG_FS_VERITY", NULL }, - .needs_cmds = (const char *[]) { - "mkfs.ext4 >= 1.45.2", - NULL + .needs_cmds = (struct tst_cmd[]) { + {.cmd = "mkfs.ext4 >= 1.45.2"}, + {} } }; -- 2.51.0 -- Mailing list info: https://lists.linux.it/listinfo/ltp ^ permalink raw reply related [flat|nested] 100+ messages in thread
* [LTP] [PATCH v4 3/3] tst_run_shell.c: Add new function handle new needs_cmds 2025-10-17 10:09 ` [LTP] [PATCH v4 0/3] new cmd support option for needs_cmds Wei Gao via ltp 2025-10-17 10:09 ` [LTP] [PATCH v4 1/3] lib: Add support option for .needs_cmds Wei Gao via ltp 2025-10-17 10:09 ` [LTP] [PATCH v4 2/3] Update test cases use new needs_cmds Wei Gao via ltp @ 2025-10-17 10:09 ` Wei Gao via ltp 2025-10-17 15:30 ` Petr Vorel 2025-10-17 15:41 ` Petr Vorel 2 siblings, 2 replies; 100+ messages in thread From: Wei Gao via ltp @ 2025-10-17 10:09 UTC (permalink / raw) To: ltp Signed-off-by: Wei Gao <wegao@suse.com> --- testcases/lib/tst_run_shell.c | 61 ++++++++++++++++++++++++++++++++++- 1 file changed, 60 insertions(+), 1 deletion(-) diff --git a/testcases/lib/tst_run_shell.c b/testcases/lib/tst_run_shell.c index 7a446e004..a6e0d1d29 100644 --- a/testcases/lib/tst_run_shell.c +++ b/testcases/lib/tst_run_shell.c @@ -175,6 +175,23 @@ static ujson_obj fs_obj = { .attr_cnt = UJSON_ARRAY_SIZE(fs_attrs), }; +enum cmd_ids { + CMD, + OPTIONAL, + PRESENT, +}; + +static ujson_obj_attr cmd_attrs[] = { + UJSON_OBJ_ATTR_IDX(CMD, "cmd", UJSON_STR), + UJSON_OBJ_ATTR_IDX(OPTIONAL, "optional", UJSON_INT), + UJSON_OBJ_ATTR_IDX(PRESENT, "present", UJSON_INT), +}; + +static ujson_obj cmd_obj = { + .attrs = cmd_attrs, + .attr_cnt = UJSON_ARRAY_SIZE(cmd_attrs), +}; + static int parse_mnt_flags(ujson_reader *reader, ujson_val *val) { int ret = 0; @@ -252,6 +269,48 @@ static struct tst_fs *parse_filesystems(ujson_reader *reader, ujson_val *val) return ret; } +static struct tst_cmd *parse_cmds(ujson_reader *reader, ujson_val *val) +{ + unsigned int i = 0, cnt = 0; + struct tst_cmd *ret; + + ujson_reader_state state = ujson_reader_state_save(reader); + + UJSON_ARR_FOREACH(reader, val) { + if (val->type != UJSON_ARR) { + ujson_err(reader, "Expected array!"); + return NULL; + } + ujson_arr_skip(reader); + cnt++; + } + + ujson_reader_state_load(reader, state); + + ret = SAFE_MALLOC(sizeof(struct tst_cmd) * (cnt + 1)); + memset(&ret[cnt], 0, sizeof(ret[cnt])); + + UJSON_ARR_FOREACH(reader, val) { + UJSON_OBJ_FOREACH_FILTER(reader, val, &cmd_obj, ujson_empty_obj) { + switch ((enum cmd_ids)val->idx) { + case CMD: + ret[i].cmd = strdup(val->val_str); + break; + case OPTIONAL: + ret[i].optional = val->val_int; + break; + case MKFS_VER: + ret[i].present = val->val_int; + break; + } + } + + i++; + } + + return ret; +} + static struct tst_tag *parse_tags(ujson_reader *reader, ujson_val *val) { unsigned int i = 0, cnt = 0; @@ -440,7 +499,7 @@ static void parse_metadata(void) ujson_err(&reader, "ABI bits must be 32 or 64"); break; case NEEDS_CMDS: - test.needs_cmds = parse_strarr(&reader, &val); + test.needs_cmds = parse_cmds(&reader, &val); break; case NEEDS_DEVFS: test.needs_devfs = val.val_bool; -- 2.51.0 -- Mailing list info: https://lists.linux.it/listinfo/ltp ^ permalink raw reply related [flat|nested] 100+ messages in thread
* Re: [LTP] [PATCH v4 3/3] tst_run_shell.c: Add new function handle new needs_cmds 2025-10-17 10:09 ` [LTP] [PATCH v4 3/3] tst_run_shell.c: Add new function handle " Wei Gao via ltp @ 2025-10-17 15:30 ` Petr Vorel 2025-10-17 15:41 ` Petr Vorel 1 sibling, 0 replies; 100+ messages in thread From: Petr Vorel @ 2025-10-17 15:30 UTC (permalink / raw) To: Wei Gao; +Cc: ltp Hi Wei, > + UJSON_ARR_FOREACH(reader, val) { > + UJSON_OBJ_FOREACH_FILTER(reader, val, &cmd_obj, ujson_empty_obj) { > + switch ((enum cmd_ids)val->idx) { > + case CMD: > + ret[i].cmd = strdup(val->val_str); > + break; > + case OPTIONAL: > + ret[i].optional = val->val_int; > + break; > + case MKFS_VER: > + ret[i].present = val->val_int; My compiler shows 2 warnings: tst_run_shell.c:302:25: warning: case value ‘3’ not in enumerated type ‘enum cmd_ids’ [-Wswitch] 302 | case MKFS_VER: | ^~~~ => Indeed, MKFS_VER is part of enum fs_ids, it should not be here. Another warning: tst_run_shell.c: In function ‘parse_cmds’: tst_run_shell.c:295:25: warning: enumeration value ‘PRESENT’ not handled in switch [-Wswitch] 295 | switch ((enum cmd_ids)val->idx) { | ^~~~~~ => Either it MKFS_VER should have PRESENT, or, because struct tst_cmd->present should not be set in the test, but by C API, we might want to call ujson_err()? Kind regards, Petr -- Mailing list info: https://lists.linux.it/listinfo/ltp ^ permalink raw reply [flat|nested] 100+ messages in thread
* Re: [LTP] [PATCH v4 3/3] tst_run_shell.c: Add new function handle new needs_cmds 2025-10-17 10:09 ` [LTP] [PATCH v4 3/3] tst_run_shell.c: Add new function handle " Wei Gao via ltp 2025-10-17 15:30 ` Petr Vorel @ 2025-10-17 15:41 ` Petr Vorel 2025-10-20 1:41 ` Wei Gao via ltp 1 sibling, 1 reply; 100+ messages in thread From: Petr Vorel @ 2025-10-17 15:41 UTC (permalink / raw) To: Wei Gao; +Cc: ltp Hi Wei, > testcases/lib/tst_run_shell.c | 61 ++++++++++++++++++++++++++++++++++- > 1 file changed, 60 insertions(+), 1 deletion(-) Also here, any change you would add a test for a new feature (as a separate commit in e.g. testcases/lib/tests/shell_loader_cmd.sh). Kind regards, Petr -- Mailing list info: https://lists.linux.it/listinfo/ltp ^ permalink raw reply [flat|nested] 100+ messages in thread
* Re: [LTP] [PATCH v4 3/3] tst_run_shell.c: Add new function handle new needs_cmds 2025-10-17 15:41 ` Petr Vorel @ 2025-10-20 1:41 ` Wei Gao via ltp 0 siblings, 0 replies; 100+ messages in thread From: Wei Gao via ltp @ 2025-10-20 1:41 UTC (permalink / raw) To: Petr Vorel; +Cc: ltp On Fri, Oct 17, 2025 at 05:41:35PM +0200, Petr Vorel wrote: > Hi Wei, > > > testcases/lib/tst_run_shell.c | 61 ++++++++++++++++++++++++++++++++++- > > 1 file changed, 60 insertions(+), 1 deletion(-) > > Also here, any change you would add a test for a new feature (as a separate > commit in e.g. testcases/lib/tests/shell_loader_cmd.sh). Will added in separate commit in next patch. > > Kind regards, > Petr -- Mailing list info: https://lists.linux.it/listinfo/ltp ^ permalink raw reply [flat|nested] 100+ messages in thread
* [LTP] [PATCH v4 0/4] new cmd support option for needs_cmds 2025-10-10 6:45 ` [LTP] [PATCH v3 0/4] new cmd support option for needs_cmds Wei Gao via ltp ` (4 preceding siblings ...) 2025-10-17 10:09 ` [LTP] [PATCH v4 0/3] new cmd support option for needs_cmds Wei Gao via ltp @ 2025-11-07 0:30 ` Wei Gao via ltp 2025-11-07 0:30 ` [LTP] [PATCH v4 1/4] tst_cmd.c: Check brk_nosupp when tst_get_path failed Wei Gao via ltp ` (4 more replies) 5 siblings, 5 replies; 100+ messages in thread From: Wei Gao via ltp @ 2025-11-07 0:30 UTC (permalink / raw) To: ltp v3->v4: - Reorganize the patches so that each one compiles successfully - Add new test case for needs_cmds Wei Gao (4): tst_cmd.c: Check brk_nosupp when tst_get_path failed lib: Add support option for .needs_cmds ioctl_loop01.c: Add new support .needs_cmds shell_loader_cmd.sh: New test case check needs_cmds include/tst_cmd.h | 13 ++++ include/tst_test.h | 16 ++++- lib/newlib_tests/tst_needs_cmds01.c | 16 ++--- lib/newlib_tests/tst_needs_cmds02.c | 6 +- lib/newlib_tests/tst_needs_cmds03.c | 6 +- lib/newlib_tests/tst_needs_cmds04.c | 6 +- lib/newlib_tests/tst_needs_cmds05.c | 6 +- lib/newlib_tests/tst_needs_cmds06.c | 6 +- lib/newlib_tests/tst_needs_cmds07.c | 6 +- lib/newlib_tests/tst_needs_cmds08.c | 8 +-- lib/tst_cmd.c | 10 ++- lib/tst_test.c | 22 +++++-- testcases/kernel/device-drivers/zram/zram03.c | 8 +-- testcases/kernel/fs/squashfs/squashfs01.c | 6 +- testcases/kernel/security/aslr/aslr01.c | 6 +- testcases/kernel/syscalls/add_key/add_key05.c | 10 +-- .../kernel/syscalls/fanotify/fanotify22.c | 6 +- testcases/kernel/syscalls/ioctl/ioctl09.c | 6 +- .../kernel/syscalls/ioctl/ioctl_loop01.c | 28 ++++----- testcases/kernel/syscalls/madvise/madvise11.c | 8 +-- .../kernel/syscalls/quotactl/quotactl01.c | 6 +- .../kernel/syscalls/quotactl/quotactl04.c | 6 +- .../kernel/syscalls/quotactl/quotactl06.c | 6 +- .../kernel/syscalls/quotactl/quotactl08.c | 6 +- .../kernel/syscalls/quotactl/quotactl09.c | 6 +- testcases/kernel/syscalls/statx/statx05.c | 8 +-- testcases/kernel/syscalls/statx/statx07.c | 6 +- testcases/kernel/syscalls/statx/statx09.c | 6 +- testcases/lib/run_tests.sh | 1 + testcases/lib/tests/shell_loader_cmd.sh | 24 ++++++++ testcases/lib/tst_run_shell.c | 61 ++++++++++++++++++- 31 files changed, 232 insertions(+), 103 deletions(-) create mode 100755 testcases/lib/tests/shell_loader_cmd.sh -- 2.51.0 -- Mailing list info: https://lists.linux.it/listinfo/ltp ^ permalink raw reply [flat|nested] 100+ messages in thread
* [LTP] [PATCH v4 1/4] tst_cmd.c: Check brk_nosupp when tst_get_path failed 2025-11-07 0:30 ` [LTP] [PATCH v4 0/4] new cmd support option for needs_cmds Wei Gao via ltp @ 2025-11-07 0:30 ` Wei Gao via ltp 2025-11-07 10:33 ` Petr Vorel 2025-11-07 0:30 ` [LTP] [PATCH v4 2/4] lib: Add support option for .needs_cmds Wei Gao via ltp ` (3 subsequent siblings) 4 siblings, 1 reply; 100+ messages in thread From: Wei Gao via ltp @ 2025-11-07 0:30 UTC (permalink / raw) To: ltp Fixes: 257394e4e3 ("Filter mkfs version in tst_fs") Signed-off-by: Wei Gao <wegao@suse.com> --- lib/tst_cmd.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/lib/tst_cmd.c b/lib/tst_cmd.c index 2faf7c743..716029c9b 100644 --- a/lib/tst_cmd.c +++ b/lib/tst_cmd.c @@ -265,8 +265,14 @@ bool tst_check_cmd(const char *cmd, const int brk_nosupp) version_token = strtok_r(NULL, " ", &next); str = strtok_r(NULL, " ", &next); - if (tst_get_path(cmd_token, path, sizeof(path))) - tst_brkm(TCONF, NULL, "Couldn't find '%s' in $PATH", cmd_token); + if (tst_get_path(cmd_token, path, sizeof(path))) { + if (brk_nosupp) { + tst_brkm(TCONF, NULL, "Couldn't find '%s' in $PATH", cmd_token); + } else { + tst_resm(TCONF, "Couldn't find '%s' in $PATH", cmd_token); + return 1; + } + } if (!op_token) return true; -- 2.51.0 -- Mailing list info: https://lists.linux.it/listinfo/ltp ^ permalink raw reply related [flat|nested] 100+ messages in thread
* Re: [LTP] [PATCH v4 1/4] tst_cmd.c: Check brk_nosupp when tst_get_path failed 2025-11-07 0:30 ` [LTP] [PATCH v4 1/4] tst_cmd.c: Check brk_nosupp when tst_get_path failed Wei Gao via ltp @ 2025-11-07 10:33 ` Petr Vorel 0 siblings, 0 replies; 100+ messages in thread From: Petr Vorel @ 2025-11-07 10:33 UTC (permalink / raw) To: Wei Gao; +Cc: ltp Hi Wei, > Fixes: 257394e4e3 ("Filter mkfs version in tst_fs") > Signed-off-by: Wei Gao <wegao@suse.com> > --- > lib/tst_cmd.c | 10 ++++++++-- > 1 file changed, 8 insertions(+), 2 deletions(-) > diff --git a/lib/tst_cmd.c b/lib/tst_cmd.c > index 2faf7c743..716029c9b 100644 > --- a/lib/tst_cmd.c > +++ b/lib/tst_cmd.c > @@ -265,8 +265,14 @@ bool tst_check_cmd(const char *cmd, const int brk_nosupp) > version_token = strtok_r(NULL, " ", &next); > str = strtok_r(NULL, " ", &next); > - if (tst_get_path(cmd_token, path, sizeof(path))) > - tst_brkm(TCONF, NULL, "Couldn't find '%s' in $PATH", cmd_token); > + if (tst_get_path(cmd_token, path, sizeof(path))) { > + if (brk_nosupp) { > + tst_brkm(TCONF, NULL, "Couldn't find '%s' in $PATH", cmd_token); > + } else { > + tst_resm(TCONF, "Couldn't find '%s' in $PATH", cmd_token); > + return 1; Function now returns 'bool', therefore 'true' or 'false' should be returned. IMHO this should be false, therefore I resent it: https://lore.kernel.org/ltp/20251107102939.1111074-3-pvorel@suse.cz/ and set this patch "changes requested". Also, I found a fix in the change I introduced, therefore send a patch which fixes it: https://lore.kernel.org/ltp/20251107102939.1111074-2-pvorel@suse.cz/ Kind regards, Petr -- Mailing list info: https://lists.linux.it/listinfo/ltp ^ permalink raw reply [flat|nested] 100+ messages in thread
* [LTP] [PATCH v4 2/4] lib: Add support option for .needs_cmds 2025-11-07 0:30 ` [LTP] [PATCH v4 0/4] new cmd support option for needs_cmds Wei Gao via ltp 2025-11-07 0:30 ` [LTP] [PATCH v4 1/4] tst_cmd.c: Check brk_nosupp when tst_get_path failed Wei Gao via ltp @ 2025-11-07 0:30 ` Wei Gao via ltp 2025-11-07 0:30 ` [LTP] [PATCH v4 3/4] ioctl_loop01.c: Add new support .needs_cmds Wei Gao via ltp ` (2 subsequent siblings) 4 siblings, 0 replies; 100+ messages in thread From: Wei Gao via ltp @ 2025-11-07 0:30 UTC (permalink / raw) To: ltp Suggested-by: Cyril Hrubis <chrubis@suse.cz> Signed-off-by: Wei Gao <wegao@suse.com> --- include/tst_cmd.h | 13 ++++ include/tst_test.h | 16 ++++- lib/newlib_tests/tst_needs_cmds01.c | 16 ++--- lib/newlib_tests/tst_needs_cmds02.c | 6 +- lib/newlib_tests/tst_needs_cmds03.c | 6 +- lib/newlib_tests/tst_needs_cmds04.c | 6 +- lib/newlib_tests/tst_needs_cmds05.c | 6 +- lib/newlib_tests/tst_needs_cmds06.c | 6 +- lib/newlib_tests/tst_needs_cmds07.c | 6 +- lib/newlib_tests/tst_needs_cmds08.c | 8 +-- lib/tst_test.c | 22 +++++-- testcases/kernel/device-drivers/zram/zram03.c | 8 +-- testcases/kernel/fs/squashfs/squashfs01.c | 6 +- testcases/kernel/security/aslr/aslr01.c | 6 +- testcases/kernel/syscalls/add_key/add_key05.c | 10 +-- .../kernel/syscalls/fanotify/fanotify22.c | 6 +- testcases/kernel/syscalls/ioctl/ioctl09.c | 6 +- testcases/kernel/syscalls/madvise/madvise11.c | 8 +-- .../kernel/syscalls/quotactl/quotactl01.c | 6 +- .../kernel/syscalls/quotactl/quotactl04.c | 6 +- .../kernel/syscalls/quotactl/quotactl06.c | 6 +- .../kernel/syscalls/quotactl/quotactl08.c | 6 +- .../kernel/syscalls/quotactl/quotactl09.c | 6 +- testcases/kernel/syscalls/statx/statx05.c | 8 +-- testcases/kernel/syscalls/statx/statx07.c | 6 +- testcases/kernel/syscalls/statx/statx09.c | 6 +- testcases/lib/tst_run_shell.c | 61 ++++++++++++++++++- 27 files changed, 185 insertions(+), 87 deletions(-) diff --git a/include/tst_cmd.h b/include/tst_cmd.h index cf6382955..2203241c5 100644 --- a/include/tst_cmd.h +++ b/include/tst_cmd.h @@ -19,6 +19,19 @@ enum tst_cmd_flags { TST_CMD_TCONF_ON_MISSING = 2, }; +/** + * struct tst_cmd - Provides details about a command struct needed by LTP test. + * @cmd: The name of the command. + * @optional: A flag indicating if the command is optional. + * @present: A flag indicating if the command was found at runtime. This is an output + * parameter, set by the LTP library during the test setup. + */ +struct tst_cmd { + const char *cmd; + unsigned int optional:1; + unsigned int present:1; +}; + /* * vfork() + execvp() specified program. * diff --git a/include/tst_test.h b/include/tst_test.h index 9c21c1728..9305cf39d 100644 --- a/include/tst_test.h +++ b/include/tst_test.h @@ -524,7 +524,7 @@ struct tst_fs { * * @tags: A {} terminated array of test tags. See struct tst_tag for details. * - * @needs_cmds: A NULL terminated array of commands required for the test to run. + * @needs_cmds: A NULL terminated array of struct tst_cmd required for the test to run. * * @needs_cgroup_ver: If set the test will run only if the specified cgroup * version is present on the system. @@ -617,7 +617,7 @@ struct tst_fs { const struct tst_tag *tags; - const char *const *needs_cmds; + struct tst_cmd *needs_cmds; const enum tst_cg_ver needs_cgroup_ver; @@ -721,6 +721,18 @@ int tst_creat_unlinked(const char *path, int flags, mode_t mode); */ const char *tst_get_tmpdir_root(void); +/** + * tst_cmd_present() - Check if a command is present + * @cmd: The name of the command to check for. + * + * This function iterates through the &tst_test->needs_cmds array. It compares + * the given command name with each entry in the array and returns the 'present' + * flag for the matching command. + * + * Return: `true` if the command is present, `false` otherwise. + */ +bool tst_cmd_present(const char *cmd); + /* * Validates exit status of child processes */ diff --git a/lib/newlib_tests/tst_needs_cmds01.c b/lib/newlib_tests/tst_needs_cmds01.c index 777c69505..6ab1145d1 100644 --- a/lib/newlib_tests/tst_needs_cmds01.c +++ b/lib/newlib_tests/tst_needs_cmds01.c @@ -12,13 +12,13 @@ static void do_test(void) static struct tst_test test = { .test_all = do_test, - .needs_cmds = (const char *[]) { - "mkfs.ext4", - "mkfs.ext4 >= 1.0.0", - "mkfs.ext4 <= 2.0.0", - "mkfs.ext4 != 2.0.0", - "mkfs.ext4 > 1.0.0", - "mkfs.ext4 < 2.0.0", - NULL + .needs_cmds = (struct tst_cmd[]) { + {.cmd = "mkfs.ext4", .optional = 1}, + {.cmd = "mkfs.ext4 >= 1.0.0", .optional = 0}, + {.cmd = "mkfs.ext4 <= 2.0.0"}, + {.cmd = "mkfs.ext4 != 2.0.0"}, + {.cmd = "mkfs.ext4 > 1.0.0"}, + {.cmd = "mkfs.ext4 < 2.0.0"}, + {} } }; diff --git a/lib/newlib_tests/tst_needs_cmds02.c b/lib/newlib_tests/tst_needs_cmds02.c index 455a275ea..f1d6105c2 100644 --- a/lib/newlib_tests/tst_needs_cmds02.c +++ b/lib/newlib_tests/tst_needs_cmds02.c @@ -16,8 +16,8 @@ static void do_test(void) static struct tst_test test = { .test_all = do_test, - .needs_cmds = (const char *[]) { - "mkfs.ext45 >= 1.43.0", - NULL + .needs_cmds = (struct tst_cmd[]) { + {.cmd = "mkfs.ext45 >= 1.43.0"}, + {} } }; diff --git a/lib/newlib_tests/tst_needs_cmds03.c b/lib/newlib_tests/tst_needs_cmds03.c index bdc1cdf6a..ac5f368e2 100644 --- a/lib/newlib_tests/tst_needs_cmds03.c +++ b/lib/newlib_tests/tst_needs_cmds03.c @@ -16,8 +16,8 @@ static void do_test(void) static struct tst_test test = { .test_all = do_test, - .needs_cmds = (const char *[]) { - "mkfs.ext4 ! 1.43.0", - NULL + .needs_cmds = (struct tst_cmd[]) { + {.cmd = "mkfs.ext4 ! 1.43.0"}, + {} } }; diff --git a/lib/newlib_tests/tst_needs_cmds04.c b/lib/newlib_tests/tst_needs_cmds04.c index de10b8f3e..2aea51772 100644 --- a/lib/newlib_tests/tst_needs_cmds04.c +++ b/lib/newlib_tests/tst_needs_cmds04.c @@ -16,8 +16,8 @@ static void do_test(void) static struct tst_test test = { .test_all = do_test, - .needs_cmds = (const char *[]) { - "mkfs.ext4 > 1.43", - NULL + .needs_cmds = (struct tst_cmd[]) { + {.cmd = "mkfs.ext4 > 1.43"}, + {} } }; diff --git a/lib/newlib_tests/tst_needs_cmds05.c b/lib/newlib_tests/tst_needs_cmds05.c index c3b2b3b9a..969d4e2f5 100644 --- a/lib/newlib_tests/tst_needs_cmds05.c +++ b/lib/newlib_tests/tst_needs_cmds05.c @@ -16,8 +16,8 @@ static void do_test(void) static struct tst_test test = { .test_all = do_test, - .needs_cmds = (const char *[]) { - "mkfs.ext4 > 1.43.0-1", - NULL + .needs_cmds = (struct tst_cmd[]) { + {.cmd = "mkfs.ext4 > 1.43.0-1"}, + {} } }; diff --git a/lib/newlib_tests/tst_needs_cmds06.c b/lib/newlib_tests/tst_needs_cmds06.c index 40b1cf09c..91470ccf9 100644 --- a/lib/newlib_tests/tst_needs_cmds06.c +++ b/lib/newlib_tests/tst_needs_cmds06.c @@ -16,8 +16,8 @@ static void do_test(void) static struct tst_test test = { .test_all = do_test, - .needs_cmds = (const char *[]) { - "mkfs.ext4 > 1.43.0 2", - NULL + .needs_cmds = (struct tst_cmd[]) { + {.cmd = "mkfs.ext4 > 1.43.0 2"}, + {} } }; diff --git a/lib/newlib_tests/tst_needs_cmds07.c b/lib/newlib_tests/tst_needs_cmds07.c index d0b4ce2ff..371bbdc1b 100644 --- a/lib/newlib_tests/tst_needs_cmds07.c +++ b/lib/newlib_tests/tst_needs_cmds07.c @@ -16,8 +16,8 @@ static void do_test(void) static struct tst_test test = { .test_all = do_test, - .needs_cmds = (const char *[]) { - "mkfs.ext45", - NULL + .needs_cmds = (struct tst_cmd[]) { + {.cmd = "mkfs.ext45"}, + {} } }; diff --git a/lib/newlib_tests/tst_needs_cmds08.c b/lib/newlib_tests/tst_needs_cmds08.c index 38df2ef6d..412f9f293 100644 --- a/lib/newlib_tests/tst_needs_cmds08.c +++ b/lib/newlib_tests/tst_needs_cmds08.c @@ -18,9 +18,9 @@ static void do_test(void) static struct tst_test test = { .test_all = do_test, - .needs_cmds = (const char *[]) { - "mkfs.xfs", - "mkfs.xfs >= 4.20.0", - NULL + .needs_cmds = (struct tst_cmd[]) { + {.cmd = "mkfs.xfs"}, + {.cmd = "mkfs.xfs >= 4.20.0"}, + {} } }; diff --git a/lib/tst_test.c b/lib/tst_test.c index da5314c50..67553f65d 100644 --- a/lib/tst_test.c +++ b/lib/tst_test.c @@ -1365,6 +1365,19 @@ static const char *default_fs_type(void) return tst_dev_fs_type(); } +bool tst_cmd_present(const char *cmd) +{ + struct tst_cmd *pcmd = tst_test->needs_cmds; + + while (pcmd->cmd) { + if (!strcmp(pcmd->cmd, cmd)) + return pcmd->present; + + pcmd++; + } + return false; +} + static void do_setup(int argc, char *argv[]) { char *tdebug_env = getenv("LTP_ENABLE_DEBUG"); @@ -1439,11 +1452,12 @@ static void do_setup(int argc, char *argv[]) tst_brk(TCONF, "%dbit ABI is not supported", tst_test->needs_abi_bits); if (tst_test->needs_cmds) { - const char *cmd; - int i; + struct tst_cmd *pcmd = tst_test->needs_cmds; - for (i = 0; (cmd = tst_test->needs_cmds[i]); ++i) - tst_check_cmd(cmd, 1); + while (pcmd->cmd) { + pcmd->present = tst_check_cmd(pcmd->cmd, !pcmd->optional) ? 1 : 0; + pcmd++; + } } if (tst_test->needs_drivers) { diff --git a/testcases/kernel/device-drivers/zram/zram03.c b/testcases/kernel/device-drivers/zram/zram03.c index 8cf26de4c..4dcf23b4e 100644 --- a/testcases/kernel/device-drivers/zram/zram03.c +++ b/testcases/kernel/device-drivers/zram/zram03.c @@ -240,9 +240,9 @@ static struct tst_test test = { "zram", NULL }, - .needs_cmds = (const char *[]) { - "modprobe", - "rmmod", - NULL + .needs_cmds = (struct tst_cmd[]) { + {.cmd = "modprobe"}, + {.cmd = "rmmod"}, + {} } }; diff --git a/testcases/kernel/fs/squashfs/squashfs01.c b/testcases/kernel/fs/squashfs/squashfs01.c index fbcb76582..7a548d62c 100644 --- a/testcases/kernel/fs/squashfs/squashfs01.c +++ b/testcases/kernel/fs/squashfs/squashfs01.c @@ -102,9 +102,9 @@ static struct tst_test test = { .needs_root = 1, .needs_device = 1, .dev_min_size = 1, - .needs_cmds = (const char *const []) { - "mksquashfs", - NULL + .needs_cmds = (struct tst_cmd[]) { + {.cmd = "mksquashfs"}, + {} }, .needs_drivers = (const char *const []) { "squashfs", diff --git a/testcases/kernel/security/aslr/aslr01.c b/testcases/kernel/security/aslr/aslr01.c index 6a396e29d..e6feb2d3c 100644 --- a/testcases/kernel/security/aslr/aslr01.c +++ b/testcases/kernel/security/aslr/aslr01.c @@ -277,8 +277,8 @@ static struct tst_test test = { "CONFIG_HAVE_ARCH_MMAP_RND_BITS=y", NULL }, - .needs_cmds = (const char *[]) { - "ldd", - NULL + .needs_cmds = (struct tst_cmd[]) { + {.cmd = "ldd"}, + {} }, }; diff --git a/testcases/kernel/syscalls/add_key/add_key05.c b/testcases/kernel/syscalls/add_key/add_key05.c index c9a2f840e..b51a84b97 100644 --- a/testcases/kernel/syscalls/add_key/add_key05.c +++ b/testcases/kernel/syscalls/add_key/add_key05.c @@ -231,11 +231,11 @@ static struct tst_test test = { {&user_buf, .size = 64}, {} }, - .needs_cmds = (const char *const []) { - "useradd", - "userdel", - "groupdel", - NULL + .needs_cmds = (struct tst_cmd[]) { + {.cmd = "useradd"}, + {.cmd = "userdel"}, + {.cmd = "groupdel"}, + {} }, .tags = (const struct tst_tag[]) { {"linux-git", "a08bf91ce28"}, diff --git a/testcases/kernel/syscalls/fanotify/fanotify22.c b/testcases/kernel/syscalls/fanotify/fanotify22.c index 357e74dbc..6578474a7 100644 --- a/testcases/kernel/syscalls/fanotify/fanotify22.c +++ b/testcases/kernel/syscalls/fanotify/fanotify22.c @@ -327,9 +327,9 @@ static struct tst_test test = { {"linux-git", "76486b104168"}, {} }, - .needs_cmds = (const char *[]) { - "debugfs", - NULL + .needs_cmds = (struct tst_cmd[]) { + {.cmd = "debugfs"}, + {} } }; diff --git a/testcases/kernel/syscalls/ioctl/ioctl09.c b/testcases/kernel/syscalls/ioctl/ioctl09.c index 262d6fcab..737aee680 100644 --- a/testcases/kernel/syscalls/ioctl/ioctl09.c +++ b/testcases/kernel/syscalls/ioctl/ioctl09.c @@ -108,9 +108,9 @@ static struct tst_test test = { "loop", NULL }, - .needs_cmds = (const char *const []) { - "parted", - NULL + .needs_cmds = (struct tst_cmd[]) { + {.cmd = "parted"}, + {} }, .needs_tmpdir = 1, }; diff --git a/testcases/kernel/syscalls/madvise/madvise11.c b/testcases/kernel/syscalls/madvise/madvise11.c index 422589f5b..73d2d4294 100644 --- a/testcases/kernel/syscalls/madvise/madvise11.c +++ b/testcases/kernel/syscalls/madvise/madvise11.c @@ -421,10 +421,10 @@ static struct tst_test test = { HW_MODULE, NULL }, - .needs_cmds = (const char *[]) { - "modprobe", - "rmmod", - NULL + .needs_cmds = (struct tst_cmd[]) { + {.cmd = "modprobe"}, + {.cmd = "rmmod"}, + {} }, .needs_kconfigs = (const char *[]) { "CONFIG_MEMORY_FAILURE=y", diff --git a/testcases/kernel/syscalls/quotactl/quotactl01.c b/testcases/kernel/syscalls/quotactl/quotactl01.c index 9dcf74ceb..3091ac5bf 100644 --- a/testcases/kernel/syscalls/quotactl/quotactl01.c +++ b/testcases/kernel/syscalls/quotactl/quotactl01.c @@ -223,9 +223,9 @@ static struct tst_test test = { {} }, .mntpoint = MNTPOINT, - .needs_cmds = (const char *const []) { - "quotacheck", - NULL + .needs_cmds = (struct tst_cmd[]) { + {.cmd = "quotacheck"}, + {} }, .setup = setup, .cleanup = cleanup, diff --git a/testcases/kernel/syscalls/quotactl/quotactl04.c b/testcases/kernel/syscalls/quotactl/quotactl04.c index d2d7b3f3e..a70903330 100644 --- a/testcases/kernel/syscalls/quotactl/quotactl04.c +++ b/testcases/kernel/syscalls/quotactl/quotactl04.c @@ -165,8 +165,8 @@ static struct tst_test test = { }, .mntpoint = MNTPOINT, .test_variants = QUOTACTL_SYSCALL_VARIANTS, - .needs_cmds = (const char *[]) { - "mkfs.ext4 >= 1.43.0", - NULL + .needs_cmds = (struct tst_cmd[]) { + {.cmd = "mkfs.ext4 >= 1.43.0"}, + {} } }; diff --git a/testcases/kernel/syscalls/quotactl/quotactl06.c b/testcases/kernel/syscalls/quotactl/quotactl06.c index 110a3aa9b..333f5720d 100644 --- a/testcases/kernel/syscalls/quotactl/quotactl06.c +++ b/testcases/kernel/syscalls/quotactl/quotactl06.c @@ -226,9 +226,9 @@ static struct tst_test test = { }, .mntpoint = MNTPOINT, .mount_device = 1, - .needs_cmds = (const char *const []) { - "quotacheck", - NULL + .needs_cmds = (struct tst_cmd[]) { + {.cmd = "quotacheck"}, + {} }, .needs_root = 1, .test_variants = QUOTACTL_FMT_VARIANTS, diff --git a/testcases/kernel/syscalls/quotactl/quotactl08.c b/testcases/kernel/syscalls/quotactl/quotactl08.c index 63087345f..ce7a8b008 100644 --- a/testcases/kernel/syscalls/quotactl/quotactl08.c +++ b/testcases/kernel/syscalls/quotactl/quotactl08.c @@ -220,8 +220,8 @@ static struct tst_test test = { .setup = setup, .cleanup = cleanup, .test_variants = QUOTACTL_SYSCALL_VARIANTS, - .needs_cmds = (const char *[]) { - "mkfs.ext4 >= 1.43.0", - NULL + .needs_cmds = (struct tst_cmd[]) { + {.cmd = "mkfs.ext4 >= 1.43.0"}, + {} } }; diff --git a/testcases/kernel/syscalls/quotactl/quotactl09.c b/testcases/kernel/syscalls/quotactl/quotactl09.c index 673666347..fd6629c0c 100644 --- a/testcases/kernel/syscalls/quotactl/quotactl09.c +++ b/testcases/kernel/syscalls/quotactl/quotactl09.c @@ -185,8 +185,8 @@ static struct tst_test test = { .mount_device = 1, .needs_root = 1, .test_variants = QUOTACTL_SYSCALL_VARIANTS, - .needs_cmds = (const char *[]) { - "mkfs.ext4 >= 1.43.0", - NULL + .needs_cmds = (struct tst_cmd[]) { + {.cmd = "mkfs.ext4 >= 1.43.0"}, + {} } }; diff --git a/testcases/kernel/syscalls/statx/statx05.c b/testcases/kernel/syscalls/statx/statx05.c index 2a4603226..07b5e7b94 100644 --- a/testcases/kernel/syscalls/statx/statx05.c +++ b/testcases/kernel/syscalls/statx/statx05.c @@ -123,9 +123,9 @@ static struct tst_test test = { {.type = "ext4"}, {} }, - .needs_cmds = (const char *[]) { - "mkfs.ext4 >= 1.43.0", - "e4crypt", - NULL + .needs_cmds = (struct tst_cmd[]) { + {.cmd = "mkfs.ext4 >= 1.43.0"}, + {.cmd = "e4crypt"}, + {} } }; diff --git a/testcases/kernel/syscalls/statx/statx07.c b/testcases/kernel/syscalls/statx/statx07.c index bab64591f..755644cf9 100644 --- a/testcases/kernel/syscalls/statx/statx07.c +++ b/testcases/kernel/syscalls/statx/statx07.c @@ -171,8 +171,8 @@ static struct tst_test test = { {} }, .needs_root = 1, - .needs_cmds = (const char *[]) { - "exportfs", - NULL + .needs_cmds = (struct tst_cmd[]) { + {.cmd = "exportfs"}, + {} } }; diff --git a/testcases/kernel/syscalls/statx/statx09.c b/testcases/kernel/syscalls/statx/statx09.c index ee4be4250..8838d5450 100644 --- a/testcases/kernel/syscalls/statx/statx09.c +++ b/testcases/kernel/syscalls/statx/statx09.c @@ -162,8 +162,8 @@ static struct tst_test test = { "CONFIG_FS_VERITY", NULL }, - .needs_cmds = (const char *[]) { - "mkfs.ext4 >= 1.45.2", - NULL + .needs_cmds = (struct tst_cmd[]) { + {.cmd = "mkfs.ext4 >= 1.45.2"}, + {} } }; diff --git a/testcases/lib/tst_run_shell.c b/testcases/lib/tst_run_shell.c index 7a446e004..6def36dcb 100644 --- a/testcases/lib/tst_run_shell.c +++ b/testcases/lib/tst_run_shell.c @@ -175,6 +175,23 @@ static ujson_obj fs_obj = { .attr_cnt = UJSON_ARRAY_SIZE(fs_attrs), }; +enum cmd_ids { + CMD, + OPTIONAL, + PRESENT, +}; + +static ujson_obj_attr cmd_attrs[] = { + UJSON_OBJ_ATTR_IDX(CMD, "cmd", UJSON_STR), + UJSON_OBJ_ATTR_IDX(OPTIONAL, "optional", UJSON_INT), + UJSON_OBJ_ATTR_IDX(PRESENT, "present", UJSON_INT), +}; + +static ujson_obj cmd_obj = { + .attrs = cmd_attrs, + .attr_cnt = UJSON_ARRAY_SIZE(cmd_attrs), +}; + static int parse_mnt_flags(ujson_reader *reader, ujson_val *val) { int ret = 0; @@ -252,6 +269,48 @@ static struct tst_fs *parse_filesystems(ujson_reader *reader, ujson_val *val) return ret; } +static struct tst_cmd *parse_cmds(ujson_reader *reader, ujson_val *val) +{ + unsigned int i = 0, cnt = 0; + struct tst_cmd *ret; + + ujson_reader_state state = ujson_reader_state_save(reader); + + UJSON_ARR_FOREACH(reader, val) { + if (val->type != UJSON_OBJ) { + ujson_err(reader, "Expected object!"); + return NULL; + } + ujson_obj_skip(reader); + cnt++; + } + + ujson_reader_state_load(reader, state); + + ret = SAFE_MALLOC(sizeof(struct tst_cmd) * (cnt + 1)); + memset(&ret[cnt], 0, sizeof(ret[cnt])); + + UJSON_ARR_FOREACH(reader, val) { + UJSON_OBJ_FOREACH_FILTER(reader, val, &cmd_obj, ujson_empty_obj) { + switch ((enum cmd_ids)val->idx) { + case CMD: + ret[i].cmd = strdup(val->val_str); + break; + case OPTIONAL: + ret[i].optional = val->val_int; + break; + case PRESENT: + ret[i].present = val->val_int; + break; + } + } + + i++; + } + + return ret; +} + static struct tst_tag *parse_tags(ujson_reader *reader, ujson_val *val) { unsigned int i = 0, cnt = 0; @@ -440,7 +499,7 @@ static void parse_metadata(void) ujson_err(&reader, "ABI bits must be 32 or 64"); break; case NEEDS_CMDS: - test.needs_cmds = parse_strarr(&reader, &val); + test.needs_cmds = parse_cmds(&reader, &val); break; case NEEDS_DEVFS: test.needs_devfs = val.val_bool; -- 2.51.0 -- Mailing list info: https://lists.linux.it/listinfo/ltp ^ permalink raw reply related [flat|nested] 100+ messages in thread
* [LTP] [PATCH v4 3/4] ioctl_loop01.c: Add new support .needs_cmds 2025-11-07 0:30 ` [LTP] [PATCH v4 0/4] new cmd support option for needs_cmds Wei Gao via ltp 2025-11-07 0:30 ` [LTP] [PATCH v4 1/4] tst_cmd.c: Check brk_nosupp when tst_get_path failed Wei Gao via ltp 2025-11-07 0:30 ` [LTP] [PATCH v4 2/4] lib: Add support option for .needs_cmds Wei Gao via ltp @ 2025-11-07 0:30 ` Wei Gao via ltp 2025-11-07 11:04 ` Petr Vorel 2025-11-07 0:30 ` [LTP] [PATCH v4 4/4] shell_loader_cmd.sh: New test case check needs_cmds Wei Gao via ltp 2025-11-10 2:47 ` [LTP] [PATCH v5 0/3] new cmd support option for needs_cmds Wei Gao via ltp 4 siblings, 1 reply; 100+ messages in thread From: Wei Gao via ltp @ 2025-11-07 0:30 UTC (permalink / raw) To: ltp Signed-off-by: Wei Gao <wegao@suse.com> --- .../kernel/syscalls/ioctl/ioctl_loop01.c | 28 +++++++++---------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/testcases/kernel/syscalls/ioctl/ioctl_loop01.c b/testcases/kernel/syscalls/ioctl/ioctl_loop01.c index 4ecc93b1e..dd5097f5f 100644 --- a/testcases/kernel/syscalls/ioctl/ioctl_loop01.c +++ b/testcases/kernel/syscalls/ioctl/ioctl_loop01.c @@ -78,21 +78,7 @@ static void check_loop_value(int set_flag, int get_flag, int autoclear_field) static void verify_ioctl_loop(void) { - int ret; - const char *const cmd_parted[] = {"parted", "-s", dev_path, "mklabel", "msdos", "mkpart", - "primary", "ext4", "1M", "10M", NULL}; - - tst_fill_file("test.img", 0, 1024 * 1024, 10); tst_attach_device(dev_path, "test.img"); - - ret = tst_cmd(cmd_parted, NULL, NULL, TST_CMD_PASS_RETVAL); - if (!ret) - parted_sup = 1; - else if (ret == 255) - tst_res(TCONF, "parted binary not installed or failed"); - else - tst_res(TCONF, "parted exited with %i", ret); - attach_flag = 1; TST_ASSERT_INT(partscan_path, 0); @@ -113,10 +99,20 @@ static void verify_ioctl_loop(void) static void setup(void) { + parted_sup = tst_cmd_present("parted"); + + const char *const cmd_parted[] = {"parted", "-s", "test.img", "mklabel", "msdos", "mkpart", + "primary", "ext4", "1M", "10M", NULL}; + dev_num = tst_find_free_loopdev(dev_path, sizeof(dev_path)); if (dev_num < 0) tst_brk(TBROK, "Failed to find free loop device"); + tst_fill_file("test.img", 0, 1024 * 1024, 10); + + if (parted_sup) + SAFE_CMD(cmd_parted, NULL, NULL); + sprintf(partscan_path, "/sys/block/loop%d/loop/partscan", dev_num); sprintf(autoclear_path, "/sys/block/loop%d/loop/autoclear", dev_num); sprintf(backing_path, "/sys/block/loop%d/loop/backing_file", dev_num); @@ -148,5 +144,9 @@ static struct tst_test test = { {"linux-git", "6ac92fb5cdff"}, {} }, + .needs_cmds = (struct tst_cmd[]) { + {.cmd = "parted", .optional = 1}, + {} + }, .needs_tmpdir = 1, }; -- 2.51.0 -- Mailing list info: https://lists.linux.it/listinfo/ltp ^ permalink raw reply related [flat|nested] 100+ messages in thread
* Re: [LTP] [PATCH v4 3/4] ioctl_loop01.c: Add new support .needs_cmds 2025-11-07 0:30 ` [LTP] [PATCH v4 3/4] ioctl_loop01.c: Add new support .needs_cmds Wei Gao via ltp @ 2025-11-07 11:04 ` Petr Vorel 2025-11-08 12:58 ` Wei Gao via ltp 0 siblings, 1 reply; 100+ messages in thread From: Petr Vorel @ 2025-11-07 11:04 UTC (permalink / raw) To: Wei Gao; +Cc: ltp Hi Wei, ... > +++ b/testcases/kernel/syscalls/ioctl/ioctl_loop01.c > @@ -78,21 +78,7 @@ static void check_loop_value(int set_flag, int get_flag, int autoclear_field) > static void verify_ioctl_loop(void) > { > - int ret; > - const char *const cmd_parted[] = {"parted", "-s", dev_path, "mklabel", "msdos", "mkpart", > - "primary", "ext4", "1M", "10M", NULL}; > - ... > static void setup(void) > { > + parted_sup = tst_cmd_present("parted"); > + > + const char *const cmd_parted[] = {"parted", "-s", "test.img", "mklabel", "msdos", "mkpart", > + "primary", "ext4", "1M", "10M", NULL}; > + dev_path => "test.img". With this you're effectively reverting your own fix from ba605cc955 ("ioctl_loop01.c: Use proper device for partitioning"). Why? 'parted' with dev_path immediately fails (haven't found why). But with your patch applied I'm able to trigger again the problem "TBROK: mkfs.vfat failed with exit code 1". Kind regards, Petr -- Mailing list info: https://lists.linux.it/listinfo/ltp ^ permalink raw reply [flat|nested] 100+ messages in thread
* Re: [LTP] [PATCH v4 3/4] ioctl_loop01.c: Add new support .needs_cmds 2025-11-07 11:04 ` Petr Vorel @ 2025-11-08 12:58 ` Wei Gao via ltp 0 siblings, 0 replies; 100+ messages in thread From: Wei Gao via ltp @ 2025-11-08 12:58 UTC (permalink / raw) To: Petr Vorel; +Cc: ltp On Fri, Nov 07, 2025 at 12:04:21PM +0100, Petr Vorel wrote: > Hi Wei, > > ... > > +++ b/testcases/kernel/syscalls/ioctl/ioctl_loop01.c > > @@ -78,21 +78,7 @@ static void check_loop_value(int set_flag, int get_flag, int autoclear_field) > > > static void verify_ioctl_loop(void) > > { > > - int ret; > > - const char *const cmd_parted[] = {"parted", "-s", dev_path, "mklabel", "msdos", "mkpart", > > - "primary", "ext4", "1M", "10M", NULL}; > > - > ... > > static void setup(void) > > { > > + parted_sup = tst_cmd_present("parted"); > > + > > + const char *const cmd_parted[] = {"parted", "-s", "test.img", "mklabel", "msdos", "mkpart", > > + "primary", "ext4", "1M", "10M", NULL}; > > + > > dev_path => "test.img". With this you're effectively reverting your own fix from > ba605cc955 ("ioctl_loop01.c: Use proper device for partitioning"). Why? > Sorry, my mistake. The root cause is that patchv2 was created before the date associated with commit ba605cc955, so change base patchv2 without rebase trigger this update. patchv2: https://patchwork.ozlabs.org/project/ltp/patch/20250928232708.24007-3-wegao@suse.com/ > 'parted' with dev_path immediately fails (haven't found why). But with your > patch applied I'm able to trigger again the problem "TBROK: mkfs.vfat failed > with exit code 1". Because missing tst_attach_device for /loop/devX before execute "parted", i will fix that in next version. tst_attach_device(dev_path, "test.img"); > > Kind regards, > Petr -- Mailing list info: https://lists.linux.it/listinfo/ltp ^ permalink raw reply [flat|nested] 100+ messages in thread
* [LTP] [PATCH v4 4/4] shell_loader_cmd.sh: New test case check needs_cmds 2025-11-07 0:30 ` [LTP] [PATCH v4 0/4] new cmd support option for needs_cmds Wei Gao via ltp ` (2 preceding siblings ...) 2025-11-07 0:30 ` [LTP] [PATCH v4 3/4] ioctl_loop01.c: Add new support .needs_cmds Wei Gao via ltp @ 2025-11-07 0:30 ` Wei Gao via ltp 2025-11-07 11:41 ` Petr Vorel 2025-11-10 2:47 ` [LTP] [PATCH v5 0/3] new cmd support option for needs_cmds Wei Gao via ltp 4 siblings, 1 reply; 100+ messages in thread From: Wei Gao via ltp @ 2025-11-07 0:30 UTC (permalink / raw) To: ltp Suggested-by: Petr Vorel <pvorel@suse.cz> Signed-off-by: Wei Gao <wegao@suse.com> --- testcases/lib/run_tests.sh | 1 + testcases/lib/tests/shell_loader_cmd.sh | 24 ++++++++++++++++++++++++ 2 files changed, 25 insertions(+) create mode 100755 testcases/lib/tests/shell_loader_cmd.sh diff --git a/testcases/lib/run_tests.sh b/testcases/lib/run_tests.sh index 5c309bbeb..24ac81a44 100755 --- a/testcases/lib/run_tests.sh +++ b/testcases/lib/run_tests.sh @@ -6,6 +6,7 @@ shell_loader.sh shell_loader_all_filesystems.sh shell_loader_c_child.sh shell_loader_filesystems.sh +shell_loader_cmd.sh shell_loader_kconfigs.sh shell_loader_supported_archs.sh shell_loader_tcnt.sh diff --git a/testcases/lib/tests/shell_loader_cmd.sh b/testcases/lib/tests/shell_loader_cmd.sh new file mode 100755 index 000000000..a05562089 --- /dev/null +++ b/testcases/lib/tests/shell_loader_cmd.sh @@ -0,0 +1,24 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (c) 2025 Wei Gao <wegao@suse.cz> +# +# --- +# env +# { +# "needs_cmds": [ +# { +# "cmd": "ls", +# "optional": 1 +# } +# ] +# } +# --- + +. tst_loader.sh + +tst_test() +{ + tst_res TPASS "We are running with needs_cmds" +} + +. tst_run.sh -- 2.51.0 -- Mailing list info: https://lists.linux.it/listinfo/ltp ^ permalink raw reply related [flat|nested] 100+ messages in thread
* Re: [LTP] [PATCH v4 4/4] shell_loader_cmd.sh: New test case check needs_cmds 2025-11-07 0:30 ` [LTP] [PATCH v4 4/4] shell_loader_cmd.sh: New test case check needs_cmds Wei Gao via ltp @ 2025-11-07 11:41 ` Petr Vorel 0 siblings, 0 replies; 100+ messages in thread From: Petr Vorel @ 2025-11-07 11:41 UTC (permalink / raw) To: Wei Gao; +Cc: ltp Hi Wei, Reviewed-by: Petr Vorel <pvorel@suse.cz> > --- /dev/null > +++ b/testcases/lib/tests/shell_loader_cmd.sh > @@ -0,0 +1,24 @@ > +#!/bin/sh > +# SPDX-License-Identifier: GPL-2.0-or-later > +# Copyright (c) 2025 Wei Gao <wegao@suse.cz> > +# > +# --- > +# env > +# { > +# "needs_cmds": [ > +# { > +# "cmd": "ls", > +# "optional": 1 > +# } Ideally we would also some test with an expression with version on "cmd", e.g. "mkfs.ext4 >= 1.0.0" to make sure it's correctly handled. I know it's just passing to the C library, but just for sure. Kind regards, Petr > +# ] > +# } > +# --- > + > +. tst_loader.sh > + > +tst_test() > +{ > + tst_res TPASS "We are running with needs_cmds" > +} -- Mailing list info: https://lists.linux.it/listinfo/ltp ^ permalink raw reply [flat|nested] 100+ messages in thread
* [LTP] [PATCH v5 0/3] new cmd support option for needs_cmds 2025-11-07 0:30 ` [LTP] [PATCH v4 0/4] new cmd support option for needs_cmds Wei Gao via ltp ` (3 preceding siblings ...) 2025-11-07 0:30 ` [LTP] [PATCH v4 4/4] shell_loader_cmd.sh: New test case check needs_cmds Wei Gao via ltp @ 2025-11-10 2:47 ` Wei Gao via ltp 2025-11-10 2:47 ` [LTP] [PATCH v5 1/3] lib: Add support option for .needs_cmds Wei Gao via ltp ` (3 more replies) 4 siblings, 4 replies; 100+ messages in thread From: Wei Gao via ltp @ 2025-11-10 2:47 UTC (permalink / raw) To: ltp v4->v5: 1.Remove https://patchwork.ozlabs.org/project/ltp/patch/20251107003041.28929-2-wegao@suse.com/ since already rewritten by Petr's another patch. 2.Fix ioctl_loop01.c rebase issue. 3.Add expression check such as "mkfs.ext4 >= 1.0.0" into test case. Wei Gao (3): lib: Add support option for .needs_cmds ioctl_loop01.c: Add new support .needs_cmds shell_loader_cmd.sh: New test case check needs_cmds include/tst_cmd.h | 13 ++++ include/tst_test.h | 16 ++++- lib/newlib_tests/tst_needs_cmds01.c | 16 ++--- lib/newlib_tests/tst_needs_cmds02.c | 6 +- lib/newlib_tests/tst_needs_cmds03.c | 6 +- lib/newlib_tests/tst_needs_cmds04.c | 6 +- lib/newlib_tests/tst_needs_cmds05.c | 6 +- lib/newlib_tests/tst_needs_cmds06.c | 6 +- lib/newlib_tests/tst_needs_cmds07.c | 6 +- lib/newlib_tests/tst_needs_cmds08.c | 8 +-- lib/tst_test.c | 22 +++++-- testcases/kernel/device-drivers/zram/zram03.c | 8 +-- testcases/kernel/fs/squashfs/squashfs01.c | 6 +- testcases/kernel/security/aslr/aslr01.c | 6 +- testcases/kernel/syscalls/add_key/add_key05.c | 10 +-- .../kernel/syscalls/fanotify/fanotify22.c | 6 +- testcases/kernel/syscalls/ioctl/ioctl09.c | 6 +- .../kernel/syscalls/ioctl/ioctl_loop01.c | 34 +++++------ testcases/kernel/syscalls/madvise/madvise11.c | 8 +-- .../kernel/syscalls/quotactl/quotactl01.c | 6 +- .../kernel/syscalls/quotactl/quotactl04.c | 6 +- .../kernel/syscalls/quotactl/quotactl06.c | 6 +- .../kernel/syscalls/quotactl/quotactl08.c | 6 +- .../kernel/syscalls/quotactl/quotactl09.c | 6 +- testcases/kernel/syscalls/statx/statx05.c | 8 +-- testcases/kernel/syscalls/statx/statx07.c | 6 +- testcases/kernel/syscalls/statx/statx09.c | 6 +- testcases/lib/run_tests.sh | 1 + testcases/lib/tests/shell_loader_cmd.sh | 28 +++++++++ testcases/lib/tst_run_shell.c | 61 ++++++++++++++++++- 30 files changed, 231 insertions(+), 104 deletions(-) create mode 100755 testcases/lib/tests/shell_loader_cmd.sh -- 2.51.0 -- Mailing list info: https://lists.linux.it/listinfo/ltp ^ permalink raw reply [flat|nested] 100+ messages in thread
* [LTP] [PATCH v5 1/3] lib: Add support option for .needs_cmds 2025-11-10 2:47 ` [LTP] [PATCH v5 0/3] new cmd support option for needs_cmds Wei Gao via ltp @ 2025-11-10 2:47 ` Wei Gao via ltp 2025-11-11 11:06 ` Petr Vorel 2025-12-12 10:30 ` Cyril Hrubis 2025-11-10 2:47 ` [LTP] [PATCH v5 2/3] ioctl_loop01.c: Add new support .needs_cmds Wei Gao via ltp ` (2 subsequent siblings) 3 siblings, 2 replies; 100+ messages in thread From: Wei Gao via ltp @ 2025-11-10 2:47 UTC (permalink / raw) To: ltp Suggested-by: Cyril Hrubis <chrubis@suse.cz> Signed-off-by: Wei Gao <wegao@suse.com> --- include/tst_cmd.h | 13 ++++ include/tst_test.h | 16 ++++- lib/newlib_tests/tst_needs_cmds01.c | 16 ++--- lib/newlib_tests/tst_needs_cmds02.c | 6 +- lib/newlib_tests/tst_needs_cmds03.c | 6 +- lib/newlib_tests/tst_needs_cmds04.c | 6 +- lib/newlib_tests/tst_needs_cmds05.c | 6 +- lib/newlib_tests/tst_needs_cmds06.c | 6 +- lib/newlib_tests/tst_needs_cmds07.c | 6 +- lib/newlib_tests/tst_needs_cmds08.c | 8 +-- lib/tst_test.c | 22 +++++-- testcases/kernel/device-drivers/zram/zram03.c | 8 +-- testcases/kernel/fs/squashfs/squashfs01.c | 6 +- testcases/kernel/security/aslr/aslr01.c | 6 +- testcases/kernel/syscalls/add_key/add_key05.c | 10 +-- .../kernel/syscalls/fanotify/fanotify22.c | 6 +- testcases/kernel/syscalls/ioctl/ioctl09.c | 6 +- testcases/kernel/syscalls/madvise/madvise11.c | 8 +-- .../kernel/syscalls/quotactl/quotactl01.c | 6 +- .../kernel/syscalls/quotactl/quotactl04.c | 6 +- .../kernel/syscalls/quotactl/quotactl06.c | 6 +- .../kernel/syscalls/quotactl/quotactl08.c | 6 +- .../kernel/syscalls/quotactl/quotactl09.c | 6 +- testcases/kernel/syscalls/statx/statx05.c | 8 +-- testcases/kernel/syscalls/statx/statx07.c | 6 +- testcases/kernel/syscalls/statx/statx09.c | 6 +- testcases/lib/tst_run_shell.c | 61 ++++++++++++++++++- 27 files changed, 185 insertions(+), 87 deletions(-) diff --git a/include/tst_cmd.h b/include/tst_cmd.h index cf6382955..2203241c5 100644 --- a/include/tst_cmd.h +++ b/include/tst_cmd.h @@ -19,6 +19,19 @@ enum tst_cmd_flags { TST_CMD_TCONF_ON_MISSING = 2, }; +/** + * struct tst_cmd - Provides details about a command struct needed by LTP test. + * @cmd: The name of the command. + * @optional: A flag indicating if the command is optional. + * @present: A flag indicating if the command was found at runtime. This is an output + * parameter, set by the LTP library during the test setup. + */ +struct tst_cmd { + const char *cmd; + unsigned int optional:1; + unsigned int present:1; +}; + /* * vfork() + execvp() specified program. * diff --git a/include/tst_test.h b/include/tst_test.h index 9c21c1728..9305cf39d 100644 --- a/include/tst_test.h +++ b/include/tst_test.h @@ -524,7 +524,7 @@ struct tst_fs { * * @tags: A {} terminated array of test tags. See struct tst_tag for details. * - * @needs_cmds: A NULL terminated array of commands required for the test to run. + * @needs_cmds: A NULL terminated array of struct tst_cmd required for the test to run. * * @needs_cgroup_ver: If set the test will run only if the specified cgroup * version is present on the system. @@ -617,7 +617,7 @@ struct tst_fs { const struct tst_tag *tags; - const char *const *needs_cmds; + struct tst_cmd *needs_cmds; const enum tst_cg_ver needs_cgroup_ver; @@ -721,6 +721,18 @@ int tst_creat_unlinked(const char *path, int flags, mode_t mode); */ const char *tst_get_tmpdir_root(void); +/** + * tst_cmd_present() - Check if a command is present + * @cmd: The name of the command to check for. + * + * This function iterates through the &tst_test->needs_cmds array. It compares + * the given command name with each entry in the array and returns the 'present' + * flag for the matching command. + * + * Return: `true` if the command is present, `false` otherwise. + */ +bool tst_cmd_present(const char *cmd); + /* * Validates exit status of child processes */ diff --git a/lib/newlib_tests/tst_needs_cmds01.c b/lib/newlib_tests/tst_needs_cmds01.c index 777c69505..6ab1145d1 100644 --- a/lib/newlib_tests/tst_needs_cmds01.c +++ b/lib/newlib_tests/tst_needs_cmds01.c @@ -12,13 +12,13 @@ static void do_test(void) static struct tst_test test = { .test_all = do_test, - .needs_cmds = (const char *[]) { - "mkfs.ext4", - "mkfs.ext4 >= 1.0.0", - "mkfs.ext4 <= 2.0.0", - "mkfs.ext4 != 2.0.0", - "mkfs.ext4 > 1.0.0", - "mkfs.ext4 < 2.0.0", - NULL + .needs_cmds = (struct tst_cmd[]) { + {.cmd = "mkfs.ext4", .optional = 1}, + {.cmd = "mkfs.ext4 >= 1.0.0", .optional = 0}, + {.cmd = "mkfs.ext4 <= 2.0.0"}, + {.cmd = "mkfs.ext4 != 2.0.0"}, + {.cmd = "mkfs.ext4 > 1.0.0"}, + {.cmd = "mkfs.ext4 < 2.0.0"}, + {} } }; diff --git a/lib/newlib_tests/tst_needs_cmds02.c b/lib/newlib_tests/tst_needs_cmds02.c index 455a275ea..f1d6105c2 100644 --- a/lib/newlib_tests/tst_needs_cmds02.c +++ b/lib/newlib_tests/tst_needs_cmds02.c @@ -16,8 +16,8 @@ static void do_test(void) static struct tst_test test = { .test_all = do_test, - .needs_cmds = (const char *[]) { - "mkfs.ext45 >= 1.43.0", - NULL + .needs_cmds = (struct tst_cmd[]) { + {.cmd = "mkfs.ext45 >= 1.43.0"}, + {} } }; diff --git a/lib/newlib_tests/tst_needs_cmds03.c b/lib/newlib_tests/tst_needs_cmds03.c index bdc1cdf6a..ac5f368e2 100644 --- a/lib/newlib_tests/tst_needs_cmds03.c +++ b/lib/newlib_tests/tst_needs_cmds03.c @@ -16,8 +16,8 @@ static void do_test(void) static struct tst_test test = { .test_all = do_test, - .needs_cmds = (const char *[]) { - "mkfs.ext4 ! 1.43.0", - NULL + .needs_cmds = (struct tst_cmd[]) { + {.cmd = "mkfs.ext4 ! 1.43.0"}, + {} } }; diff --git a/lib/newlib_tests/tst_needs_cmds04.c b/lib/newlib_tests/tst_needs_cmds04.c index de10b8f3e..2aea51772 100644 --- a/lib/newlib_tests/tst_needs_cmds04.c +++ b/lib/newlib_tests/tst_needs_cmds04.c @@ -16,8 +16,8 @@ static void do_test(void) static struct tst_test test = { .test_all = do_test, - .needs_cmds = (const char *[]) { - "mkfs.ext4 > 1.43", - NULL + .needs_cmds = (struct tst_cmd[]) { + {.cmd = "mkfs.ext4 > 1.43"}, + {} } }; diff --git a/lib/newlib_tests/tst_needs_cmds05.c b/lib/newlib_tests/tst_needs_cmds05.c index c3b2b3b9a..969d4e2f5 100644 --- a/lib/newlib_tests/tst_needs_cmds05.c +++ b/lib/newlib_tests/tst_needs_cmds05.c @@ -16,8 +16,8 @@ static void do_test(void) static struct tst_test test = { .test_all = do_test, - .needs_cmds = (const char *[]) { - "mkfs.ext4 > 1.43.0-1", - NULL + .needs_cmds = (struct tst_cmd[]) { + {.cmd = "mkfs.ext4 > 1.43.0-1"}, + {} } }; diff --git a/lib/newlib_tests/tst_needs_cmds06.c b/lib/newlib_tests/tst_needs_cmds06.c index 40b1cf09c..91470ccf9 100644 --- a/lib/newlib_tests/tst_needs_cmds06.c +++ b/lib/newlib_tests/tst_needs_cmds06.c @@ -16,8 +16,8 @@ static void do_test(void) static struct tst_test test = { .test_all = do_test, - .needs_cmds = (const char *[]) { - "mkfs.ext4 > 1.43.0 2", - NULL + .needs_cmds = (struct tst_cmd[]) { + {.cmd = "mkfs.ext4 > 1.43.0 2"}, + {} } }; diff --git a/lib/newlib_tests/tst_needs_cmds07.c b/lib/newlib_tests/tst_needs_cmds07.c index d0b4ce2ff..371bbdc1b 100644 --- a/lib/newlib_tests/tst_needs_cmds07.c +++ b/lib/newlib_tests/tst_needs_cmds07.c @@ -16,8 +16,8 @@ static void do_test(void) static struct tst_test test = { .test_all = do_test, - .needs_cmds = (const char *[]) { - "mkfs.ext45", - NULL + .needs_cmds = (struct tst_cmd[]) { + {.cmd = "mkfs.ext45"}, + {} } }; diff --git a/lib/newlib_tests/tst_needs_cmds08.c b/lib/newlib_tests/tst_needs_cmds08.c index 38df2ef6d..412f9f293 100644 --- a/lib/newlib_tests/tst_needs_cmds08.c +++ b/lib/newlib_tests/tst_needs_cmds08.c @@ -18,9 +18,9 @@ static void do_test(void) static struct tst_test test = { .test_all = do_test, - .needs_cmds = (const char *[]) { - "mkfs.xfs", - "mkfs.xfs >= 4.20.0", - NULL + .needs_cmds = (struct tst_cmd[]) { + {.cmd = "mkfs.xfs"}, + {.cmd = "mkfs.xfs >= 4.20.0"}, + {} } }; diff --git a/lib/tst_test.c b/lib/tst_test.c index da5314c50..67553f65d 100644 --- a/lib/tst_test.c +++ b/lib/tst_test.c @@ -1365,6 +1365,19 @@ static const char *default_fs_type(void) return tst_dev_fs_type(); } +bool tst_cmd_present(const char *cmd) +{ + struct tst_cmd *pcmd = tst_test->needs_cmds; + + while (pcmd->cmd) { + if (!strcmp(pcmd->cmd, cmd)) + return pcmd->present; + + pcmd++; + } + return false; +} + static void do_setup(int argc, char *argv[]) { char *tdebug_env = getenv("LTP_ENABLE_DEBUG"); @@ -1439,11 +1452,12 @@ static void do_setup(int argc, char *argv[]) tst_brk(TCONF, "%dbit ABI is not supported", tst_test->needs_abi_bits); if (tst_test->needs_cmds) { - const char *cmd; - int i; + struct tst_cmd *pcmd = tst_test->needs_cmds; - for (i = 0; (cmd = tst_test->needs_cmds[i]); ++i) - tst_check_cmd(cmd, 1); + while (pcmd->cmd) { + pcmd->present = tst_check_cmd(pcmd->cmd, !pcmd->optional) ? 1 : 0; + pcmd++; + } } if (tst_test->needs_drivers) { diff --git a/testcases/kernel/device-drivers/zram/zram03.c b/testcases/kernel/device-drivers/zram/zram03.c index 8cf26de4c..4dcf23b4e 100644 --- a/testcases/kernel/device-drivers/zram/zram03.c +++ b/testcases/kernel/device-drivers/zram/zram03.c @@ -240,9 +240,9 @@ static struct tst_test test = { "zram", NULL }, - .needs_cmds = (const char *[]) { - "modprobe", - "rmmod", - NULL + .needs_cmds = (struct tst_cmd[]) { + {.cmd = "modprobe"}, + {.cmd = "rmmod"}, + {} } }; diff --git a/testcases/kernel/fs/squashfs/squashfs01.c b/testcases/kernel/fs/squashfs/squashfs01.c index fbcb76582..7a548d62c 100644 --- a/testcases/kernel/fs/squashfs/squashfs01.c +++ b/testcases/kernel/fs/squashfs/squashfs01.c @@ -102,9 +102,9 @@ static struct tst_test test = { .needs_root = 1, .needs_device = 1, .dev_min_size = 1, - .needs_cmds = (const char *const []) { - "mksquashfs", - NULL + .needs_cmds = (struct tst_cmd[]) { + {.cmd = "mksquashfs"}, + {} }, .needs_drivers = (const char *const []) { "squashfs", diff --git a/testcases/kernel/security/aslr/aslr01.c b/testcases/kernel/security/aslr/aslr01.c index 6a396e29d..e6feb2d3c 100644 --- a/testcases/kernel/security/aslr/aslr01.c +++ b/testcases/kernel/security/aslr/aslr01.c @@ -277,8 +277,8 @@ static struct tst_test test = { "CONFIG_HAVE_ARCH_MMAP_RND_BITS=y", NULL }, - .needs_cmds = (const char *[]) { - "ldd", - NULL + .needs_cmds = (struct tst_cmd[]) { + {.cmd = "ldd"}, + {} }, }; diff --git a/testcases/kernel/syscalls/add_key/add_key05.c b/testcases/kernel/syscalls/add_key/add_key05.c index c9a2f840e..b51a84b97 100644 --- a/testcases/kernel/syscalls/add_key/add_key05.c +++ b/testcases/kernel/syscalls/add_key/add_key05.c @@ -231,11 +231,11 @@ static struct tst_test test = { {&user_buf, .size = 64}, {} }, - .needs_cmds = (const char *const []) { - "useradd", - "userdel", - "groupdel", - NULL + .needs_cmds = (struct tst_cmd[]) { + {.cmd = "useradd"}, + {.cmd = "userdel"}, + {.cmd = "groupdel"}, + {} }, .tags = (const struct tst_tag[]) { {"linux-git", "a08bf91ce28"}, diff --git a/testcases/kernel/syscalls/fanotify/fanotify22.c b/testcases/kernel/syscalls/fanotify/fanotify22.c index 357e74dbc..6578474a7 100644 --- a/testcases/kernel/syscalls/fanotify/fanotify22.c +++ b/testcases/kernel/syscalls/fanotify/fanotify22.c @@ -327,9 +327,9 @@ static struct tst_test test = { {"linux-git", "76486b104168"}, {} }, - .needs_cmds = (const char *[]) { - "debugfs", - NULL + .needs_cmds = (struct tst_cmd[]) { + {.cmd = "debugfs"}, + {} } }; diff --git a/testcases/kernel/syscalls/ioctl/ioctl09.c b/testcases/kernel/syscalls/ioctl/ioctl09.c index 262d6fcab..737aee680 100644 --- a/testcases/kernel/syscalls/ioctl/ioctl09.c +++ b/testcases/kernel/syscalls/ioctl/ioctl09.c @@ -108,9 +108,9 @@ static struct tst_test test = { "loop", NULL }, - .needs_cmds = (const char *const []) { - "parted", - NULL + .needs_cmds = (struct tst_cmd[]) { + {.cmd = "parted"}, + {} }, .needs_tmpdir = 1, }; diff --git a/testcases/kernel/syscalls/madvise/madvise11.c b/testcases/kernel/syscalls/madvise/madvise11.c index 422589f5b..73d2d4294 100644 --- a/testcases/kernel/syscalls/madvise/madvise11.c +++ b/testcases/kernel/syscalls/madvise/madvise11.c @@ -421,10 +421,10 @@ static struct tst_test test = { HW_MODULE, NULL }, - .needs_cmds = (const char *[]) { - "modprobe", - "rmmod", - NULL + .needs_cmds = (struct tst_cmd[]) { + {.cmd = "modprobe"}, + {.cmd = "rmmod"}, + {} }, .needs_kconfigs = (const char *[]) { "CONFIG_MEMORY_FAILURE=y", diff --git a/testcases/kernel/syscalls/quotactl/quotactl01.c b/testcases/kernel/syscalls/quotactl/quotactl01.c index 9dcf74ceb..3091ac5bf 100644 --- a/testcases/kernel/syscalls/quotactl/quotactl01.c +++ b/testcases/kernel/syscalls/quotactl/quotactl01.c @@ -223,9 +223,9 @@ static struct tst_test test = { {} }, .mntpoint = MNTPOINT, - .needs_cmds = (const char *const []) { - "quotacheck", - NULL + .needs_cmds = (struct tst_cmd[]) { + {.cmd = "quotacheck"}, + {} }, .setup = setup, .cleanup = cleanup, diff --git a/testcases/kernel/syscalls/quotactl/quotactl04.c b/testcases/kernel/syscalls/quotactl/quotactl04.c index d2d7b3f3e..a70903330 100644 --- a/testcases/kernel/syscalls/quotactl/quotactl04.c +++ b/testcases/kernel/syscalls/quotactl/quotactl04.c @@ -165,8 +165,8 @@ static struct tst_test test = { }, .mntpoint = MNTPOINT, .test_variants = QUOTACTL_SYSCALL_VARIANTS, - .needs_cmds = (const char *[]) { - "mkfs.ext4 >= 1.43.0", - NULL + .needs_cmds = (struct tst_cmd[]) { + {.cmd = "mkfs.ext4 >= 1.43.0"}, + {} } }; diff --git a/testcases/kernel/syscalls/quotactl/quotactl06.c b/testcases/kernel/syscalls/quotactl/quotactl06.c index 110a3aa9b..333f5720d 100644 --- a/testcases/kernel/syscalls/quotactl/quotactl06.c +++ b/testcases/kernel/syscalls/quotactl/quotactl06.c @@ -226,9 +226,9 @@ static struct tst_test test = { }, .mntpoint = MNTPOINT, .mount_device = 1, - .needs_cmds = (const char *const []) { - "quotacheck", - NULL + .needs_cmds = (struct tst_cmd[]) { + {.cmd = "quotacheck"}, + {} }, .needs_root = 1, .test_variants = QUOTACTL_FMT_VARIANTS, diff --git a/testcases/kernel/syscalls/quotactl/quotactl08.c b/testcases/kernel/syscalls/quotactl/quotactl08.c index 63087345f..ce7a8b008 100644 --- a/testcases/kernel/syscalls/quotactl/quotactl08.c +++ b/testcases/kernel/syscalls/quotactl/quotactl08.c @@ -220,8 +220,8 @@ static struct tst_test test = { .setup = setup, .cleanup = cleanup, .test_variants = QUOTACTL_SYSCALL_VARIANTS, - .needs_cmds = (const char *[]) { - "mkfs.ext4 >= 1.43.0", - NULL + .needs_cmds = (struct tst_cmd[]) { + {.cmd = "mkfs.ext4 >= 1.43.0"}, + {} } }; diff --git a/testcases/kernel/syscalls/quotactl/quotactl09.c b/testcases/kernel/syscalls/quotactl/quotactl09.c index 673666347..fd6629c0c 100644 --- a/testcases/kernel/syscalls/quotactl/quotactl09.c +++ b/testcases/kernel/syscalls/quotactl/quotactl09.c @@ -185,8 +185,8 @@ static struct tst_test test = { .mount_device = 1, .needs_root = 1, .test_variants = QUOTACTL_SYSCALL_VARIANTS, - .needs_cmds = (const char *[]) { - "mkfs.ext4 >= 1.43.0", - NULL + .needs_cmds = (struct tst_cmd[]) { + {.cmd = "mkfs.ext4 >= 1.43.0"}, + {} } }; diff --git a/testcases/kernel/syscalls/statx/statx05.c b/testcases/kernel/syscalls/statx/statx05.c index 2a4603226..07b5e7b94 100644 --- a/testcases/kernel/syscalls/statx/statx05.c +++ b/testcases/kernel/syscalls/statx/statx05.c @@ -123,9 +123,9 @@ static struct tst_test test = { {.type = "ext4"}, {} }, - .needs_cmds = (const char *[]) { - "mkfs.ext4 >= 1.43.0", - "e4crypt", - NULL + .needs_cmds = (struct tst_cmd[]) { + {.cmd = "mkfs.ext4 >= 1.43.0"}, + {.cmd = "e4crypt"}, + {} } }; diff --git a/testcases/kernel/syscalls/statx/statx07.c b/testcases/kernel/syscalls/statx/statx07.c index bab64591f..755644cf9 100644 --- a/testcases/kernel/syscalls/statx/statx07.c +++ b/testcases/kernel/syscalls/statx/statx07.c @@ -171,8 +171,8 @@ static struct tst_test test = { {} }, .needs_root = 1, - .needs_cmds = (const char *[]) { - "exportfs", - NULL + .needs_cmds = (struct tst_cmd[]) { + {.cmd = "exportfs"}, + {} } }; diff --git a/testcases/kernel/syscalls/statx/statx09.c b/testcases/kernel/syscalls/statx/statx09.c index ee4be4250..8838d5450 100644 --- a/testcases/kernel/syscalls/statx/statx09.c +++ b/testcases/kernel/syscalls/statx/statx09.c @@ -162,8 +162,8 @@ static struct tst_test test = { "CONFIG_FS_VERITY", NULL }, - .needs_cmds = (const char *[]) { - "mkfs.ext4 >= 1.45.2", - NULL + .needs_cmds = (struct tst_cmd[]) { + {.cmd = "mkfs.ext4 >= 1.45.2"}, + {} } }; diff --git a/testcases/lib/tst_run_shell.c b/testcases/lib/tst_run_shell.c index 7a446e004..6def36dcb 100644 --- a/testcases/lib/tst_run_shell.c +++ b/testcases/lib/tst_run_shell.c @@ -175,6 +175,23 @@ static ujson_obj fs_obj = { .attr_cnt = UJSON_ARRAY_SIZE(fs_attrs), }; +enum cmd_ids { + CMD, + OPTIONAL, + PRESENT, +}; + +static ujson_obj_attr cmd_attrs[] = { + UJSON_OBJ_ATTR_IDX(CMD, "cmd", UJSON_STR), + UJSON_OBJ_ATTR_IDX(OPTIONAL, "optional", UJSON_INT), + UJSON_OBJ_ATTR_IDX(PRESENT, "present", UJSON_INT), +}; + +static ujson_obj cmd_obj = { + .attrs = cmd_attrs, + .attr_cnt = UJSON_ARRAY_SIZE(cmd_attrs), +}; + static int parse_mnt_flags(ujson_reader *reader, ujson_val *val) { int ret = 0; @@ -252,6 +269,48 @@ static struct tst_fs *parse_filesystems(ujson_reader *reader, ujson_val *val) return ret; } +static struct tst_cmd *parse_cmds(ujson_reader *reader, ujson_val *val) +{ + unsigned int i = 0, cnt = 0; + struct tst_cmd *ret; + + ujson_reader_state state = ujson_reader_state_save(reader); + + UJSON_ARR_FOREACH(reader, val) { + if (val->type != UJSON_OBJ) { + ujson_err(reader, "Expected object!"); + return NULL; + } + ujson_obj_skip(reader); + cnt++; + } + + ujson_reader_state_load(reader, state); + + ret = SAFE_MALLOC(sizeof(struct tst_cmd) * (cnt + 1)); + memset(&ret[cnt], 0, sizeof(ret[cnt])); + + UJSON_ARR_FOREACH(reader, val) { + UJSON_OBJ_FOREACH_FILTER(reader, val, &cmd_obj, ujson_empty_obj) { + switch ((enum cmd_ids)val->idx) { + case CMD: + ret[i].cmd = strdup(val->val_str); + break; + case OPTIONAL: + ret[i].optional = val->val_int; + break; + case PRESENT: + ret[i].present = val->val_int; + break; + } + } + + i++; + } + + return ret; +} + static struct tst_tag *parse_tags(ujson_reader *reader, ujson_val *val) { unsigned int i = 0, cnt = 0; @@ -440,7 +499,7 @@ static void parse_metadata(void) ujson_err(&reader, "ABI bits must be 32 or 64"); break; case NEEDS_CMDS: - test.needs_cmds = parse_strarr(&reader, &val); + test.needs_cmds = parse_cmds(&reader, &val); break; case NEEDS_DEVFS: test.needs_devfs = val.val_bool; -- 2.51.0 -- Mailing list info: https://lists.linux.it/listinfo/ltp ^ permalink raw reply related [flat|nested] 100+ messages in thread
* Re: [LTP] [PATCH v5 1/3] lib: Add support option for .needs_cmds 2025-11-10 2:47 ` [LTP] [PATCH v5 1/3] lib: Add support option for .needs_cmds Wei Gao via ltp @ 2025-11-11 11:06 ` Petr Vorel 2025-12-12 10:30 ` Cyril Hrubis 1 sibling, 0 replies; 100+ messages in thread From: Petr Vorel @ 2025-11-11 11:06 UTC (permalink / raw) To: Wei Gao; +Cc: ltp Hi Wei, ... > /* > * vfork() + execvp() specified program. > * > diff --git a/include/tst_test.h b/include/tst_test.h > index 9c21c1728..9305cf39d 100644 > --- a/include/tst_test.h > +++ b/include/tst_test.h > @@ -524,7 +524,7 @@ struct tst_fs { > * > * @tags: A {} terminated array of test tags. See struct tst_tag for details. > * > - * @needs_cmds: A NULL terminated array of commands required for the test to run. > + * @needs_cmds: A NULL terminated array of struct tst_cmd required for the test to run. Please use :ref:`...` formatting to make struct clickable. * @needs_cmds: A NULL terminated array of :ref:`struct tst_cmd` required for * the test to run. > * > * @needs_cgroup_ver: If set the test will run only if the specified cgroup > * version is present on the system. > @@ -617,7 +617,7 @@ struct tst_fs { > const struct tst_tag *tags; > - const char *const *needs_cmds; > + struct tst_cmd *needs_cmds; > const enum tst_cg_ver needs_cgroup_ver; > @@ -721,6 +721,18 @@ int tst_creat_unlinked(const char *path, int flags, mode_t mode); > */ > const char *tst_get_tmpdir_root(void); > +/** > + * tst_cmd_present() - Check if a command is present > + * @cmd: The name of the command to check for. > + * > + * This function iterates through the &tst_test->needs_cmds array. It compares > + * the given command name with each entry in the array and returns the 'present' And here please again make it clickable tst_cmd->present. It really helps people to click and see what you mean by 'present'. * the given command name with each entry in the array and returns the * &tst_cmd->present flag for the matching command. If this is the only part to change, it can be done before merge. > + * flag for the matching command. > + * > + * Return: `true` if the command is present, `false` otherwise. > + */ > +bool tst_cmd_present(const char *cmd); Reviewed-by: Petr Vorel <pvorel@suse.cz> Kind regards, Petr -- Mailing list info: https://lists.linux.it/listinfo/ltp ^ permalink raw reply [flat|nested] 100+ messages in thread
* Re: [LTP] [PATCH v5 1/3] lib: Add support option for .needs_cmds 2025-11-10 2:47 ` [LTP] [PATCH v5 1/3] lib: Add support option for .needs_cmds Wei Gao via ltp 2025-11-11 11:06 ` Petr Vorel @ 2025-12-12 10:30 ` Cyril Hrubis 2025-12-12 11:16 ` Petr Vorel 1 sibling, 1 reply; 100+ messages in thread From: Cyril Hrubis @ 2025-12-12 10:30 UTC (permalink / raw) To: Wei Gao; +Cc: ltp Hi! > diff --git a/lib/tst_test.c b/lib/tst_test.c > index da5314c50..67553f65d 100644 > --- a/lib/tst_test.c > +++ b/lib/tst_test.c > @@ -1365,6 +1365,19 @@ static const char *default_fs_type(void) > return tst_dev_fs_type(); > } > > +bool tst_cmd_present(const char *cmd) > +{ > + struct tst_cmd *pcmd = tst_test->needs_cmds; > + > + while (pcmd->cmd) { > + if (!strcmp(pcmd->cmd, cmd)) > + return pcmd->present; > + > + pcmd++; > + } > + return false; Once again, we should tst_brk(TBROK, "Unexpected command '%s'", cmd) here since we asked for something that we haven't checked for! -- Cyril Hrubis chrubis@suse.cz -- Mailing list info: https://lists.linux.it/listinfo/ltp ^ permalink raw reply [flat|nested] 100+ messages in thread
* Re: [LTP] [PATCH v5 1/3] lib: Add support option for .needs_cmds 2025-12-12 10:30 ` Cyril Hrubis @ 2025-12-12 11:16 ` Petr Vorel 2025-12-15 7:33 ` Wei Gao via ltp 0 siblings, 1 reply; 100+ messages in thread From: Petr Vorel @ 2025-12-12 11:16 UTC (permalink / raw) To: Cyril Hrubis; +Cc: ltp > Hi! > > diff --git a/lib/tst_test.c b/lib/tst_test.c > > index da5314c50..67553f65d 100644 > > --- a/lib/tst_test.c > > +++ b/lib/tst_test.c > > @@ -1365,6 +1365,19 @@ static const char *default_fs_type(void) > > return tst_dev_fs_type(); > > } > > +bool tst_cmd_present(const char *cmd) > > +{ > > + struct tst_cmd *pcmd = tst_test->needs_cmds; > > + > > + while (pcmd->cmd) { > > + if (!strcmp(pcmd->cmd, cmd)) > > + return pcmd->present; > > + > > + pcmd++; > > + } > > + return false; > Once again, we should tst_brk(TBROK, "Unexpected command '%s'", cmd) here since we asked for > something that we haven't checked for! Good point. I'm sorry to overlook this in my review. Also, strictly speaking tst_cmd_present() is only defined, not used. The commit is about changing .needs_cmds from char array (string) to struct tst_cmd. Therefore it could be in a separate commit. We don't have to be too strict, but given how many tests needed to be adapted adding tst_cmd_present() is somehow buried with other changes. Kind regards, Petr -- Mailing list info: https://lists.linux.it/listinfo/ltp ^ permalink raw reply [flat|nested] 100+ messages in thread
* Re: [LTP] [PATCH v5 1/3] lib: Add support option for .needs_cmds 2025-12-12 11:16 ` Petr Vorel @ 2025-12-15 7:33 ` Wei Gao via ltp 2025-12-15 9:36 ` Petr Vorel 2026-01-07 8:05 ` Petr Vorel 0 siblings, 2 replies; 100+ messages in thread From: Wei Gao via ltp @ 2025-12-15 7:33 UTC (permalink / raw) To: Petr Vorel; +Cc: ltp On Fri, Dec 12, 2025 at 12:16:18PM +0100, Petr Vorel wrote: > > Hi! > > > diff --git a/lib/tst_test.c b/lib/tst_test.c > > > index da5314c50..67553f65d 100644 > > > --- a/lib/tst_test.c > > > +++ b/lib/tst_test.c > > > @@ -1365,6 +1365,19 @@ static const char *default_fs_type(void) > > > return tst_dev_fs_type(); > > > } > > > > +bool tst_cmd_present(const char *cmd) > > > +{ > > > + struct tst_cmd *pcmd = tst_test->needs_cmds; > > > + > > > + while (pcmd->cmd) { > > > + if (!strcmp(pcmd->cmd, cmd)) > > > + return pcmd->present; > > > + > > > + pcmd++; > > > + } > > > + return false; > > > Once again, we should tst_brk(TBROK, "Unexpected command '%s'", cmd) here since we asked for > > something that we haven't checked for! > > Good point. I'm sorry to overlook this in my review. > > Also, strictly speaking tst_cmd_present() is only defined, not used. The commit > is about changing .needs_cmds from char array (string) to struct tst_cmd. > Therefore it could be in a separate commit. We don't have to be too strict, but > given how many tests needed to be adapted adding tst_cmd_present() is somehow > buried with other changes. Thanks all for detail feedback. Let's me give some explaination why skip tst_brk in above function: tst_cmd_present will be used in latest ioctl_loop01.c and it should not use tst_brk otherwise we will brk out of test in setup() too early. The new support needs_cmds.optional in current patch is used for support tst_cmd_present scenario in ioctl_loop01.c. Correct me if any mistake. ioctl_loop01.c code: static void setup(void) { parted_sup = tst_cmd_present("parted"); <===== ..... if (parted_sup) SAFE_CMD(cmd_parted, NULL, NULL); <=== sprintf(partscan_path, "/sys/block/loop%d/loop/partscan", dev_num); } > > Kind regards, > Petr -- Mailing list info: https://lists.linux.it/listinfo/ltp ^ permalink raw reply [flat|nested] 100+ messages in thread
* Re: [LTP] [PATCH v5 1/3] lib: Add support option for .needs_cmds 2025-12-15 7:33 ` Wei Gao via ltp @ 2025-12-15 9:36 ` Petr Vorel 2025-12-15 10:59 ` Wei Gao via ltp 2026-01-07 8:05 ` Petr Vorel 1 sibling, 1 reply; 100+ messages in thread From: Petr Vorel @ 2025-12-15 9:36 UTC (permalink / raw) To: Wei Gao; +Cc: ltp Hi Wei, ... > > Also, strictly speaking tst_cmd_present() is only defined, not used. The commit > > is about changing .needs_cmds from char array (string) to struct tst_cmd. > > Therefore it could be in a separate commit. We don't have to be too strict, but > > given how many tests needed to be adapted adding tst_cmd_present() is somehow > > buried with other changes. > Thanks all for detail feedback. Let's me give some explaination why skip > tst_brk in above function: > tst_cmd_present will be used in latest ioctl_loop01.c and it should not > use tst_brk otherwise we will brk out of test in setup() too early. > The new support needs_cmds.optional in current patch is used for support > tst_cmd_present scenario in ioctl_loop01.c. > Correct me if any mistake. Sure, I noticed tst_cmd_present() usage in a later commit :). My point was (while this patchset is also about ideal feature change split into commits) that if you touch many files with struct tst_cmd change, adding unrelated change (tst_cmd_present()) will hide this change. I would personally move adding tst_cmd_present() to a separate commit. It's not that important, just to make review easier. The rules (which I've tried to explain on this patchset) are * each commit must compile (even temporarily break build is not acceptable) * split changes into small logical parts People talk about atomic changes: "As small as possible, but complete" so that they don't break CI. https://dev.to/samuelfaure/how-atomic-git-commits-dramatically-increased-my-productivity-and-will-increase-yours-too-4a84 Kind regards, Petr > ioctl_loop01.c code: > static void setup(void) > { > parted_sup = tst_cmd_present("parted"); <===== > ..... > if (parted_sup) > SAFE_CMD(cmd_parted, NULL, NULL); <=== > sprintf(partscan_path, "/sys/block/loop%d/loop/partscan", dev_num); > } > > Kind regards, > > Petr -- Mailing list info: https://lists.linux.it/listinfo/ltp ^ permalink raw reply [flat|nested] 100+ messages in thread
* Re: [LTP] [PATCH v5 1/3] lib: Add support option for .needs_cmds 2025-12-15 9:36 ` Petr Vorel @ 2025-12-15 10:59 ` Wei Gao via ltp 2025-12-17 13:18 ` Petr Vorel 0 siblings, 1 reply; 100+ messages in thread From: Wei Gao via ltp @ 2025-12-15 10:59 UTC (permalink / raw) To: Petr Vorel; +Cc: ltp On Mon, Dec 15, 2025 at 10:36:39AM +0100, Petr Vorel wrote: > Hi Wei, > > ... > > > Also, strictly speaking tst_cmd_present() is only defined, not used. The commit > > > is about changing .needs_cmds from char array (string) to struct tst_cmd. > > > Therefore it could be in a separate commit. We don't have to be too strict, but > > > given how many tests needed to be adapted adding tst_cmd_present() is somehow > > > buried with other changes. > > > Thanks all for detail feedback. Let's me give some explaination why skip > > tst_brk in above function: > > tst_cmd_present will be used in latest ioctl_loop01.c and it should not > > use tst_brk otherwise we will brk out of test in setup() too early. > > The new support needs_cmds.optional in current patch is used for support > > tst_cmd_present scenario in ioctl_loop01.c. > > Correct me if any mistake. > > Sure, I noticed tst_cmd_present() usage in a later commit :). > > My point was (while this patchset is also about ideal feature change split into > commits) that if you touch many files with struct tst_cmd change, adding > unrelated change (tst_cmd_present()) will hide this change. I would personally > move adding tst_cmd_present() to a separate commit. It's not that important, > just to make review easier. Thanks, i get your point now. @Petr @Cyril If we have are agree with following changes then i can sent next patch: 1) Just move the declaration and definition of tst_cmd_present to a separate commit without any functional content changes. 2) Modify function comments such as add ref:`...` > > The rules (which I've tried to explain on this patchset) are > * each commit must compile (even temporarily break build is not acceptable) > * split changes into small logical parts > > People talk about atomic changes: "As small as possible, but complete" so that > they don't break CI. > https://dev.to/samuelfaure/how-atomic-git-commits-dramatically-increased-my-productivity-and-will-increase-yours-too-4a84 Nice link:) > > Kind regards, > Petr > > > ioctl_loop01.c code: > > static void setup(void) > > { > > parted_sup = tst_cmd_present("parted"); <===== > > > ..... > > if (parted_sup) > > SAFE_CMD(cmd_parted, NULL, NULL); <=== > > > sprintf(partscan_path, "/sys/block/loop%d/loop/partscan", dev_num); > > } > > > > Kind regards, > > > Petr -- Mailing list info: https://lists.linux.it/listinfo/ltp ^ permalink raw reply [flat|nested] 100+ messages in thread
* Re: [LTP] [PATCH v5 1/3] lib: Add support option for .needs_cmds 2025-12-15 10:59 ` Wei Gao via ltp @ 2025-12-17 13:18 ` Petr Vorel 0 siblings, 0 replies; 100+ messages in thread From: Petr Vorel @ 2025-12-17 13:18 UTC (permalink / raw) To: Wei Gao; +Cc: ltp > > Hi Wei, > > ... > > > > Also, strictly speaking tst_cmd_present() is only defined, not used. The commit > > > > is about changing .needs_cmds from char array (string) to struct tst_cmd. > > > > Therefore it could be in a separate commit. We don't have to be too strict, but > > > > given how many tests needed to be adapted adding tst_cmd_present() is somehow > > > > buried with other changes. > > > Thanks all for detail feedback. Let's me give some explaination why skip > > > tst_brk in above function: > > > tst_cmd_present will be used in latest ioctl_loop01.c and it should not > > > use tst_brk otherwise we will brk out of test in setup() too early. > > > The new support needs_cmds.optional in current patch is used for support > > > tst_cmd_present scenario in ioctl_loop01.c. > > > Correct me if any mistake. > > Sure, I noticed tst_cmd_present() usage in a later commit :). > > My point was (while this patchset is also about ideal feature change split into > > commits) that if you touch many files with struct tst_cmd change, adding > > unrelated change (tst_cmd_present()) will hide this change. I would personally > > move adding tst_cmd_present() to a separate commit. It's not that important, > > just to make review easier. > Thanks, i get your point now. > @Petr @Cyril > If we have are agree with following changes then i can sent next patch: > 1) Just move the declaration and definition of tst_cmd_present to a separate commit without any functional content changes. > 2) Modify function comments such as add ref:`...` +1, thank you! Kind regards, Petr -- Mailing list info: https://lists.linux.it/listinfo/ltp ^ permalink raw reply [flat|nested] 100+ messages in thread
* Re: [LTP] [PATCH v5 1/3] lib: Add support option for .needs_cmds 2025-12-15 7:33 ` Wei Gao via ltp 2025-12-15 9:36 ` Petr Vorel @ 2026-01-07 8:05 ` Petr Vorel 1 sibling, 0 replies; 100+ messages in thread From: Petr Vorel @ 2026-01-07 8:05 UTC (permalink / raw) To: Wei Gao; +Cc: ltp > On Fri, Dec 12, 2025 at 12:16:18PM +0100, Petr Vorel wrote: > > > Hi! > > > > diff --git a/lib/tst_test.c b/lib/tst_test.c > > > > index da5314c50..67553f65d 100644 > > > > --- a/lib/tst_test.c > > > > +++ b/lib/tst_test.c > > > > @@ -1365,6 +1365,19 @@ static const char *default_fs_type(void) > > > > return tst_dev_fs_type(); > > > > } > > > > +bool tst_cmd_present(const char *cmd) > > > > +{ > > > > + struct tst_cmd *pcmd = tst_test->needs_cmds; > > > > + > > > > + while (pcmd->cmd) { > > > > + if (!strcmp(pcmd->cmd, cmd)) > > > > + return pcmd->present; > > > > + > > > > + pcmd++; > > > > + } > > > > + return false; > > > Once again, we should tst_brk(TBROK, "Unexpected command '%s'", cmd) here since we asked for > > > something that we haven't checked for! > > Good point. I'm sorry to overlook this in my review. > > Also, strictly speaking tst_cmd_present() is only defined, not used. The commit > > is about changing .needs_cmds from char array (string) to struct tst_cmd. > > Therefore it could be in a separate commit. We don't have to be too strict, but > > given how many tests needed to be adapted adding tst_cmd_present() is somehow > > buried with other changes. > Thanks all for detail feedback. Let's me give some explaination why skip > tst_brk in above function: > tst_cmd_present will be used in latest ioctl_loop01.c and it should not > use tst_brk otherwise we will brk out of test in setup() too early. > The new support needs_cmds.optional in current patch is used for support > tst_cmd_present scenario in ioctl_loop01.c. > Correct me if any mistake. > ioctl_loop01.c code: > static void setup(void) > { > parted_sup = tst_cmd_present("parted"); <===== > ..... > if (parted_sup) > SAFE_CMD(cmd_parted, NULL, NULL); <=== > sprintf(partscan_path, "/sys/block/loop%d/loop/partscan", dev_num); > } And also: static struct tst_test test = { ... .needs_cmds = (struct tst_cmd[]) { {.cmd = "parted", .optional = 1}, {} Therefore IMHO you are wrong. + while (pcmd->cmd) { + if (!strcmp(pcmd->cmd, cmd)) We always match this for programs which we checked via .needs_cmds (regardless true or false return). + return pcmd->present; + + pcmd++; + } If we get here that means that we ask in tst_cmd_present("...") for program we did not add .needs_cmds. That's why Cyril asked for tst_brk(). + return false; Kind regards, Petr > > Kind regards, > > Petr -- Mailing list info: https://lists.linux.it/listinfo/ltp ^ permalink raw reply [flat|nested] 100+ messages in thread
* [LTP] [PATCH v5 2/3] ioctl_loop01.c: Add new support .needs_cmds 2025-11-10 2:47 ` [LTP] [PATCH v5 0/3] new cmd support option for needs_cmds Wei Gao via ltp 2025-11-10 2:47 ` [LTP] [PATCH v5 1/3] lib: Add support option for .needs_cmds Wei Gao via ltp @ 2025-11-10 2:47 ` Wei Gao via ltp 2025-11-11 11:14 ` Petr Vorel 2025-11-10 2:47 ` [LTP] [PATCH v5 3/3] shell_loader_cmd.sh: New test case check needs_cmds Wei Gao via ltp 2025-12-23 2:08 ` [LTP] [PATCH v6 0/4] new cmd support option for needs_cmds Wei Gao via ltp 3 siblings, 1 reply; 100+ messages in thread From: Wei Gao via ltp @ 2025-11-10 2:47 UTC (permalink / raw) To: ltp Signed-off-by: Wei Gao <wegao@suse.com> --- .../kernel/syscalls/ioctl/ioctl_loop01.c | 34 +++++++++---------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/testcases/kernel/syscalls/ioctl/ioctl_loop01.c b/testcases/kernel/syscalls/ioctl/ioctl_loop01.c index 4ecc93b1e..a8a9305c8 100644 --- a/testcases/kernel/syscalls/ioctl/ioctl_loop01.c +++ b/testcases/kernel/syscalls/ioctl/ioctl_loop01.c @@ -78,23 +78,6 @@ static void check_loop_value(int set_flag, int get_flag, int autoclear_field) static void verify_ioctl_loop(void) { - int ret; - const char *const cmd_parted[] = {"parted", "-s", dev_path, "mklabel", "msdos", "mkpart", - "primary", "ext4", "1M", "10M", NULL}; - - tst_fill_file("test.img", 0, 1024 * 1024, 10); - tst_attach_device(dev_path, "test.img"); - - ret = tst_cmd(cmd_parted, NULL, NULL, TST_CMD_PASS_RETVAL); - if (!ret) - parted_sup = 1; - else if (ret == 255) - tst_res(TCONF, "parted binary not installed or failed"); - else - tst_res(TCONF, "parted exited with %i", ret); - - attach_flag = 1; - TST_ASSERT_INT(partscan_path, 0); TST_ASSERT_INT(autoclear_path, 0); TST_ASSERT_STR(backing_path, backing_file_path); @@ -113,10 +96,23 @@ static void verify_ioctl_loop(void) static void setup(void) { + parted_sup = tst_cmd_present("parted"); + + const char *const cmd_parted[] = {"parted", "-s", dev_path, "mklabel", "msdos", "mkpart", + "primary", "ext4", "1M", "10M", NULL}; + dev_num = tst_find_free_loopdev(dev_path, sizeof(dev_path)); if (dev_num < 0) tst_brk(TBROK, "Failed to find free loop device"); + tst_fill_file("test.img", 0, 1024 * 1024, 10); + + tst_attach_device(dev_path, "test.img"); + attach_flag = 1; + + if (parted_sup) + SAFE_CMD(cmd_parted, NULL, NULL); + sprintf(partscan_path, "/sys/block/loop%d/loop/partscan", dev_num); sprintf(autoclear_path, "/sys/block/loop%d/loop/autoclear", dev_num); sprintf(backing_path, "/sys/block/loop%d/loop/backing_file", dev_num); @@ -148,5 +144,9 @@ static struct tst_test test = { {"linux-git", "6ac92fb5cdff"}, {} }, + .needs_cmds = (struct tst_cmd[]) { + {.cmd = "parted", .optional = 1}, + {} + }, .needs_tmpdir = 1, }; -- 2.51.0 -- Mailing list info: https://lists.linux.it/listinfo/ltp ^ permalink raw reply related [flat|nested] 100+ messages in thread
* Re: [LTP] [PATCH v5 2/3] ioctl_loop01.c: Add new support .needs_cmds 2025-11-10 2:47 ` [LTP] [PATCH v5 2/3] ioctl_loop01.c: Add new support .needs_cmds Wei Gao via ltp @ 2025-11-11 11:14 ` Petr Vorel 0 siblings, 0 replies; 100+ messages in thread From: Petr Vorel @ 2025-11-11 11:14 UTC (permalink / raw) To: Wei Gao; +Cc: Martin Doucha, ltp Hi Wei, Reviewed-by: Petr Vorel <pvorel@suse.cz> > +++ b/testcases/kernel/syscalls/ioctl/ioctl_loop01.c > @@ -78,23 +78,6 @@ static void check_loop_value(int set_flag, int get_flag, int autoclear_field) > static void verify_ioctl_loop(void) > { > - int ret; > - const char *const cmd_parted[] = {"parted", "-s", dev_path, "mklabel", "msdos", "mkpart", > - "primary", "ext4", "1M", "10M", NULL}; > - > - tst_fill_file("test.img", 0, 1024 * 1024, 10); > - tst_attach_device(dev_path, "test.img"); > - > - ret = tst_cmd(cmd_parted, NULL, NULL, TST_CMD_PASS_RETVAL); > - if (!ret) > - parted_sup = 1; > - else if (ret == 255) > - tst_res(TCONF, "parted binary not installed or failed"); > - else > - tst_res(TCONF, "parted exited with %i", ret); > - > - attach_flag = 1; > - > TST_ASSERT_INT(partscan_path, 0); > TST_ASSERT_INT(autoclear_path, 0); > TST_ASSERT_STR(backing_path, backing_file_path); > @@ -113,10 +96,23 @@ static void verify_ioctl_loop(void) > static void setup(void) > { > + parted_sup = tst_cmd_present("parted"); > + > + const char *const cmd_parted[] = {"parted", "-s", dev_path, "mklabel", "msdos", "mkpart", > + "primary", "ext4", "1M", "10M", NULL}; FYI unfortunately I'm still able to trigger loop failure on SLES 5.14 based kernel when looping ioctl_loop01 and ioctl_ficlone02 for a while on both current master and with this patch (which does not handle the problem). dmesg: [ 1101.501003] ioctl_loop01 [ 1101.519346] loop0: detected capacity change from 0 to 20480 [ 1101.664879] loop_reread_partitions: partition scan of loop0 () failed (rc=-16) [ 1101.705931] blk_update_request: I/O error, dev loop0, sector 20352 op 0x0:(READ) flags 0x80700 phys_seg 1 prio class 0 [ 1101.710398] blk_update_request: I/O error, dev loop0, sector 20352 op 0x0:(READ) flags 0x0 phys_seg 1 prio class 0 [ 1101.710423] __loop_clr_fd: partition scan of loop0 failed (rc=-16) [ 1101.713612] Buffer I/O error on dev loop0p1, logical block 2288, async page read [ 1101.774843] blk_update_request: I/O error, dev loop0, sector 20352 op 0x0:(READ) flags 0x80700 phys_seg 1 prio class 0 [ 1101.783014] blk_update_request: I/O error, dev loop0, sector 20352 op 0x0:(READ) flags 0x0 phys_seg 1 prio class 0 [ 1101.787585] Buffer I/O error on dev loop0p1, logical block 2288, async page read [ 1101.824974] ioctl_ficlone02 [ 1101.827315] loop0: detected capacity change from 0 to 614400 [ 1101.861851] /dev/zero: Can't open blockdev [ 1101.968916] EXT4-fs (loop0): mounting ext2 file system using the ext4 subsystem [ 1101.975954] EXT4-fs (loop0): mounted filesystem without journal. Opts: (null). Quota mode: none. [ 1102.156957] EXT4-fs (loop0): mounting ext3 file system using the ext4 subsystem [ 1102.163452] EXT4-fs (loop0): mounted filesystem with ordered data mode. Opts: (null). Quota mode: none. [ 1102.268502] EXT4-fs (loop0): mounted filesystem with ordered data mode. Opts: (null). Quota mode: none. Fortunately Martin is working on a patch for LTP library that'll check for leftover partitions after loop device release and clear them, with appropriate TWARN message. Kind regards, Petr > + > dev_num = tst_find_free_loopdev(dev_path, sizeof(dev_path)); > if (dev_num < 0) > tst_brk(TBROK, "Failed to find free loop device"); > + tst_fill_file("test.img", 0, 1024 * 1024, 10); > + > + tst_attach_device(dev_path, "test.img"); > + attach_flag = 1; > + > + if (parted_sup) > + SAFE_CMD(cmd_parted, NULL, NULL); > + > sprintf(partscan_path, "/sys/block/loop%d/loop/partscan", dev_num); > sprintf(autoclear_path, "/sys/block/loop%d/loop/autoclear", dev_num); > sprintf(backing_path, "/sys/block/loop%d/loop/backing_file", dev_num); > @@ -148,5 +144,9 @@ static struct tst_test test = { > {"linux-git", "6ac92fb5cdff"}, > {} > }, > + .needs_cmds = (struct tst_cmd[]) { > + {.cmd = "parted", .optional = 1}, > + {} > + }, -- Mailing list info: https://lists.linux.it/listinfo/ltp ^ permalink raw reply [flat|nested] 100+ messages in thread
* [LTP] [PATCH v5 3/3] shell_loader_cmd.sh: New test case check needs_cmds 2025-11-10 2:47 ` [LTP] [PATCH v5 0/3] new cmd support option for needs_cmds Wei Gao via ltp 2025-11-10 2:47 ` [LTP] [PATCH v5 1/3] lib: Add support option for .needs_cmds Wei Gao via ltp 2025-11-10 2:47 ` [LTP] [PATCH v5 2/3] ioctl_loop01.c: Add new support .needs_cmds Wei Gao via ltp @ 2025-11-10 2:47 ` Wei Gao via ltp 2025-11-11 10:41 ` Wei Gao via ltp 2025-11-11 11:15 ` Petr Vorel 2025-12-23 2:08 ` [LTP] [PATCH v6 0/4] new cmd support option for needs_cmds Wei Gao via ltp 3 siblings, 2 replies; 100+ messages in thread From: Wei Gao via ltp @ 2025-11-10 2:47 UTC (permalink / raw) To: ltp Suggested-by: Petr Vorel <pvorel@suse.cz> Signed-off-by: Wei Gao <wegao@suse.com> --- testcases/lib/run_tests.sh | 1 + testcases/lib/tests/shell_loader_cmd.sh | 28 +++++++++++++++++++++++++ 2 files changed, 29 insertions(+) create mode 100755 testcases/lib/tests/shell_loader_cmd.sh diff --git a/testcases/lib/run_tests.sh b/testcases/lib/run_tests.sh index 5c309bbeb..24ac81a44 100755 --- a/testcases/lib/run_tests.sh +++ b/testcases/lib/run_tests.sh @@ -6,6 +6,7 @@ shell_loader.sh shell_loader_all_filesystems.sh shell_loader_c_child.sh shell_loader_filesystems.sh +shell_loader_cmd.sh shell_loader_kconfigs.sh shell_loader_supported_archs.sh shell_loader_tcnt.sh diff --git a/testcases/lib/tests/shell_loader_cmd.sh b/testcases/lib/tests/shell_loader_cmd.sh new file mode 100755 index 000000000..4e8e61eb6 --- /dev/null +++ b/testcases/lib/tests/shell_loader_cmd.sh @@ -0,0 +1,28 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (c) 2025 Wei Gao <wegao@suse.cz> +# +# --- +# env +# { +# "needs_cmds": [ +# { +# "cmd": "ls", +# "optional": 1 +# }, +# { +# "cmd": "mkfs.ext4 >= 1.0.0", +# "optional": 1 +# } +# ] +# } +# --- + +. tst_loader.sh + +tst_test() +{ + tst_res TPASS "We are running with needs_cmds" +} + +. tst_run.sh -- 2.51.0 -- Mailing list info: https://lists.linux.it/listinfo/ltp ^ permalink raw reply related [flat|nested] 100+ messages in thread
* Re: [LTP] [PATCH v5 3/3] shell_loader_cmd.sh: New test case check needs_cmds 2025-11-10 2:47 ` [LTP] [PATCH v5 3/3] shell_loader_cmd.sh: New test case check needs_cmds Wei Gao via ltp @ 2025-11-11 10:41 ` Wei Gao via ltp 2025-11-11 11:15 ` Petr Vorel 1 sibling, 0 replies; 100+ messages in thread From: Wei Gao via ltp @ 2025-11-11 10:41 UTC (permalink / raw) To: ltp Sorry, It seems some strange CI failure triggered by "cmd": "mkfs.ext4 >= 1.0.0", i need further check and will update it. On Mon, Nov 10, 2025 at 10:48 AM Wei Gao <wegao@suse.com> wrote: > Suggested-by: Petr Vorel <pvorel@suse.cz> > Signed-off-by: Wei Gao <wegao@suse.com> > --- > testcases/lib/run_tests.sh | 1 + > testcases/lib/tests/shell_loader_cmd.sh | 28 +++++++++++++++++++++++++ > 2 files changed, 29 insertions(+) > create mode 100755 testcases/lib/tests/shell_loader_cmd.sh > > diff --git a/testcases/lib/run_tests.sh b/testcases/lib/run_tests.sh > index 5c309bbeb..24ac81a44 100755 > --- a/testcases/lib/run_tests.sh > +++ b/testcases/lib/run_tests.sh > @@ -6,6 +6,7 @@ shell_loader.sh > shell_loader_all_filesystems.sh > shell_loader_c_child.sh > shell_loader_filesystems.sh > +shell_loader_cmd.sh > shell_loader_kconfigs.sh > shell_loader_supported_archs.sh > shell_loader_tcnt.sh > diff --git a/testcases/lib/tests/shell_loader_cmd.sh > b/testcases/lib/tests/shell_loader_cmd.sh > new file mode 100755 > index 000000000..4e8e61eb6 > --- /dev/null > +++ b/testcases/lib/tests/shell_loader_cmd.sh > @@ -0,0 +1,28 @@ > +#!/bin/sh > +# SPDX-License-Identifier: GPL-2.0-or-later > +# Copyright (c) 2025 Wei Gao <wegao@suse.cz> > +# > +# --- > +# env > +# { > +# "needs_cmds": [ > +# { > +# "cmd": "ls", > +# "optional": 1 > +# }, > +# { > +# "cmd": "mkfs.ext4 >= 1.0.0", > +# "optional": 1 > +# } > +# ] > +# } > +# --- > + > +. tst_loader.sh > + > +tst_test() > +{ > + tst_res TPASS "We are running with needs_cmds" > +} > + > +. tst_run.sh > -- > 2.51.0 > > -- Mailing list info: https://lists.linux.it/listinfo/ltp ^ permalink raw reply [flat|nested] 100+ messages in thread
* Re: [LTP] [PATCH v5 3/3] shell_loader_cmd.sh: New test case check needs_cmds 2025-11-10 2:47 ` [LTP] [PATCH v5 3/3] shell_loader_cmd.sh: New test case check needs_cmds Wei Gao via ltp 2025-11-11 10:41 ` Wei Gao via ltp @ 2025-11-11 11:15 ` Petr Vorel 1 sibling, 0 replies; 100+ messages in thread From: Petr Vorel @ 2025-11-11 11:15 UTC (permalink / raw) To: Wei Gao; +Cc: ltp Hi Wei, Reviewed-by: Petr Vorel <pvorel@suse.cz> Thanks! Kind regards, Petr -- Mailing list info: https://lists.linux.it/listinfo/ltp ^ permalink raw reply [flat|nested] 100+ messages in thread
* [LTP] [PATCH v6 0/4] new cmd support option for needs_cmds 2025-11-10 2:47 ` [LTP] [PATCH v5 0/3] new cmd support option for needs_cmds Wei Gao via ltp ` (2 preceding siblings ...) 2025-11-10 2:47 ` [LTP] [PATCH v5 3/3] shell_loader_cmd.sh: New test case check needs_cmds Wei Gao via ltp @ 2025-12-23 2:08 ` Wei Gao via ltp 2025-12-23 2:08 ` [LTP] [PATCH v6 1/4] lib: Add support option for .needs_cmds Wei Gao via ltp ` (4 more replies) 3 siblings, 5 replies; 100+ messages in thread From: Wei Gao via ltp @ 2025-12-23 2:08 UTC (permalink / raw) To: ltp v5-v6: 1) Move the declaration and definition of tst_cmd_present to a separate commit 2) Modify function comments such as add ref:`...` Wei Gao (4): lib: Add support option for .needs_cmds tst_test.c: Add tst_cmd_present check if a command is present ioctl_loop01.c: Add new support .needs_cmds shell_loader_cmd.sh: New test case check needs_cmds include/tst_cmd.h | 13 ++++ include/tst_test.h | 16 ++++- lib/newlib_tests/tst_needs_cmds01.c | 16 ++--- lib/newlib_tests/tst_needs_cmds02.c | 6 +- lib/newlib_tests/tst_needs_cmds03.c | 6 +- lib/newlib_tests/tst_needs_cmds04.c | 6 +- lib/newlib_tests/tst_needs_cmds05.c | 6 +- lib/newlib_tests/tst_needs_cmds06.c | 6 +- lib/newlib_tests/tst_needs_cmds07.c | 6 +- lib/newlib_tests/tst_needs_cmds08.c | 8 +-- lib/tst_test.c | 22 +++++-- testcases/kernel/device-drivers/zram/zram03.c | 8 +-- testcases/kernel/fs/squashfs/squashfs01.c | 6 +- testcases/kernel/security/aslr/aslr01.c | 6 +- testcases/kernel/syscalls/add_key/add_key05.c | 10 +-- .../kernel/syscalls/fanotify/fanotify22.c | 6 +- testcases/kernel/syscalls/ioctl/ioctl09.c | 6 +- .../kernel/syscalls/ioctl/ioctl_loop01.c | 34 +++++------ testcases/kernel/syscalls/madvise/madvise11.c | 8 +-- .../kernel/syscalls/quotactl/quotactl01.c | 6 +- .../kernel/syscalls/quotactl/quotactl04.c | 6 +- .../kernel/syscalls/quotactl/quotactl06.c | 6 +- .../kernel/syscalls/quotactl/quotactl08.c | 6 +- .../kernel/syscalls/quotactl/quotactl09.c | 6 +- testcases/kernel/syscalls/statx/statx05.c | 8 +-- testcases/kernel/syscalls/statx/statx07.c | 6 +- testcases/kernel/syscalls/statx/statx09.c | 6 +- testcases/lib/run_tests.sh | 1 + testcases/lib/tests/shell_loader_cmd.sh | 28 +++++++++ testcases/lib/tst_run_shell.c | 61 ++++++++++++++++++- 30 files changed, 231 insertions(+), 104 deletions(-) create mode 100755 testcases/lib/tests/shell_loader_cmd.sh -- 2.52.0 -- Mailing list info: https://lists.linux.it/listinfo/ltp ^ permalink raw reply [flat|nested] 100+ messages in thread
* [LTP] [PATCH v6 1/4] lib: Add support option for .needs_cmds 2025-12-23 2:08 ` [LTP] [PATCH v6 0/4] new cmd support option for needs_cmds Wei Gao via ltp @ 2025-12-23 2:08 ` Wei Gao via ltp 2026-01-05 13:48 ` Petr Vorel 2026-01-06 10:01 ` Cyril Hrubis 2025-12-23 2:08 ` [LTP] [PATCH v6 2/4] tst_test.c: Add tst_cmd_present check if a command is present Wei Gao via ltp ` (3 subsequent siblings) 4 siblings, 2 replies; 100+ messages in thread From: Wei Gao via ltp @ 2025-12-23 2:08 UTC (permalink / raw) To: ltp Suggested-by: Cyril Hrubis <chrubis@suse.cz> Signed-off-by: Wei Gao <wegao@suse.com> --- include/tst_cmd.h | 13 ++++ include/tst_test.h | 4 +- lib/newlib_tests/tst_needs_cmds01.c | 16 ++--- lib/newlib_tests/tst_needs_cmds02.c | 6 +- lib/newlib_tests/tst_needs_cmds03.c | 6 +- lib/newlib_tests/tst_needs_cmds04.c | 6 +- lib/newlib_tests/tst_needs_cmds05.c | 6 +- lib/newlib_tests/tst_needs_cmds06.c | 6 +- lib/newlib_tests/tst_needs_cmds07.c | 6 +- lib/newlib_tests/tst_needs_cmds08.c | 8 +-- lib/tst_test.c | 9 +-- testcases/kernel/device-drivers/zram/zram03.c | 8 +-- testcases/kernel/fs/squashfs/squashfs01.c | 6 +- testcases/kernel/security/aslr/aslr01.c | 6 +- testcases/kernel/syscalls/add_key/add_key05.c | 10 +-- .../kernel/syscalls/fanotify/fanotify22.c | 6 +- testcases/kernel/syscalls/ioctl/ioctl09.c | 6 +- testcases/kernel/syscalls/madvise/madvise11.c | 8 +-- .../kernel/syscalls/quotactl/quotactl01.c | 6 +- .../kernel/syscalls/quotactl/quotactl04.c | 6 +- .../kernel/syscalls/quotactl/quotactl06.c | 6 +- .../kernel/syscalls/quotactl/quotactl08.c | 6 +- .../kernel/syscalls/quotactl/quotactl09.c | 6 +- testcases/kernel/syscalls/statx/statx05.c | 8 +-- testcases/kernel/syscalls/statx/statx07.c | 6 +- testcases/kernel/syscalls/statx/statx09.c | 6 +- testcases/lib/tst_run_shell.c | 61 ++++++++++++++++++- 27 files changed, 160 insertions(+), 87 deletions(-) diff --git a/include/tst_cmd.h b/include/tst_cmd.h index cf6382955..2203241c5 100644 --- a/include/tst_cmd.h +++ b/include/tst_cmd.h @@ -19,6 +19,19 @@ enum tst_cmd_flags { TST_CMD_TCONF_ON_MISSING = 2, }; +/** + * struct tst_cmd - Provides details about a command struct needed by LTP test. + * @cmd: The name of the command. + * @optional: A flag indicating if the command is optional. + * @present: A flag indicating if the command was found at runtime. This is an output + * parameter, set by the LTP library during the test setup. + */ +struct tst_cmd { + const char *cmd; + unsigned int optional:1; + unsigned int present:1; +}; + /* * vfork() + execvp() specified program. * diff --git a/include/tst_test.h b/include/tst_test.h index 9c21c1728..38a9d0d54 100644 --- a/include/tst_test.h +++ b/include/tst_test.h @@ -524,7 +524,7 @@ struct tst_fs { * * @tags: A {} terminated array of test tags. See struct tst_tag for details. * - * @needs_cmds: A NULL terminated array of commands required for the test to run. + * @needs_cmds: A NULL terminated array of :ref:`struct tst_cmd` required for the test to run. * * @needs_cgroup_ver: If set the test will run only if the specified cgroup * version is present on the system. @@ -617,7 +617,7 @@ struct tst_fs { const struct tst_tag *tags; - const char *const *needs_cmds; + struct tst_cmd *needs_cmds; const enum tst_cg_ver needs_cgroup_ver; diff --git a/lib/newlib_tests/tst_needs_cmds01.c b/lib/newlib_tests/tst_needs_cmds01.c index 777c69505..6ab1145d1 100644 --- a/lib/newlib_tests/tst_needs_cmds01.c +++ b/lib/newlib_tests/tst_needs_cmds01.c @@ -12,13 +12,13 @@ static void do_test(void) static struct tst_test test = { .test_all = do_test, - .needs_cmds = (const char *[]) { - "mkfs.ext4", - "mkfs.ext4 >= 1.0.0", - "mkfs.ext4 <= 2.0.0", - "mkfs.ext4 != 2.0.0", - "mkfs.ext4 > 1.0.0", - "mkfs.ext4 < 2.0.0", - NULL + .needs_cmds = (struct tst_cmd[]) { + {.cmd = "mkfs.ext4", .optional = 1}, + {.cmd = "mkfs.ext4 >= 1.0.0", .optional = 0}, + {.cmd = "mkfs.ext4 <= 2.0.0"}, + {.cmd = "mkfs.ext4 != 2.0.0"}, + {.cmd = "mkfs.ext4 > 1.0.0"}, + {.cmd = "mkfs.ext4 < 2.0.0"}, + {} } }; diff --git a/lib/newlib_tests/tst_needs_cmds02.c b/lib/newlib_tests/tst_needs_cmds02.c index 455a275ea..f1d6105c2 100644 --- a/lib/newlib_tests/tst_needs_cmds02.c +++ b/lib/newlib_tests/tst_needs_cmds02.c @@ -16,8 +16,8 @@ static void do_test(void) static struct tst_test test = { .test_all = do_test, - .needs_cmds = (const char *[]) { - "mkfs.ext45 >= 1.43.0", - NULL + .needs_cmds = (struct tst_cmd[]) { + {.cmd = "mkfs.ext45 >= 1.43.0"}, + {} } }; diff --git a/lib/newlib_tests/tst_needs_cmds03.c b/lib/newlib_tests/tst_needs_cmds03.c index bdc1cdf6a..ac5f368e2 100644 --- a/lib/newlib_tests/tst_needs_cmds03.c +++ b/lib/newlib_tests/tst_needs_cmds03.c @@ -16,8 +16,8 @@ static void do_test(void) static struct tst_test test = { .test_all = do_test, - .needs_cmds = (const char *[]) { - "mkfs.ext4 ! 1.43.0", - NULL + .needs_cmds = (struct tst_cmd[]) { + {.cmd = "mkfs.ext4 ! 1.43.0"}, + {} } }; diff --git a/lib/newlib_tests/tst_needs_cmds04.c b/lib/newlib_tests/tst_needs_cmds04.c index de10b8f3e..2aea51772 100644 --- a/lib/newlib_tests/tst_needs_cmds04.c +++ b/lib/newlib_tests/tst_needs_cmds04.c @@ -16,8 +16,8 @@ static void do_test(void) static struct tst_test test = { .test_all = do_test, - .needs_cmds = (const char *[]) { - "mkfs.ext4 > 1.43", - NULL + .needs_cmds = (struct tst_cmd[]) { + {.cmd = "mkfs.ext4 > 1.43"}, + {} } }; diff --git a/lib/newlib_tests/tst_needs_cmds05.c b/lib/newlib_tests/tst_needs_cmds05.c index c3b2b3b9a..969d4e2f5 100644 --- a/lib/newlib_tests/tst_needs_cmds05.c +++ b/lib/newlib_tests/tst_needs_cmds05.c @@ -16,8 +16,8 @@ static void do_test(void) static struct tst_test test = { .test_all = do_test, - .needs_cmds = (const char *[]) { - "mkfs.ext4 > 1.43.0-1", - NULL + .needs_cmds = (struct tst_cmd[]) { + {.cmd = "mkfs.ext4 > 1.43.0-1"}, + {} } }; diff --git a/lib/newlib_tests/tst_needs_cmds06.c b/lib/newlib_tests/tst_needs_cmds06.c index 40b1cf09c..91470ccf9 100644 --- a/lib/newlib_tests/tst_needs_cmds06.c +++ b/lib/newlib_tests/tst_needs_cmds06.c @@ -16,8 +16,8 @@ static void do_test(void) static struct tst_test test = { .test_all = do_test, - .needs_cmds = (const char *[]) { - "mkfs.ext4 > 1.43.0 2", - NULL + .needs_cmds = (struct tst_cmd[]) { + {.cmd = "mkfs.ext4 > 1.43.0 2"}, + {} } }; diff --git a/lib/newlib_tests/tst_needs_cmds07.c b/lib/newlib_tests/tst_needs_cmds07.c index d0b4ce2ff..371bbdc1b 100644 --- a/lib/newlib_tests/tst_needs_cmds07.c +++ b/lib/newlib_tests/tst_needs_cmds07.c @@ -16,8 +16,8 @@ static void do_test(void) static struct tst_test test = { .test_all = do_test, - .needs_cmds = (const char *[]) { - "mkfs.ext45", - NULL + .needs_cmds = (struct tst_cmd[]) { + {.cmd = "mkfs.ext45"}, + {} } }; diff --git a/lib/newlib_tests/tst_needs_cmds08.c b/lib/newlib_tests/tst_needs_cmds08.c index 38df2ef6d..412f9f293 100644 --- a/lib/newlib_tests/tst_needs_cmds08.c +++ b/lib/newlib_tests/tst_needs_cmds08.c @@ -18,9 +18,9 @@ static void do_test(void) static struct tst_test test = { .test_all = do_test, - .needs_cmds = (const char *[]) { - "mkfs.xfs", - "mkfs.xfs >= 4.20.0", - NULL + .needs_cmds = (struct tst_cmd[]) { + {.cmd = "mkfs.xfs"}, + {.cmd = "mkfs.xfs >= 4.20.0"}, + {} } }; diff --git a/lib/tst_test.c b/lib/tst_test.c index da5314c50..42a54621e 100644 --- a/lib/tst_test.c +++ b/lib/tst_test.c @@ -1439,11 +1439,12 @@ static void do_setup(int argc, char *argv[]) tst_brk(TCONF, "%dbit ABI is not supported", tst_test->needs_abi_bits); if (tst_test->needs_cmds) { - const char *cmd; - int i; + struct tst_cmd *pcmd = tst_test->needs_cmds; - for (i = 0; (cmd = tst_test->needs_cmds[i]); ++i) - tst_check_cmd(cmd, 1); + while (pcmd->cmd) { + pcmd->present = tst_check_cmd(pcmd->cmd, !pcmd->optional) ? 1 : 0; + pcmd++; + } } if (tst_test->needs_drivers) { diff --git a/testcases/kernel/device-drivers/zram/zram03.c b/testcases/kernel/device-drivers/zram/zram03.c index 8cf26de4c..4dcf23b4e 100644 --- a/testcases/kernel/device-drivers/zram/zram03.c +++ b/testcases/kernel/device-drivers/zram/zram03.c @@ -240,9 +240,9 @@ static struct tst_test test = { "zram", NULL }, - .needs_cmds = (const char *[]) { - "modprobe", - "rmmod", - NULL + .needs_cmds = (struct tst_cmd[]) { + {.cmd = "modprobe"}, + {.cmd = "rmmod"}, + {} } }; diff --git a/testcases/kernel/fs/squashfs/squashfs01.c b/testcases/kernel/fs/squashfs/squashfs01.c index fbcb76582..7a548d62c 100644 --- a/testcases/kernel/fs/squashfs/squashfs01.c +++ b/testcases/kernel/fs/squashfs/squashfs01.c @@ -102,9 +102,9 @@ static struct tst_test test = { .needs_root = 1, .needs_device = 1, .dev_min_size = 1, - .needs_cmds = (const char *const []) { - "mksquashfs", - NULL + .needs_cmds = (struct tst_cmd[]) { + {.cmd = "mksquashfs"}, + {} }, .needs_drivers = (const char *const []) { "squashfs", diff --git a/testcases/kernel/security/aslr/aslr01.c b/testcases/kernel/security/aslr/aslr01.c index 6a396e29d..e6feb2d3c 100644 --- a/testcases/kernel/security/aslr/aslr01.c +++ b/testcases/kernel/security/aslr/aslr01.c @@ -277,8 +277,8 @@ static struct tst_test test = { "CONFIG_HAVE_ARCH_MMAP_RND_BITS=y", NULL }, - .needs_cmds = (const char *[]) { - "ldd", - NULL + .needs_cmds = (struct tst_cmd[]) { + {.cmd = "ldd"}, + {} }, }; diff --git a/testcases/kernel/syscalls/add_key/add_key05.c b/testcases/kernel/syscalls/add_key/add_key05.c index c9a2f840e..b51a84b97 100644 --- a/testcases/kernel/syscalls/add_key/add_key05.c +++ b/testcases/kernel/syscalls/add_key/add_key05.c @@ -231,11 +231,11 @@ static struct tst_test test = { {&user_buf, .size = 64}, {} }, - .needs_cmds = (const char *const []) { - "useradd", - "userdel", - "groupdel", - NULL + .needs_cmds = (struct tst_cmd[]) { + {.cmd = "useradd"}, + {.cmd = "userdel"}, + {.cmd = "groupdel"}, + {} }, .tags = (const struct tst_tag[]) { {"linux-git", "a08bf91ce28"}, diff --git a/testcases/kernel/syscalls/fanotify/fanotify22.c b/testcases/kernel/syscalls/fanotify/fanotify22.c index 357e74dbc..6578474a7 100644 --- a/testcases/kernel/syscalls/fanotify/fanotify22.c +++ b/testcases/kernel/syscalls/fanotify/fanotify22.c @@ -327,9 +327,9 @@ static struct tst_test test = { {"linux-git", "76486b104168"}, {} }, - .needs_cmds = (const char *[]) { - "debugfs", - NULL + .needs_cmds = (struct tst_cmd[]) { + {.cmd = "debugfs"}, + {} } }; diff --git a/testcases/kernel/syscalls/ioctl/ioctl09.c b/testcases/kernel/syscalls/ioctl/ioctl09.c index c046d8959..21e16efb6 100644 --- a/testcases/kernel/syscalls/ioctl/ioctl09.c +++ b/testcases/kernel/syscalls/ioctl/ioctl09.c @@ -108,9 +108,9 @@ static struct tst_test test = { "loop", NULL }, - .needs_cmds = (const char *const []) { - "parted", - NULL + .needs_cmds = (struct tst_cmd[]) { + {.cmd = "parted"}, + {} }, .needs_tmpdir = 1, }; diff --git a/testcases/kernel/syscalls/madvise/madvise11.c b/testcases/kernel/syscalls/madvise/madvise11.c index 422589f5b..73d2d4294 100644 --- a/testcases/kernel/syscalls/madvise/madvise11.c +++ b/testcases/kernel/syscalls/madvise/madvise11.c @@ -421,10 +421,10 @@ static struct tst_test test = { HW_MODULE, NULL }, - .needs_cmds = (const char *[]) { - "modprobe", - "rmmod", - NULL + .needs_cmds = (struct tst_cmd[]) { + {.cmd = "modprobe"}, + {.cmd = "rmmod"}, + {} }, .needs_kconfigs = (const char *[]) { "CONFIG_MEMORY_FAILURE=y", diff --git a/testcases/kernel/syscalls/quotactl/quotactl01.c b/testcases/kernel/syscalls/quotactl/quotactl01.c index 9dcf74ceb..3091ac5bf 100644 --- a/testcases/kernel/syscalls/quotactl/quotactl01.c +++ b/testcases/kernel/syscalls/quotactl/quotactl01.c @@ -223,9 +223,9 @@ static struct tst_test test = { {} }, .mntpoint = MNTPOINT, - .needs_cmds = (const char *const []) { - "quotacheck", - NULL + .needs_cmds = (struct tst_cmd[]) { + {.cmd = "quotacheck"}, + {} }, .setup = setup, .cleanup = cleanup, diff --git a/testcases/kernel/syscalls/quotactl/quotactl04.c b/testcases/kernel/syscalls/quotactl/quotactl04.c index d2d7b3f3e..a70903330 100644 --- a/testcases/kernel/syscalls/quotactl/quotactl04.c +++ b/testcases/kernel/syscalls/quotactl/quotactl04.c @@ -165,8 +165,8 @@ static struct tst_test test = { }, .mntpoint = MNTPOINT, .test_variants = QUOTACTL_SYSCALL_VARIANTS, - .needs_cmds = (const char *[]) { - "mkfs.ext4 >= 1.43.0", - NULL + .needs_cmds = (struct tst_cmd[]) { + {.cmd = "mkfs.ext4 >= 1.43.0"}, + {} } }; diff --git a/testcases/kernel/syscalls/quotactl/quotactl06.c b/testcases/kernel/syscalls/quotactl/quotactl06.c index 110a3aa9b..333f5720d 100644 --- a/testcases/kernel/syscalls/quotactl/quotactl06.c +++ b/testcases/kernel/syscalls/quotactl/quotactl06.c @@ -226,9 +226,9 @@ static struct tst_test test = { }, .mntpoint = MNTPOINT, .mount_device = 1, - .needs_cmds = (const char *const []) { - "quotacheck", - NULL + .needs_cmds = (struct tst_cmd[]) { + {.cmd = "quotacheck"}, + {} }, .needs_root = 1, .test_variants = QUOTACTL_FMT_VARIANTS, diff --git a/testcases/kernel/syscalls/quotactl/quotactl08.c b/testcases/kernel/syscalls/quotactl/quotactl08.c index 63087345f..ce7a8b008 100644 --- a/testcases/kernel/syscalls/quotactl/quotactl08.c +++ b/testcases/kernel/syscalls/quotactl/quotactl08.c @@ -220,8 +220,8 @@ static struct tst_test test = { .setup = setup, .cleanup = cleanup, .test_variants = QUOTACTL_SYSCALL_VARIANTS, - .needs_cmds = (const char *[]) { - "mkfs.ext4 >= 1.43.0", - NULL + .needs_cmds = (struct tst_cmd[]) { + {.cmd = "mkfs.ext4 >= 1.43.0"}, + {} } }; diff --git a/testcases/kernel/syscalls/quotactl/quotactl09.c b/testcases/kernel/syscalls/quotactl/quotactl09.c index 673666347..fd6629c0c 100644 --- a/testcases/kernel/syscalls/quotactl/quotactl09.c +++ b/testcases/kernel/syscalls/quotactl/quotactl09.c @@ -185,8 +185,8 @@ static struct tst_test test = { .mount_device = 1, .needs_root = 1, .test_variants = QUOTACTL_SYSCALL_VARIANTS, - .needs_cmds = (const char *[]) { - "mkfs.ext4 >= 1.43.0", - NULL + .needs_cmds = (struct tst_cmd[]) { + {.cmd = "mkfs.ext4 >= 1.43.0"}, + {} } }; diff --git a/testcases/kernel/syscalls/statx/statx05.c b/testcases/kernel/syscalls/statx/statx05.c index 2a4603226..07b5e7b94 100644 --- a/testcases/kernel/syscalls/statx/statx05.c +++ b/testcases/kernel/syscalls/statx/statx05.c @@ -123,9 +123,9 @@ static struct tst_test test = { {.type = "ext4"}, {} }, - .needs_cmds = (const char *[]) { - "mkfs.ext4 >= 1.43.0", - "e4crypt", - NULL + .needs_cmds = (struct tst_cmd[]) { + {.cmd = "mkfs.ext4 >= 1.43.0"}, + {.cmd = "e4crypt"}, + {} } }; diff --git a/testcases/kernel/syscalls/statx/statx07.c b/testcases/kernel/syscalls/statx/statx07.c index bab64591f..755644cf9 100644 --- a/testcases/kernel/syscalls/statx/statx07.c +++ b/testcases/kernel/syscalls/statx/statx07.c @@ -171,8 +171,8 @@ static struct tst_test test = { {} }, .needs_root = 1, - .needs_cmds = (const char *[]) { - "exportfs", - NULL + .needs_cmds = (struct tst_cmd[]) { + {.cmd = "exportfs"}, + {} } }; diff --git a/testcases/kernel/syscalls/statx/statx09.c b/testcases/kernel/syscalls/statx/statx09.c index ee4be4250..8838d5450 100644 --- a/testcases/kernel/syscalls/statx/statx09.c +++ b/testcases/kernel/syscalls/statx/statx09.c @@ -162,8 +162,8 @@ static struct tst_test test = { "CONFIG_FS_VERITY", NULL }, - .needs_cmds = (const char *[]) { - "mkfs.ext4 >= 1.45.2", - NULL + .needs_cmds = (struct tst_cmd[]) { + {.cmd = "mkfs.ext4 >= 1.45.2"}, + {} } }; diff --git a/testcases/lib/tst_run_shell.c b/testcases/lib/tst_run_shell.c index 91f34127d..f3786a4a5 100644 --- a/testcases/lib/tst_run_shell.c +++ b/testcases/lib/tst_run_shell.c @@ -179,6 +179,23 @@ static ujson_obj fs_obj = { .attr_cnt = UJSON_ARRAY_SIZE(fs_attrs), }; +enum cmd_ids { + CMD, + OPTIONAL, + PRESENT, +}; + +static ujson_obj_attr cmd_attrs[] = { + UJSON_OBJ_ATTR_IDX(CMD, "cmd", UJSON_STR), + UJSON_OBJ_ATTR_IDX(OPTIONAL, "optional", UJSON_INT), + UJSON_OBJ_ATTR_IDX(PRESENT, "present", UJSON_INT), +}; + +static ujson_obj cmd_obj = { + .attrs = cmd_attrs, + .attr_cnt = UJSON_ARRAY_SIZE(cmd_attrs), +}; + static int parse_mnt_flags(ujson_reader *reader, ujson_val *val) { int ret = 0; @@ -256,6 +273,48 @@ static struct tst_fs *parse_filesystems(ujson_reader *reader, ujson_val *val) return ret; } +static struct tst_cmd *parse_cmds(ujson_reader *reader, ujson_val *val) +{ + unsigned int i = 0, cnt = 0; + struct tst_cmd *ret; + + ujson_reader_state state = ujson_reader_state_save(reader); + + UJSON_ARR_FOREACH(reader, val) { + if (val->type != UJSON_OBJ) { + ujson_err(reader, "Expected object!"); + return NULL; + } + ujson_obj_skip(reader); + cnt++; + } + + ujson_reader_state_load(reader, state); + + ret = SAFE_MALLOC(sizeof(struct tst_cmd) * (cnt + 1)); + memset(&ret[cnt], 0, sizeof(ret[cnt])); + + UJSON_ARR_FOREACH(reader, val) { + UJSON_OBJ_FOREACH_FILTER(reader, val, &cmd_obj, ujson_empty_obj) { + switch ((enum cmd_ids)val->idx) { + case CMD: + ret[i].cmd = strdup(val->val_str); + break; + case OPTIONAL: + ret[i].optional = val->val_int; + break; + case PRESENT: + ret[i].present = val->val_int; + break; + } + } + + i++; + } + + return ret; +} + static struct tst_tag *parse_tags(ujson_reader *reader, ujson_val *val) { unsigned int i = 0, cnt = 0; @@ -450,7 +509,7 @@ static void parse_metadata(void) ujson_err(&reader, "ABI bits must be 32 or 64"); break; case NEEDS_CMDS: - test.needs_cmds = parse_strarr(&reader, &val); + test.needs_cmds = parse_cmds(&reader, &val); break; case NEEDS_DEVFS: test.needs_devfs = val.val_bool; -- 2.52.0 -- Mailing list info: https://lists.linux.it/listinfo/ltp ^ permalink raw reply related [flat|nested] 100+ messages in thread
* Re: [LTP] [PATCH v6 1/4] lib: Add support option for .needs_cmds 2025-12-23 2:08 ` [LTP] [PATCH v6 1/4] lib: Add support option for .needs_cmds Wei Gao via ltp @ 2026-01-05 13:48 ` Petr Vorel 2026-01-06 10:01 ` Cyril Hrubis 1 sibling, 0 replies; 100+ messages in thread From: Petr Vorel @ 2026-01-05 13:48 UTC (permalink / raw) To: Wei Gao; +Cc: ltp Hi Wei, LGTM now, thanks! Reviewed-by: Petr Vorel <pvorel@suse.cz> Kind regards, Petr -- Mailing list info: https://lists.linux.it/listinfo/ltp ^ permalink raw reply [flat|nested] 100+ messages in thread
* Re: [LTP] [PATCH v6 1/4] lib: Add support option for .needs_cmds 2025-12-23 2:08 ` [LTP] [PATCH v6 1/4] lib: Add support option for .needs_cmds Wei Gao via ltp 2026-01-05 13:48 ` Petr Vorel @ 2026-01-06 10:01 ` Cyril Hrubis 1 sibling, 0 replies; 100+ messages in thread From: Cyril Hrubis @ 2026-01-06 10:01 UTC (permalink / raw) To: Wei Gao; +Cc: ltp Hi! > +enum cmd_ids { > + CMD, > + OPTIONAL, > + PRESENT, > +}; > + > +static ujson_obj_attr cmd_attrs[] = { > + UJSON_OBJ_ATTR_IDX(CMD, "cmd", UJSON_STR), > + UJSON_OBJ_ATTR_IDX(OPTIONAL, "optional", UJSON_INT), > + UJSON_OBJ_ATTR_IDX(PRESENT, "present", UJSON_INT), I do not think that we should add the present attribute to the shell parser, that attribute should never be set by the test and is set by the shell library. The rest looks good. With the "present" attribute removed from the json parser: Reviewed-by: Cyril Hrubis <chrubis@suse.cz> -- Cyril Hrubis chrubis@suse.cz -- Mailing list info: https://lists.linux.it/listinfo/ltp ^ permalink raw reply [flat|nested] 100+ messages in thread
* [LTP] [PATCH v6 2/4] tst_test.c: Add tst_cmd_present check if a command is present 2025-12-23 2:08 ` [LTP] [PATCH v6 0/4] new cmd support option for needs_cmds Wei Gao via ltp 2025-12-23 2:08 ` [LTP] [PATCH v6 1/4] lib: Add support option for .needs_cmds Wei Gao via ltp @ 2025-12-23 2:08 ` Wei Gao via ltp 2026-01-05 13:52 ` Petr Vorel 2026-01-06 10:02 ` Cyril Hrubis 2025-12-23 2:08 ` [LTP] [PATCH v6 3/4] ioctl_loop01.c: Add new support .needs_cmds Wei Gao via ltp ` (2 subsequent siblings) 4 siblings, 2 replies; 100+ messages in thread From: Wei Gao via ltp @ 2025-12-23 2:08 UTC (permalink / raw) To: ltp Signed-off-by: Wei Gao <wegao@suse.com> --- include/tst_test.h | 12 ++++++++++++ lib/tst_test.c | 13 +++++++++++++ 2 files changed, 25 insertions(+) diff --git a/include/tst_test.h b/include/tst_test.h index 38a9d0d54..89dd31582 100644 --- a/include/tst_test.h +++ b/include/tst_test.h @@ -721,6 +721,18 @@ int tst_creat_unlinked(const char *path, int flags, mode_t mode); */ const char *tst_get_tmpdir_root(void); +/** + * tst_cmd_present() - Check if a command is present + * @cmd: The name of the command to check for. + * + * This function iterates through the &tst_test->needs_cmds array. It compares + * the given command name with each entry in the array and returns the + * &tst_cmd->present flag for the matching command. + * + * Return: `true` if the command is present, `false` otherwise. + */ +bool tst_cmd_present(const char *cmd); + /* * Validates exit status of child processes */ diff --git a/lib/tst_test.c b/lib/tst_test.c index 42a54621e..67553f65d 100644 --- a/lib/tst_test.c +++ b/lib/tst_test.c @@ -1365,6 +1365,19 @@ static const char *default_fs_type(void) return tst_dev_fs_type(); } +bool tst_cmd_present(const char *cmd) +{ + struct tst_cmd *pcmd = tst_test->needs_cmds; + + while (pcmd->cmd) { + if (!strcmp(pcmd->cmd, cmd)) + return pcmd->present; + + pcmd++; + } + return false; +} + static void do_setup(int argc, char *argv[]) { char *tdebug_env = getenv("LTP_ENABLE_DEBUG"); -- 2.52.0 -- Mailing list info: https://lists.linux.it/listinfo/ltp ^ permalink raw reply related [flat|nested] 100+ messages in thread
* Re: [LTP] [PATCH v6 2/4] tst_test.c: Add tst_cmd_present check if a command is present 2025-12-23 2:08 ` [LTP] [PATCH v6 2/4] tst_test.c: Add tst_cmd_present check if a command is present Wei Gao via ltp @ 2026-01-05 13:52 ` Petr Vorel 2026-01-06 10:02 ` Cyril Hrubis 1 sibling, 0 replies; 100+ messages in thread From: Petr Vorel @ 2026-01-05 13:52 UTC (permalink / raw) To: Wei Gao; +Cc: ltp Hi Wei, Reviewed-by: Petr Vorel <pvorel@suse.cz> Thanks! Kind regards, Petr -- Mailing list info: https://lists.linux.it/listinfo/ltp ^ permalink raw reply [flat|nested] 100+ messages in thread
* Re: [LTP] [PATCH v6 2/4] tst_test.c: Add tst_cmd_present check if a command is present 2025-12-23 2:08 ` [LTP] [PATCH v6 2/4] tst_test.c: Add tst_cmd_present check if a command is present Wei Gao via ltp 2026-01-05 13:52 ` Petr Vorel @ 2026-01-06 10:02 ` Cyril Hrubis 2026-01-07 6:16 ` Wei Gao via ltp 1 sibling, 1 reply; 100+ messages in thread From: Cyril Hrubis @ 2026-01-06 10:02 UTC (permalink / raw) To: Wei Gao; +Cc: ltp Hi! > /* > * Validates exit status of child processes > */ > diff --git a/lib/tst_test.c b/lib/tst_test.c > index 42a54621e..67553f65d 100644 > --- a/lib/tst_test.c > +++ b/lib/tst_test.c > @@ -1365,6 +1365,19 @@ static const char *default_fs_type(void) > return tst_dev_fs_type(); > } > > +bool tst_cmd_present(const char *cmd) > +{ > + struct tst_cmd *pcmd = tst_test->needs_cmds; > + > + while (pcmd->cmd) { > + if (!strcmp(pcmd->cmd, cmd)) > + return pcmd->present; > + > + pcmd++; > + } > + return false; For a third time, when we get here we asked for something that haven't been tested for so we should tst_brk() here! > +} > + > static void do_setup(int argc, char *argv[]) > { > char *tdebug_env = getenv("LTP_ENABLE_DEBUG"); > -- > 2.52.0 > -- Cyril Hrubis chrubis@suse.cz -- Mailing list info: https://lists.linux.it/listinfo/ltp ^ permalink raw reply [flat|nested] 100+ messages in thread
* Re: [LTP] [PATCH v6 2/4] tst_test.c: Add tst_cmd_present check if a command is present 2026-01-06 10:02 ` Cyril Hrubis @ 2026-01-07 6:16 ` Wei Gao via ltp 2026-01-07 8:09 ` Petr Vorel 2026-01-07 9:56 ` Cyril Hrubis 0 siblings, 2 replies; 100+ messages in thread From: Wei Gao via ltp @ 2026-01-07 6:16 UTC (permalink / raw) To: Cyril Hrubis; +Cc: ltp On Tue, Jan 06, 2026 at 11:02:20AM +0100, Cyril Hrubis wrote: > Hi! > > /* > > * Validates exit status of child processes > > */ > > diff --git a/lib/tst_test.c b/lib/tst_test.c > > index 42a54621e..67553f65d 100644 > > --- a/lib/tst_test.c > > +++ b/lib/tst_test.c > > @@ -1365,6 +1365,19 @@ static const char *default_fs_type(void) > > return tst_dev_fs_type(); > > } > > > > +bool tst_cmd_present(const char *cmd) > > +{ > > + struct tst_cmd *pcmd = tst_test->needs_cmds; > > + > > + while (pcmd->cmd) { > > + if (!strcmp(pcmd->cmd, cmd)) > > + return pcmd->present; > > + > > + pcmd++; > > + } > > + return false; > > For a third time, when we get here we asked for something that haven't > been tested for so we should tst_brk() here! > I think you may have missed my earlier explanation of why we should avoid using tst_brk() here. https://lore.kernel.org/ltp/aT-5tkQkM_g2VZ35@autotest-wegao.qe.prg2.suse.org/ > > +} > > + > > static void do_setup(int argc, char *argv[]) > > { > > char *tdebug_env = getenv("LTP_ENABLE_DEBUG"); > > -- > > 2.52.0 > > > > -- > Cyril Hrubis > chrubis@suse.cz -- Mailing list info: https://lists.linux.it/listinfo/ltp ^ permalink raw reply [flat|nested] 100+ messages in thread
* Re: [LTP] [PATCH v6 2/4] tst_test.c: Add tst_cmd_present check if a command is present 2026-01-07 6:16 ` Wei Gao via ltp @ 2026-01-07 8:09 ` Petr Vorel 2026-01-07 8:27 ` Petr Vorel 2026-01-07 9:56 ` Cyril Hrubis 1 sibling, 1 reply; 100+ messages in thread From: Petr Vorel @ 2026-01-07 8:09 UTC (permalink / raw) To: Wei Gao; +Cc: ltp Hi all, ... > > For a third time, when we get here we asked for something that haven't > > been tested for so we should tst_brk() here! > I think you may have missed my earlier explanation of why we should avoid using tst_brk() here. > https://lore.kernel.org/ltp/aT-5tkQkM_g2VZ35@autotest-wegao.qe.prg2.suse.org/ Wei, I got your point but IMHO you're wrong. I replied to the thread to keep discussion on the same place. https://lore.kernel.org/ltp/20260107080545.GC727950@pevik/ Kind regards, Petr > > -- > > Cyril Hrubis -- Mailing list info: https://lists.linux.it/listinfo/ltp ^ permalink raw reply [flat|nested] 100+ messages in thread
* Re: [LTP] [PATCH v6 2/4] tst_test.c: Add tst_cmd_present check if a command is present 2026-01-07 8:09 ` Petr Vorel @ 2026-01-07 8:27 ` Petr Vorel 2026-01-07 9:59 ` Cyril Hrubis 0 siblings, 1 reply; 100+ messages in thread From: Petr Vorel @ 2026-01-07 8:27 UTC (permalink / raw) To: Wei Gao, Cyril Hrubis, ltp, Li Wang Hi all, > Wei, I got your point but IMHO you're wrong. I replied to the thread to keep > discussion on the same place. > https://lore.kernel.org/ltp/20260107080545.GC727950@pevik/ And besides the discussion why tst_brk() is needed, we need other sanity checks. To summarize sanity checks 1) tst_brk for not checked command at the end. 2) tst_brk for NULL otherwise we get segfault. Maybe check also for empty command before attempting to do anything else. diff --git lib/tst_test.c lib/tst_test.c index bf92e6cc92..cf67c2a9f0 100644 --- lib/tst_test.c +++ lib/tst_test.c @@ -1379,12 +1379,16 @@ bool tst_cmd_present(const char *cmd) { struct tst_cmd *pcmd = tst_test->needs_cmds; + if (!cmd || cmd[0] == '\0') + tst_brk(TBROK, "Invalid cmd"); + while (pcmd->cmd) { if (!strcmp(pcmd->cmd, cmd)) return pcmd->present; pcmd++; } + tst_brk(TBROK, "'%s' not checked", cmd); return false; } 3) Shouldn't we use tst_brk_() to point to the code in the test instead of tst_brk()? If yes, we probably want to have tst_cmd_present_() as library internal (static, with const char *file, const int lineno parameters) which calls tst_brk_() and tst_cmd_present() as public (the only with signature in header). Kind regards, Petr -- Mailing list info: https://lists.linux.it/listinfo/ltp ^ permalink raw reply related [flat|nested] 100+ messages in thread
* Re: [LTP] [PATCH v6 2/4] tst_test.c: Add tst_cmd_present check if a command is present 2026-01-07 8:27 ` Petr Vorel @ 2026-01-07 9:59 ` Cyril Hrubis 2026-01-09 6:11 ` Wei Gao via ltp 2026-01-12 11:05 ` Petr Vorel 0 siblings, 2 replies; 100+ messages in thread From: Cyril Hrubis @ 2026-01-07 9:59 UTC (permalink / raw) To: Petr Vorel; +Cc: ltp Hi! > 1) tst_brk for not checked command at the end. > 2) tst_brk for NULL otherwise we get segfault. Maybe check also for empty > command before attempting to do anything else. Technically the empty command will end up in the tst_brk() at the end, so I would add only the NULL check. > index bf92e6cc92..cf67c2a9f0 100644 > --- lib/tst_test.c > +++ lib/tst_test.c > @@ -1379,12 +1379,16 @@ bool tst_cmd_present(const char *cmd) > { > struct tst_cmd *pcmd = tst_test->needs_cmds; > > + if (!cmd || cmd[0] == '\0') > + tst_brk(TBROK, "Invalid cmd"); > + > while (pcmd->cmd) { > if (!strcmp(pcmd->cmd, cmd)) > return pcmd->present; > > pcmd++; > } > + tst_brk(TBROK, "'%s' not checked", cmd); > return false; > } > > > 3) Shouldn't we use tst_brk_() to point to the code in the test instead of > tst_brk()? If yes, we probably want to have tst_cmd_present_() as library > internal (static, with const char *file, const int lineno parameters) which > calls tst_brk_() and tst_cmd_present() as public (the only with signature in > header). I do not think that this is that important to have, the tst_cmd_present() calls are going to be quite rare and hence easy to locate in the sources. -- Cyril Hrubis chrubis@suse.cz -- Mailing list info: https://lists.linux.it/listinfo/ltp ^ permalink raw reply [flat|nested] 100+ messages in thread
* Re: [LTP] [PATCH v6 2/4] tst_test.c: Add tst_cmd_present check if a command is present 2026-01-07 9:59 ` Cyril Hrubis @ 2026-01-09 6:11 ` Wei Gao via ltp 2026-01-12 11:05 ` Petr Vorel 1 sibling, 0 replies; 100+ messages in thread From: Wei Gao via ltp @ 2026-01-09 6:11 UTC (permalink / raw) To: Cyril Hrubis; +Cc: ltp On Wed, Jan 07, 2026 at 10:59:42AM +0100, Cyril Hrubis wrote: > Hi! > > 1) tst_brk for not checked command at the end. > > 2) tst_brk for NULL otherwise we get segfault. Maybe check also for empty > > command before attempting to do anything else. > > Technically the empty command will end up in the tst_brk() at the end, > so I would add only the NULL check. > > > index bf92e6cc92..cf67c2a9f0 100644 > > --- lib/tst_test.c > > +++ lib/tst_test.c > > @@ -1379,12 +1379,16 @@ bool tst_cmd_present(const char *cmd) > > { > > struct tst_cmd *pcmd = tst_test->needs_cmds; > > > > + if (!cmd || cmd[0] == '\0') > > + tst_brk(TBROK, "Invalid cmd"); > > + > > while (pcmd->cmd) { > > if (!strcmp(pcmd->cmd, cmd)) > > return pcmd->present; > > > > pcmd++; > > } > > + tst_brk(TBROK, "'%s' not checked", cmd); > > return false; > > } > > > > > > 3) Shouldn't we use tst_brk_() to point to the code in the test instead of > > tst_brk()? If yes, we probably want to have tst_cmd_present_() as library > > internal (static, with const char *file, const int lineno parameters) which > > calls tst_brk_() and tst_cmd_present() as public (the only with signature in > > header). > > I do not think that this is that important to have, the > tst_cmd_present() calls are going to be quite rare and hence easy to > locate in the sources. Thanks @Petr @Cyril, will send next patchset. > > -- > Cyril Hrubis > chrubis@suse.cz -- Mailing list info: https://lists.linux.it/listinfo/ltp ^ permalink raw reply [flat|nested] 100+ messages in thread
* Re: [LTP] [PATCH v6 2/4] tst_test.c: Add tst_cmd_present check if a command is present 2026-01-07 9:59 ` Cyril Hrubis 2026-01-09 6:11 ` Wei Gao via ltp @ 2026-01-12 11:05 ` Petr Vorel 1 sibling, 0 replies; 100+ messages in thread From: Petr Vorel @ 2026-01-12 11:05 UTC (permalink / raw) To: Cyril Hrubis; +Cc: ltp > Hi! > > 1) tst_brk for not checked command at the end. > > 2) tst_brk for NULL otherwise we get segfault. Maybe check also for empty > > command before attempting to do anything else. > Technically the empty command will end up in the tst_brk() at the end, > so I would add only the NULL check. Sure, just the message will be a bit confusing: '' not checked. That's why I checked also for empty command. Anyway, v7 is out with cmd[0] == '\0' as well. But it can be removed during merge. https://lore.kernel.org/ltp/20260109061716.20258-3-wegao@suse.com/ > > index bf92e6cc92..cf67c2a9f0 100644 > > --- lib/tst_test.c > > +++ lib/tst_test.c > > @@ -1379,12 +1379,16 @@ bool tst_cmd_present(const char *cmd) > > { > > struct tst_cmd *pcmd = tst_test->needs_cmds; > > + if (!cmd || cmd[0] == '\0') > > + tst_brk(TBROK, "Invalid cmd"); > > + > > while (pcmd->cmd) { > > if (!strcmp(pcmd->cmd, cmd)) > > return pcmd->present; > > pcmd++; > > } > > + tst_brk(TBROK, "'%s' not checked", cmd); > > return false; > > } > > 3) Shouldn't we use tst_brk_() to point to the code in the test instead of > > tst_brk()? If yes, we probably want to have tst_cmd_present_() as library > > internal (static, with const char *file, const int lineno parameters) which > > calls tst_brk_() and tst_cmd_present() as public (the only with signature in > > header). > I do not think that this is that important to have, the > tst_cmd_present() calls are going to be quite rare and hence easy to > locate in the sources. OK, that simplifies things. Kind regards, Petr -- Mailing list info: https://lists.linux.it/listinfo/ltp ^ permalink raw reply [flat|nested] 100+ messages in thread
* Re: [LTP] [PATCH v6 2/4] tst_test.c: Add tst_cmd_present check if a command is present 2026-01-07 6:16 ` Wei Gao via ltp 2026-01-07 8:09 ` Petr Vorel @ 2026-01-07 9:56 ` Cyril Hrubis 1 sibling, 0 replies; 100+ messages in thread From: Cyril Hrubis @ 2026-01-07 9:56 UTC (permalink / raw) To: Wei Gao; +Cc: ltp Hi! > > > +bool tst_cmd_present(const char *cmd) > > > +{ > > > + struct tst_cmd *pcmd = tst_test->needs_cmds; > > > + > > > + while (pcmd->cmd) { > > > + if (!strcmp(pcmd->cmd, cmd)) > > > + return pcmd->present; > > > + > > > + pcmd++; > > > + } > > > + return false; > > > > For a third time, when we get here we asked for something that haven't > > been tested for so we should tst_brk() here! > > > I think you may have missed my earlier explanation of why we should avoid using tst_brk() here. > https://lore.kernel.org/ltp/aT-5tkQkM_g2VZ35@autotest-wegao.qe.prg2.suse.org/ Indeed I missed that one, but that is incorrect, we will get to this point only if we asked for a command that wasn't added to the tst_test.needs_cmds array, which is a programming mistake and test should report TBROK in that case. -- Cyril Hrubis chrubis@suse.cz -- Mailing list info: https://lists.linux.it/listinfo/ltp ^ permalink raw reply [flat|nested] 100+ messages in thread
* [LTP] [PATCH v6 3/4] ioctl_loop01.c: Add new support .needs_cmds 2025-12-23 2:08 ` [LTP] [PATCH v6 0/4] new cmd support option for needs_cmds Wei Gao via ltp 2025-12-23 2:08 ` [LTP] [PATCH v6 1/4] lib: Add support option for .needs_cmds Wei Gao via ltp 2025-12-23 2:08 ` [LTP] [PATCH v6 2/4] tst_test.c: Add tst_cmd_present check if a command is present Wei Gao via ltp @ 2025-12-23 2:08 ` Wei Gao via ltp 2026-01-05 13:56 ` Petr Vorel 2025-12-23 2:08 ` [LTP] [PATCH v6 4/4] shell_loader_cmd.sh: New test case check needs_cmds Wei Gao via ltp 2026-01-09 6:16 ` [LTP] [PATCH v7 0/4] new cmd support option for needs_cmds Wei Gao via ltp 4 siblings, 1 reply; 100+ messages in thread From: Wei Gao via ltp @ 2025-12-23 2:08 UTC (permalink / raw) To: ltp Signed-off-by: Wei Gao <wegao@suse.com> --- .../kernel/syscalls/ioctl/ioctl_loop01.c | 34 +++++++++---------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/testcases/kernel/syscalls/ioctl/ioctl_loop01.c b/testcases/kernel/syscalls/ioctl/ioctl_loop01.c index 9fbdbb1f2..b8df2d633 100644 --- a/testcases/kernel/syscalls/ioctl/ioctl_loop01.c +++ b/testcases/kernel/syscalls/ioctl/ioctl_loop01.c @@ -79,23 +79,6 @@ static void check_loop_value(int set_flag, int get_flag, int autoclear_field) static void verify_ioctl_loop(void) { - int ret; - const char *const cmd_parted[] = {"parted", "-s", dev_path, "mklabel", "msdos", "mkpart", - "primary", "ext4", "1M", "10M", NULL}; - - tst_fill_file("test.img", 0, 1024 * 1024, 10); - tst_attach_device(dev_path, "test.img"); - - ret = tst_cmd(cmd_parted, NULL, NULL, TST_CMD_PASS_RETVAL); - if (!ret) - parted_sup = 1; - else if (ret == 255) - tst_res(TCONF, "parted binary not installed or failed"); - else - tst_res(TCONF, "parted exited with %i", ret); - - attach_flag = 1; - TST_ASSERT_INT(partscan_path, 0); TST_ASSERT_INT(autoclear_path, 0); TST_ASSERT_STR(backing_path, backing_file_path); @@ -114,10 +97,23 @@ static void verify_ioctl_loop(void) static void setup(void) { + parted_sup = tst_cmd_present("parted"); + + const char *const cmd_parted[] = {"parted", "-s", dev_path, "mklabel", "msdos", "mkpart", + "primary", "ext4", "1M", "10M", NULL}; + dev_num = tst_find_free_loopdev(dev_path, sizeof(dev_path)); if (dev_num < 0) tst_brk(TBROK, "Failed to find free loop device"); + tst_fill_file("test.img", 0, 1024 * 1024, 10); + + tst_attach_device(dev_path, "test.img"); + attach_flag = 1; + + if (parted_sup) + SAFE_CMD(cmd_parted, NULL, NULL); + sprintf(partscan_path, "/sys/block/loop%d/loop/partscan", dev_num); sprintf(autoclear_path, "/sys/block/loop%d/loop/autoclear", dev_num); sprintf(backing_path, "/sys/block/loop%d/loop/backing_file", dev_num); @@ -149,5 +145,9 @@ static struct tst_test test = { {"linux-git", "6ac92fb5cdff"}, {} }, + .needs_cmds = (struct tst_cmd[]) { + {.cmd = "parted", .optional = 1}, + {} + }, .needs_tmpdir = 1, }; -- 2.52.0 -- Mailing list info: https://lists.linux.it/listinfo/ltp ^ permalink raw reply related [flat|nested] 100+ messages in thread
* Re: [LTP] [PATCH v6 3/4] ioctl_loop01.c: Add new support .needs_cmds 2025-12-23 2:08 ` [LTP] [PATCH v6 3/4] ioctl_loop01.c: Add new support .needs_cmds Wei Gao via ltp @ 2026-01-05 13:56 ` Petr Vorel 0 siblings, 0 replies; 100+ messages in thread From: Petr Vorel @ 2026-01-05 13:56 UTC (permalink / raw) To: Wei Gao; +Cc: ltp Hi Wei, Reviewed-by: Petr Vorel <pvorel@suse.cz> (The same as in v5, where I added my RBT. FYI you can carry RBT on the commits without changes). Kind regards, Petr -- Mailing list info: https://lists.linux.it/listinfo/ltp ^ permalink raw reply [flat|nested] 100+ messages in thread
* [LTP] [PATCH v6 4/4] shell_loader_cmd.sh: New test case check needs_cmds 2025-12-23 2:08 ` [LTP] [PATCH v6 0/4] new cmd support option for needs_cmds Wei Gao via ltp ` (2 preceding siblings ...) 2025-12-23 2:08 ` [LTP] [PATCH v6 3/4] ioctl_loop01.c: Add new support .needs_cmds Wei Gao via ltp @ 2025-12-23 2:08 ` Wei Gao via ltp 2026-01-05 13:57 ` Petr Vorel 2026-01-09 6:16 ` [LTP] [PATCH v7 0/4] new cmd support option for needs_cmds Wei Gao via ltp 4 siblings, 1 reply; 100+ messages in thread From: Wei Gao via ltp @ 2025-12-23 2:08 UTC (permalink / raw) To: ltp Suggested-by: Petr Vorel <pvorel@suse.cz> Signed-off-by: Wei Gao <wegao@suse.com> --- testcases/lib/run_tests.sh | 1 + testcases/lib/tests/shell_loader_cmd.sh | 28 +++++++++++++++++++++++++ 2 files changed, 29 insertions(+) create mode 100755 testcases/lib/tests/shell_loader_cmd.sh diff --git a/testcases/lib/run_tests.sh b/testcases/lib/run_tests.sh index 5c309bbeb..24ac81a44 100755 --- a/testcases/lib/run_tests.sh +++ b/testcases/lib/run_tests.sh @@ -6,6 +6,7 @@ shell_loader.sh shell_loader_all_filesystems.sh shell_loader_c_child.sh shell_loader_filesystems.sh +shell_loader_cmd.sh shell_loader_kconfigs.sh shell_loader_supported_archs.sh shell_loader_tcnt.sh diff --git a/testcases/lib/tests/shell_loader_cmd.sh b/testcases/lib/tests/shell_loader_cmd.sh new file mode 100755 index 000000000..4e8e61eb6 --- /dev/null +++ b/testcases/lib/tests/shell_loader_cmd.sh @@ -0,0 +1,28 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (c) 2025 Wei Gao <wegao@suse.cz> +# +# --- +# env +# { +# "needs_cmds": [ +# { +# "cmd": "ls", +# "optional": 1 +# }, +# { +# "cmd": "mkfs.ext4 >= 1.0.0", +# "optional": 1 +# } +# ] +# } +# --- + +. tst_loader.sh + +tst_test() +{ + tst_res TPASS "We are running with needs_cmds" +} + +. tst_run.sh -- 2.52.0 -- Mailing list info: https://lists.linux.it/listinfo/ltp ^ permalink raw reply related [flat|nested] 100+ messages in thread
* Re: [LTP] [PATCH v6 4/4] shell_loader_cmd.sh: New test case check needs_cmds 2025-12-23 2:08 ` [LTP] [PATCH v6 4/4] shell_loader_cmd.sh: New test case check needs_cmds Wei Gao via ltp @ 2026-01-05 13:57 ` Petr Vorel 0 siblings, 0 replies; 100+ messages in thread From: Petr Vorel @ 2026-01-05 13:57 UTC (permalink / raw) To: Wei Gao; +Cc: ltp Hi Wei, Reviewed-by: Petr Vorel <pvorel@suse.cz> (The same as in v5, where I added my RBT. FYI you can carry RBT on the commits without changes). Kind regards, Petr -- Mailing list info: https://lists.linux.it/listinfo/ltp ^ permalink raw reply [flat|nested] 100+ messages in thread
* [LTP] [PATCH v7 0/4] new cmd support option for needs_cmds 2025-12-23 2:08 ` [LTP] [PATCH v6 0/4] new cmd support option for needs_cmds Wei Gao via ltp ` (3 preceding siblings ...) 2025-12-23 2:08 ` [LTP] [PATCH v6 4/4] shell_loader_cmd.sh: New test case check needs_cmds Wei Gao via ltp @ 2026-01-09 6:16 ` Wei Gao via ltp 2026-01-09 6:16 ` [LTP] [PATCH v7 1/4] lib: Add support option for .needs_cmds Wei Gao via ltp ` (3 more replies) 4 siblings, 4 replies; 100+ messages in thread From: Wei Gao via ltp @ 2026-01-09 6:16 UTC (permalink / raw) To: ltp v6->v7: 1) Add tst_brk in tst_cmd_present 2) Remove "present" attribute from the json parser Wei Gao (4): lib: Add support option for .needs_cmds tst_test.c: Add tst_cmd_present check if a command is present ioctl_loop01.c: Add new support .needs_cmds shell_loader_cmd.sh: New test case check needs_cmds include/tst_cmd.h | 13 +++++ include/tst_test.h | 16 +++++- lib/newlib_tests/tst_needs_cmds01.c | 16 +++--- lib/newlib_tests/tst_needs_cmds02.c | 6 +- lib/newlib_tests/tst_needs_cmds03.c | 6 +- lib/newlib_tests/tst_needs_cmds04.c | 6 +- lib/newlib_tests/tst_needs_cmds05.c | 6 +- lib/newlib_tests/tst_needs_cmds06.c | 6 +- lib/newlib_tests/tst_needs_cmds07.c | 6 +- lib/newlib_tests/tst_needs_cmds08.c | 8 +-- lib/tst_test.c | 27 +++++++-- testcases/kernel/device-drivers/zram/zram03.c | 8 +-- testcases/kernel/fs/squashfs/squashfs01.c | 6 +- testcases/kernel/security/aslr/aslr01.c | 6 +- testcases/kernel/syscalls/add_key/add_key05.c | 10 ++-- .../kernel/syscalls/fanotify/fanotify22.c | 6 +- testcases/kernel/syscalls/ioctl/ioctl09.c | 6 +- .../kernel/syscalls/ioctl/ioctl_loop01.c | 34 +++++------ testcases/kernel/syscalls/madvise/madvise11.c | 8 +-- .../kernel/syscalls/quotactl/quotactl01.c | 6 +- .../kernel/syscalls/quotactl/quotactl04.c | 6 +- .../kernel/syscalls/quotactl/quotactl06.c | 6 +- .../kernel/syscalls/quotactl/quotactl08.c | 6 +- .../kernel/syscalls/quotactl/quotactl09.c | 6 +- testcases/kernel/syscalls/statx/statx05.c | 8 +-- testcases/kernel/syscalls/statx/statx07.c | 6 +- testcases/kernel/syscalls/statx/statx09.c | 6 +- testcases/lib/run_tests.sh | 1 + testcases/lib/tests/shell_loader_cmd.sh | 28 ++++++++++ testcases/lib/tst_run_shell.c | 56 ++++++++++++++++++- 30 files changed, 231 insertions(+), 104 deletions(-) create mode 100755 testcases/lib/tests/shell_loader_cmd.sh -- 2.52.0 -- Mailing list info: https://lists.linux.it/listinfo/ltp ^ permalink raw reply [flat|nested] 100+ messages in thread
* [LTP] [PATCH v7 1/4] lib: Add support option for .needs_cmds 2026-01-09 6:16 ` [LTP] [PATCH v7 0/4] new cmd support option for needs_cmds Wei Gao via ltp @ 2026-01-09 6:16 ` Wei Gao via ltp 2026-01-09 19:15 ` Petr Vorel ` (2 more replies) 2026-01-09 6:16 ` [LTP] [PATCH v7 2/4] tst_test.c: Add tst_cmd_present check if a command is present Wei Gao via ltp ` (2 subsequent siblings) 3 siblings, 3 replies; 100+ messages in thread From: Wei Gao via ltp @ 2026-01-09 6:16 UTC (permalink / raw) To: ltp Suggested-by: Cyril Hrubis <chrubis@suse.cz> Reviewed-by: Cyril Hrubis <chrubis@suse.cz> Signed-off-by: Wei Gao <wegao@suse.com> --- include/tst_cmd.h | 13 +++++ include/tst_test.h | 4 +- lib/newlib_tests/tst_needs_cmds01.c | 16 +++--- lib/newlib_tests/tst_needs_cmds02.c | 6 +- lib/newlib_tests/tst_needs_cmds03.c | 6 +- lib/newlib_tests/tst_needs_cmds04.c | 6 +- lib/newlib_tests/tst_needs_cmds05.c | 6 +- lib/newlib_tests/tst_needs_cmds06.c | 6 +- lib/newlib_tests/tst_needs_cmds07.c | 6 +- lib/newlib_tests/tst_needs_cmds08.c | 8 +-- lib/tst_test.c | 9 +-- testcases/kernel/device-drivers/zram/zram03.c | 8 +-- testcases/kernel/fs/squashfs/squashfs01.c | 6 +- testcases/kernel/security/aslr/aslr01.c | 6 +- testcases/kernel/syscalls/add_key/add_key05.c | 10 ++-- .../kernel/syscalls/fanotify/fanotify22.c | 6 +- testcases/kernel/syscalls/ioctl/ioctl09.c | 6 +- testcases/kernel/syscalls/madvise/madvise11.c | 8 +-- .../kernel/syscalls/quotactl/quotactl01.c | 6 +- .../kernel/syscalls/quotactl/quotactl04.c | 6 +- .../kernel/syscalls/quotactl/quotactl06.c | 6 +- .../kernel/syscalls/quotactl/quotactl08.c | 6 +- .../kernel/syscalls/quotactl/quotactl09.c | 6 +- testcases/kernel/syscalls/statx/statx05.c | 8 +-- testcases/kernel/syscalls/statx/statx07.c | 6 +- testcases/kernel/syscalls/statx/statx09.c | 6 +- testcases/lib/tst_run_shell.c | 56 ++++++++++++++++++- 27 files changed, 155 insertions(+), 87 deletions(-) diff --git a/include/tst_cmd.h b/include/tst_cmd.h index cf6382955..2203241c5 100644 --- a/include/tst_cmd.h +++ b/include/tst_cmd.h @@ -19,6 +19,19 @@ enum tst_cmd_flags { TST_CMD_TCONF_ON_MISSING = 2, }; +/** + * struct tst_cmd - Provides details about a command struct needed by LTP test. + * @cmd: The name of the command. + * @optional: A flag indicating if the command is optional. + * @present: A flag indicating if the command was found at runtime. This is an output + * parameter, set by the LTP library during the test setup. + */ +struct tst_cmd { + const char *cmd; + unsigned int optional:1; + unsigned int present:1; +}; + /* * vfork() + execvp() specified program. * diff --git a/include/tst_test.h b/include/tst_test.h index 75bc57ab6..dc2e9a397 100644 --- a/include/tst_test.h +++ b/include/tst_test.h @@ -526,7 +526,7 @@ struct tst_fs { * * @tags: A {} terminated array of test tags. See struct tst_tag for details. * - * @needs_cmds: A NULL terminated array of commands required for the test to run. + * @needs_cmds: A NULL terminated array of :ref:`struct tst_cmd` required for the test to run. * * @needs_cgroup_ver: If set the test will run only if the specified cgroup * version is present on the system. @@ -619,7 +619,7 @@ struct tst_fs { const struct tst_tag *tags; - const char *const *needs_cmds; + struct tst_cmd *needs_cmds; const enum tst_cg_ver needs_cgroup_ver; diff --git a/lib/newlib_tests/tst_needs_cmds01.c b/lib/newlib_tests/tst_needs_cmds01.c index 777c69505..6ab1145d1 100644 --- a/lib/newlib_tests/tst_needs_cmds01.c +++ b/lib/newlib_tests/tst_needs_cmds01.c @@ -12,13 +12,13 @@ static void do_test(void) static struct tst_test test = { .test_all = do_test, - .needs_cmds = (const char *[]) { - "mkfs.ext4", - "mkfs.ext4 >= 1.0.0", - "mkfs.ext4 <= 2.0.0", - "mkfs.ext4 != 2.0.0", - "mkfs.ext4 > 1.0.0", - "mkfs.ext4 < 2.0.0", - NULL + .needs_cmds = (struct tst_cmd[]) { + {.cmd = "mkfs.ext4", .optional = 1}, + {.cmd = "mkfs.ext4 >= 1.0.0", .optional = 0}, + {.cmd = "mkfs.ext4 <= 2.0.0"}, + {.cmd = "mkfs.ext4 != 2.0.0"}, + {.cmd = "mkfs.ext4 > 1.0.0"}, + {.cmd = "mkfs.ext4 < 2.0.0"}, + {} } }; diff --git a/lib/newlib_tests/tst_needs_cmds02.c b/lib/newlib_tests/tst_needs_cmds02.c index 455a275ea..f1d6105c2 100644 --- a/lib/newlib_tests/tst_needs_cmds02.c +++ b/lib/newlib_tests/tst_needs_cmds02.c @@ -16,8 +16,8 @@ static void do_test(void) static struct tst_test test = { .test_all = do_test, - .needs_cmds = (const char *[]) { - "mkfs.ext45 >= 1.43.0", - NULL + .needs_cmds = (struct tst_cmd[]) { + {.cmd = "mkfs.ext45 >= 1.43.0"}, + {} } }; diff --git a/lib/newlib_tests/tst_needs_cmds03.c b/lib/newlib_tests/tst_needs_cmds03.c index bdc1cdf6a..ac5f368e2 100644 --- a/lib/newlib_tests/tst_needs_cmds03.c +++ b/lib/newlib_tests/tst_needs_cmds03.c @@ -16,8 +16,8 @@ static void do_test(void) static struct tst_test test = { .test_all = do_test, - .needs_cmds = (const char *[]) { - "mkfs.ext4 ! 1.43.0", - NULL + .needs_cmds = (struct tst_cmd[]) { + {.cmd = "mkfs.ext4 ! 1.43.0"}, + {} } }; diff --git a/lib/newlib_tests/tst_needs_cmds04.c b/lib/newlib_tests/tst_needs_cmds04.c index de10b8f3e..2aea51772 100644 --- a/lib/newlib_tests/tst_needs_cmds04.c +++ b/lib/newlib_tests/tst_needs_cmds04.c @@ -16,8 +16,8 @@ static void do_test(void) static struct tst_test test = { .test_all = do_test, - .needs_cmds = (const char *[]) { - "mkfs.ext4 > 1.43", - NULL + .needs_cmds = (struct tst_cmd[]) { + {.cmd = "mkfs.ext4 > 1.43"}, + {} } }; diff --git a/lib/newlib_tests/tst_needs_cmds05.c b/lib/newlib_tests/tst_needs_cmds05.c index c3b2b3b9a..969d4e2f5 100644 --- a/lib/newlib_tests/tst_needs_cmds05.c +++ b/lib/newlib_tests/tst_needs_cmds05.c @@ -16,8 +16,8 @@ static void do_test(void) static struct tst_test test = { .test_all = do_test, - .needs_cmds = (const char *[]) { - "mkfs.ext4 > 1.43.0-1", - NULL + .needs_cmds = (struct tst_cmd[]) { + {.cmd = "mkfs.ext4 > 1.43.0-1"}, + {} } }; diff --git a/lib/newlib_tests/tst_needs_cmds06.c b/lib/newlib_tests/tst_needs_cmds06.c index 40b1cf09c..91470ccf9 100644 --- a/lib/newlib_tests/tst_needs_cmds06.c +++ b/lib/newlib_tests/tst_needs_cmds06.c @@ -16,8 +16,8 @@ static void do_test(void) static struct tst_test test = { .test_all = do_test, - .needs_cmds = (const char *[]) { - "mkfs.ext4 > 1.43.0 2", - NULL + .needs_cmds = (struct tst_cmd[]) { + {.cmd = "mkfs.ext4 > 1.43.0 2"}, + {} } }; diff --git a/lib/newlib_tests/tst_needs_cmds07.c b/lib/newlib_tests/tst_needs_cmds07.c index d0b4ce2ff..371bbdc1b 100644 --- a/lib/newlib_tests/tst_needs_cmds07.c +++ b/lib/newlib_tests/tst_needs_cmds07.c @@ -16,8 +16,8 @@ static void do_test(void) static struct tst_test test = { .test_all = do_test, - .needs_cmds = (const char *[]) { - "mkfs.ext45", - NULL + .needs_cmds = (struct tst_cmd[]) { + {.cmd = "mkfs.ext45"}, + {} } }; diff --git a/lib/newlib_tests/tst_needs_cmds08.c b/lib/newlib_tests/tst_needs_cmds08.c index 38df2ef6d..412f9f293 100644 --- a/lib/newlib_tests/tst_needs_cmds08.c +++ b/lib/newlib_tests/tst_needs_cmds08.c @@ -18,9 +18,9 @@ static void do_test(void) static struct tst_test test = { .test_all = do_test, - .needs_cmds = (const char *[]) { - "mkfs.xfs", - "mkfs.xfs >= 4.20.0", - NULL + .needs_cmds = (struct tst_cmd[]) { + {.cmd = "mkfs.xfs"}, + {.cmd = "mkfs.xfs >= 4.20.0"}, + {} } }; diff --git a/lib/tst_test.c b/lib/tst_test.c index e115ce689..09aa7fce2 100644 --- a/lib/tst_test.c +++ b/lib/tst_test.c @@ -1449,11 +1449,12 @@ static void do_setup(int argc, char *argv[]) tst_brk(TCONF, "%dbit ABI is not supported", tst_test->needs_abi_bits); if (tst_test->needs_cmds) { - const char *cmd; - int i; + struct tst_cmd *pcmd = tst_test->needs_cmds; - for (i = 0; (cmd = tst_test->needs_cmds[i]); ++i) - tst_check_cmd(cmd, 1); + while (pcmd->cmd) { + pcmd->present = tst_check_cmd(pcmd->cmd, !pcmd->optional) ? 1 : 0; + pcmd++; + } } if (tst_test->needs_drivers) { diff --git a/testcases/kernel/device-drivers/zram/zram03.c b/testcases/kernel/device-drivers/zram/zram03.c index 8cf26de4c..4dcf23b4e 100644 --- a/testcases/kernel/device-drivers/zram/zram03.c +++ b/testcases/kernel/device-drivers/zram/zram03.c @@ -240,9 +240,9 @@ static struct tst_test test = { "zram", NULL }, - .needs_cmds = (const char *[]) { - "modprobe", - "rmmod", - NULL + .needs_cmds = (struct tst_cmd[]) { + {.cmd = "modprobe"}, + {.cmd = "rmmod"}, + {} } }; diff --git a/testcases/kernel/fs/squashfs/squashfs01.c b/testcases/kernel/fs/squashfs/squashfs01.c index fbcb76582..7a548d62c 100644 --- a/testcases/kernel/fs/squashfs/squashfs01.c +++ b/testcases/kernel/fs/squashfs/squashfs01.c @@ -102,9 +102,9 @@ static struct tst_test test = { .needs_root = 1, .needs_device = 1, .dev_min_size = 1, - .needs_cmds = (const char *const []) { - "mksquashfs", - NULL + .needs_cmds = (struct tst_cmd[]) { + {.cmd = "mksquashfs"}, + {} }, .needs_drivers = (const char *const []) { "squashfs", diff --git a/testcases/kernel/security/aslr/aslr01.c b/testcases/kernel/security/aslr/aslr01.c index 6a396e29d..e6feb2d3c 100644 --- a/testcases/kernel/security/aslr/aslr01.c +++ b/testcases/kernel/security/aslr/aslr01.c @@ -277,8 +277,8 @@ static struct tst_test test = { "CONFIG_HAVE_ARCH_MMAP_RND_BITS=y", NULL }, - .needs_cmds = (const char *[]) { - "ldd", - NULL + .needs_cmds = (struct tst_cmd[]) { + {.cmd = "ldd"}, + {} }, }; diff --git a/testcases/kernel/syscalls/add_key/add_key05.c b/testcases/kernel/syscalls/add_key/add_key05.c index c9a2f840e..b51a84b97 100644 --- a/testcases/kernel/syscalls/add_key/add_key05.c +++ b/testcases/kernel/syscalls/add_key/add_key05.c @@ -231,11 +231,11 @@ static struct tst_test test = { {&user_buf, .size = 64}, {} }, - .needs_cmds = (const char *const []) { - "useradd", - "userdel", - "groupdel", - NULL + .needs_cmds = (struct tst_cmd[]) { + {.cmd = "useradd"}, + {.cmd = "userdel"}, + {.cmd = "groupdel"}, + {} }, .tags = (const struct tst_tag[]) { {"linux-git", "a08bf91ce28"}, diff --git a/testcases/kernel/syscalls/fanotify/fanotify22.c b/testcases/kernel/syscalls/fanotify/fanotify22.c index 357e74dbc..6578474a7 100644 --- a/testcases/kernel/syscalls/fanotify/fanotify22.c +++ b/testcases/kernel/syscalls/fanotify/fanotify22.c @@ -327,9 +327,9 @@ static struct tst_test test = { {"linux-git", "76486b104168"}, {} }, - .needs_cmds = (const char *[]) { - "debugfs", - NULL + .needs_cmds = (struct tst_cmd[]) { + {.cmd = "debugfs"}, + {} } }; diff --git a/testcases/kernel/syscalls/ioctl/ioctl09.c b/testcases/kernel/syscalls/ioctl/ioctl09.c index c046d8959..21e16efb6 100644 --- a/testcases/kernel/syscalls/ioctl/ioctl09.c +++ b/testcases/kernel/syscalls/ioctl/ioctl09.c @@ -108,9 +108,9 @@ static struct tst_test test = { "loop", NULL }, - .needs_cmds = (const char *const []) { - "parted", - NULL + .needs_cmds = (struct tst_cmd[]) { + {.cmd = "parted"}, + {} }, .needs_tmpdir = 1, }; diff --git a/testcases/kernel/syscalls/madvise/madvise11.c b/testcases/kernel/syscalls/madvise/madvise11.c index 422589f5b..73d2d4294 100644 --- a/testcases/kernel/syscalls/madvise/madvise11.c +++ b/testcases/kernel/syscalls/madvise/madvise11.c @@ -421,10 +421,10 @@ static struct tst_test test = { HW_MODULE, NULL }, - .needs_cmds = (const char *[]) { - "modprobe", - "rmmod", - NULL + .needs_cmds = (struct tst_cmd[]) { + {.cmd = "modprobe"}, + {.cmd = "rmmod"}, + {} }, .needs_kconfigs = (const char *[]) { "CONFIG_MEMORY_FAILURE=y", diff --git a/testcases/kernel/syscalls/quotactl/quotactl01.c b/testcases/kernel/syscalls/quotactl/quotactl01.c index 9dcf74ceb..3091ac5bf 100644 --- a/testcases/kernel/syscalls/quotactl/quotactl01.c +++ b/testcases/kernel/syscalls/quotactl/quotactl01.c @@ -223,9 +223,9 @@ static struct tst_test test = { {} }, .mntpoint = MNTPOINT, - .needs_cmds = (const char *const []) { - "quotacheck", - NULL + .needs_cmds = (struct tst_cmd[]) { + {.cmd = "quotacheck"}, + {} }, .setup = setup, .cleanup = cleanup, diff --git a/testcases/kernel/syscalls/quotactl/quotactl04.c b/testcases/kernel/syscalls/quotactl/quotactl04.c index d2d7b3f3e..a70903330 100644 --- a/testcases/kernel/syscalls/quotactl/quotactl04.c +++ b/testcases/kernel/syscalls/quotactl/quotactl04.c @@ -165,8 +165,8 @@ static struct tst_test test = { }, .mntpoint = MNTPOINT, .test_variants = QUOTACTL_SYSCALL_VARIANTS, - .needs_cmds = (const char *[]) { - "mkfs.ext4 >= 1.43.0", - NULL + .needs_cmds = (struct tst_cmd[]) { + {.cmd = "mkfs.ext4 >= 1.43.0"}, + {} } }; diff --git a/testcases/kernel/syscalls/quotactl/quotactl06.c b/testcases/kernel/syscalls/quotactl/quotactl06.c index 110a3aa9b..333f5720d 100644 --- a/testcases/kernel/syscalls/quotactl/quotactl06.c +++ b/testcases/kernel/syscalls/quotactl/quotactl06.c @@ -226,9 +226,9 @@ static struct tst_test test = { }, .mntpoint = MNTPOINT, .mount_device = 1, - .needs_cmds = (const char *const []) { - "quotacheck", - NULL + .needs_cmds = (struct tst_cmd[]) { + {.cmd = "quotacheck"}, + {} }, .needs_root = 1, .test_variants = QUOTACTL_FMT_VARIANTS, diff --git a/testcases/kernel/syscalls/quotactl/quotactl08.c b/testcases/kernel/syscalls/quotactl/quotactl08.c index 63087345f..ce7a8b008 100644 --- a/testcases/kernel/syscalls/quotactl/quotactl08.c +++ b/testcases/kernel/syscalls/quotactl/quotactl08.c @@ -220,8 +220,8 @@ static struct tst_test test = { .setup = setup, .cleanup = cleanup, .test_variants = QUOTACTL_SYSCALL_VARIANTS, - .needs_cmds = (const char *[]) { - "mkfs.ext4 >= 1.43.0", - NULL + .needs_cmds = (struct tst_cmd[]) { + {.cmd = "mkfs.ext4 >= 1.43.0"}, + {} } }; diff --git a/testcases/kernel/syscalls/quotactl/quotactl09.c b/testcases/kernel/syscalls/quotactl/quotactl09.c index 673666347..fd6629c0c 100644 --- a/testcases/kernel/syscalls/quotactl/quotactl09.c +++ b/testcases/kernel/syscalls/quotactl/quotactl09.c @@ -185,8 +185,8 @@ static struct tst_test test = { .mount_device = 1, .needs_root = 1, .test_variants = QUOTACTL_SYSCALL_VARIANTS, - .needs_cmds = (const char *[]) { - "mkfs.ext4 >= 1.43.0", - NULL + .needs_cmds = (struct tst_cmd[]) { + {.cmd = "mkfs.ext4 >= 1.43.0"}, + {} } }; diff --git a/testcases/kernel/syscalls/statx/statx05.c b/testcases/kernel/syscalls/statx/statx05.c index 2a4603226..07b5e7b94 100644 --- a/testcases/kernel/syscalls/statx/statx05.c +++ b/testcases/kernel/syscalls/statx/statx05.c @@ -123,9 +123,9 @@ static struct tst_test test = { {.type = "ext4"}, {} }, - .needs_cmds = (const char *[]) { - "mkfs.ext4 >= 1.43.0", - "e4crypt", - NULL + .needs_cmds = (struct tst_cmd[]) { + {.cmd = "mkfs.ext4 >= 1.43.0"}, + {.cmd = "e4crypt"}, + {} } }; diff --git a/testcases/kernel/syscalls/statx/statx07.c b/testcases/kernel/syscalls/statx/statx07.c index bab64591f..755644cf9 100644 --- a/testcases/kernel/syscalls/statx/statx07.c +++ b/testcases/kernel/syscalls/statx/statx07.c @@ -171,8 +171,8 @@ static struct tst_test test = { {} }, .needs_root = 1, - .needs_cmds = (const char *[]) { - "exportfs", - NULL + .needs_cmds = (struct tst_cmd[]) { + {.cmd = "exportfs"}, + {} } }; diff --git a/testcases/kernel/syscalls/statx/statx09.c b/testcases/kernel/syscalls/statx/statx09.c index ee4be4250..8838d5450 100644 --- a/testcases/kernel/syscalls/statx/statx09.c +++ b/testcases/kernel/syscalls/statx/statx09.c @@ -162,8 +162,8 @@ static struct tst_test test = { "CONFIG_FS_VERITY", NULL }, - .needs_cmds = (const char *[]) { - "mkfs.ext4 >= 1.45.2", - NULL + .needs_cmds = (struct tst_cmd[]) { + {.cmd = "mkfs.ext4 >= 1.45.2"}, + {} } }; diff --git a/testcases/lib/tst_run_shell.c b/testcases/lib/tst_run_shell.c index 91f34127d..ddcb606b2 100644 --- a/testcases/lib/tst_run_shell.c +++ b/testcases/lib/tst_run_shell.c @@ -179,6 +179,21 @@ static ujson_obj fs_obj = { .attr_cnt = UJSON_ARRAY_SIZE(fs_attrs), }; +enum cmd_ids { + CMD, + OPTIONAL, +}; + +static ujson_obj_attr cmd_attrs[] = { + UJSON_OBJ_ATTR_IDX(CMD, "cmd", UJSON_STR), + UJSON_OBJ_ATTR_IDX(OPTIONAL, "optional", UJSON_INT), +}; + +static ujson_obj cmd_obj = { + .attrs = cmd_attrs, + .attr_cnt = UJSON_ARRAY_SIZE(cmd_attrs), +}; + static int parse_mnt_flags(ujson_reader *reader, ujson_val *val) { int ret = 0; @@ -256,6 +271,45 @@ static struct tst_fs *parse_filesystems(ujson_reader *reader, ujson_val *val) return ret; } +static struct tst_cmd *parse_cmds(ujson_reader *reader, ujson_val *val) +{ + unsigned int i = 0, cnt = 0; + struct tst_cmd *ret; + + ujson_reader_state state = ujson_reader_state_save(reader); + + UJSON_ARR_FOREACH(reader, val) { + if (val->type != UJSON_OBJ) { + ujson_err(reader, "Expected object!"); + return NULL; + } + ujson_obj_skip(reader); + cnt++; + } + + ujson_reader_state_load(reader, state); + + ret = SAFE_MALLOC(sizeof(struct tst_cmd) * (cnt + 1)); + memset(&ret[cnt], 0, sizeof(ret[cnt])); + + UJSON_ARR_FOREACH(reader, val) { + UJSON_OBJ_FOREACH_FILTER(reader, val, &cmd_obj, ujson_empty_obj) { + switch ((enum cmd_ids)val->idx) { + case CMD: + ret[i].cmd = strdup(val->val_str); + break; + case OPTIONAL: + ret[i].optional = val->val_int; + break; + } + } + + i++; + } + + return ret; +} + static struct tst_tag *parse_tags(ujson_reader *reader, ujson_val *val) { unsigned int i = 0, cnt = 0; @@ -450,7 +504,7 @@ static void parse_metadata(void) ujson_err(&reader, "ABI bits must be 32 or 64"); break; case NEEDS_CMDS: - test.needs_cmds = parse_strarr(&reader, &val); + test.needs_cmds = parse_cmds(&reader, &val); break; case NEEDS_DEVFS: test.needs_devfs = val.val_bool; -- 2.52.0 -- Mailing list info: https://lists.linux.it/listinfo/ltp ^ permalink raw reply related [flat|nested] 100+ messages in thread
* Re: [LTP] [PATCH v7 1/4] lib: Add support option for .needs_cmds 2026-01-09 6:16 ` [LTP] [PATCH v7 1/4] lib: Add support option for .needs_cmds Wei Gao via ltp @ 2026-01-09 19:15 ` Petr Vorel 2026-01-09 19:21 ` Petr Vorel 2026-01-16 14:03 ` Li Wang via ltp 2026-01-19 14:51 ` Cyril Hrubis 2 siblings, 1 reply; 100+ messages in thread From: Petr Vorel @ 2026-01-09 19:15 UTC (permalink / raw) To: Wei Gao; +Cc: ltp Hi Wei, I'm sorry, I merged old patch which unfortunately touched the files you modified. Therefore CI fails. OTOH the basic rule is always rebase to the current master before sending a patch. Please remember this for next time. For now, my fork has your branch rebased: wei/needs_cmds.v7.rebased https://github.com/pevik/ltp/tree/wei/needs_cmds.v7.rebased Thanks for removing present attribute. Reviewed-by: Petr Vorel <pvorel@suse.cz> Kind regards, Petr -- Mailing list info: https://lists.linux.it/listinfo/ltp ^ permalink raw reply [flat|nested] 100+ messages in thread
* Re: [LTP] [PATCH v7 1/4] lib: Add support option for .needs_cmds 2026-01-09 19:15 ` Petr Vorel @ 2026-01-09 19:21 ` Petr Vorel 0 siblings, 0 replies; 100+ messages in thread From: Petr Vorel @ 2026-01-09 19:21 UTC (permalink / raw) To: Wei Gao, ltp, Cyril Hrubis > For now, my fork has your branch rebased: wei/needs_cmds.v7.rebased > https://github.com/pevik/ltp/tree/wei/needs_cmds.v7.rebased And it builds: https://github.com/pevik/ltp/actions/runs/20862658475 @Cyril: from my point ready to merge. Kind regards, Petr -- Mailing list info: https://lists.linux.it/listinfo/ltp ^ permalink raw reply [flat|nested] 100+ messages in thread
* Re: [LTP] [PATCH v7 1/4] lib: Add support option for .needs_cmds 2026-01-09 6:16 ` [LTP] [PATCH v7 1/4] lib: Add support option for .needs_cmds Wei Gao via ltp 2026-01-09 19:15 ` Petr Vorel @ 2026-01-16 14:03 ` Li Wang via ltp 2026-01-19 14:51 ` Cyril Hrubis 2 siblings, 0 replies; 100+ messages in thread From: Li Wang via ltp @ 2026-01-16 14:03 UTC (permalink / raw) To: Wei Gao; +Cc: ltp Reviewed-by: Li Wang <liwang@redhat.com> -- Regards, Li Wang -- Mailing list info: https://lists.linux.it/listinfo/ltp ^ permalink raw reply [flat|nested] 100+ messages in thread
* Re: [LTP] [PATCH v7 1/4] lib: Add support option for .needs_cmds 2026-01-09 6:16 ` [LTP] [PATCH v7 1/4] lib: Add support option for .needs_cmds Wei Gao via ltp 2026-01-09 19:15 ` Petr Vorel 2026-01-16 14:03 ` Li Wang via ltp @ 2026-01-19 14:51 ` Cyril Hrubis 2026-01-20 6:42 ` Petr Vorel 2 siblings, 1 reply; 100+ messages in thread From: Cyril Hrubis @ 2026-01-19 14:51 UTC (permalink / raw) To: Wei Gao; +Cc: ltp Hi! > +enum cmd_ids { > + CMD, > + OPTIONAL, > +}; > + > +static ujson_obj_attr cmd_attrs[] = { > + UJSON_OBJ_ATTR_IDX(CMD, "cmd", UJSON_STR), > + UJSON_OBJ_ATTR_IDX(OPTIONAL, "optional", UJSON_INT), I guess that it would be cleaner to map this to BOOL, and adjust metadata parser to match the value. I guess that I can send a separate patch to adjust these two once this is pushed though. -- Cyril Hrubis chrubis@suse.cz -- Mailing list info: https://lists.linux.it/listinfo/ltp ^ permalink raw reply [flat|nested] 100+ messages in thread
* Re: [LTP] [PATCH v7 1/4] lib: Add support option for .needs_cmds 2026-01-19 14:51 ` Cyril Hrubis @ 2026-01-20 6:42 ` Petr Vorel 0 siblings, 0 replies; 100+ messages in thread From: Petr Vorel @ 2026-01-20 6:42 UTC (permalink / raw) To: Cyril Hrubis; +Cc: ltp > Hi! > > +enum cmd_ids { > > + CMD, > > + OPTIONAL, > > +}; > > + > > +static ujson_obj_attr cmd_attrs[] = { > > + UJSON_OBJ_ATTR_IDX(CMD, "cmd", UJSON_STR), > > + UJSON_OBJ_ATTR_IDX(OPTIONAL, "optional", UJSON_INT), > I guess that it would be cleaner to map this to BOOL, and adjust > metadata parser to match the value. I guess that I can send a separate > patch to adjust these two once this is pushed though. Good point. I also agree to merge this and fix in a follow up. If you add your RBT, I'll merge whole patchset. Kind regards, Petr -- Mailing list info: https://lists.linux.it/listinfo/ltp ^ permalink raw reply [flat|nested] 100+ messages in thread
* [LTP] [PATCH v7 2/4] tst_test.c: Add tst_cmd_present check if a command is present 2026-01-09 6:16 ` [LTP] [PATCH v7 0/4] new cmd support option for needs_cmds Wei Gao via ltp 2026-01-09 6:16 ` [LTP] [PATCH v7 1/4] lib: Add support option for .needs_cmds Wei Gao via ltp @ 2026-01-09 6:16 ` Wei Gao via ltp 2026-01-09 19:17 ` Petr Vorel ` (2 more replies) 2026-01-09 6:16 ` [LTP] [PATCH v7 3/4] ioctl_loop01.c: Add new support .needs_cmds Wei Gao via ltp 2026-01-09 6:16 ` [LTP] [PATCH v7 4/4] shell_loader_cmd.sh: New test case check needs_cmds Wei Gao via ltp 3 siblings, 3 replies; 100+ messages in thread From: Wei Gao via ltp @ 2026-01-09 6:16 UTC (permalink / raw) To: ltp Signed-off-by: Wei Gao <wegao@suse.com> Reviewed-by: Petr Vorel <pvorel@suse.cz> --- include/tst_test.h | 12 ++++++++++++ lib/tst_test.c | 18 ++++++++++++++++++ 2 files changed, 30 insertions(+) diff --git a/include/tst_test.h b/include/tst_test.h index dc2e9a397..d15bf87fd 100644 --- a/include/tst_test.h +++ b/include/tst_test.h @@ -726,6 +726,18 @@ int tst_creat_unlinked(const char *path, int flags, mode_t mode); */ const char *tst_get_tmpdir_root(void); +/** + * tst_cmd_present() - Check if a command is present + * @cmd: The name of the command to check for. + * + * This function iterates through the &tst_test->needs_cmds array. It compares + * the given command name with each entry in the array and returns the + * &tst_cmd->present flag for the matching command. + * + * Return: `true` if the command is present, `false` otherwise. + */ +bool tst_cmd_present(const char *cmd); + /* * Validates exit status of child processes */ diff --git a/lib/tst_test.c b/lib/tst_test.c index 09aa7fce2..0c2bbbbd6 100644 --- a/lib/tst_test.c +++ b/lib/tst_test.c @@ -1375,6 +1375,24 @@ static const char *default_fs_type(void) return tst_dev_fs_type(); } +bool tst_cmd_present(const char *cmd) +{ + struct tst_cmd *pcmd = tst_test->needs_cmds; + + if (!cmd || cmd[0] == '\0') + tst_brk(TBROK, "Invalid cmd"); + + while (pcmd->cmd) { + if (!strcmp(pcmd->cmd, cmd)) + return pcmd->present; + + pcmd++; + } + + tst_brk(TBROK, "'%s' not checked", cmd); + return false; +} + static void do_setup(int argc, char *argv[]) { char *tdebug_env = getenv("LTP_ENABLE_DEBUG"); -- 2.52.0 -- Mailing list info: https://lists.linux.it/listinfo/ltp ^ permalink raw reply related [flat|nested] 100+ messages in thread
* Re: [LTP] [PATCH v7 2/4] tst_test.c: Add tst_cmd_present check if a command is present 2026-01-09 6:16 ` [LTP] [PATCH v7 2/4] tst_test.c: Add tst_cmd_present check if a command is present Wei Gao via ltp @ 2026-01-09 19:17 ` Petr Vorel 2026-01-12 11:08 ` Petr Vorel 2026-01-16 13:58 ` Li Wang via ltp 2026-01-19 13:17 ` Cyril Hrubis 2 siblings, 1 reply; 100+ messages in thread From: Petr Vorel @ 2026-01-09 19:17 UTC (permalink / raw) To: Wei Gao; +Cc: ltp Hi Wei, ... > +++ b/lib/tst_test.c > @@ -1375,6 +1375,24 @@ static const char *default_fs_type(void) > return tst_dev_fs_type(); > } > +bool tst_cmd_present(const char *cmd) > +{ > + struct tst_cmd *pcmd = tst_test->needs_cmds; > + > + if (!cmd || cmd[0] == '\0') > + tst_brk(TBROK, "Invalid cmd"); I'd still prefer tst_brk_() as I described at v6, but that can be done as a separate change. I keep my RBT :). Kind regards, Petr > + > + while (pcmd->cmd) { > + if (!strcmp(pcmd->cmd, cmd)) > + return pcmd->present; > + > + pcmd++; > + } > + > + tst_brk(TBROK, "'%s' not checked", cmd); > + return false; > +} > + > static void do_setup(int argc, char *argv[]) > { > char *tdebug_env = getenv("LTP_ENABLE_DEBUG"); -- Mailing list info: https://lists.linux.it/listinfo/ltp ^ permalink raw reply [flat|nested] 100+ messages in thread
* Re: [LTP] [PATCH v7 2/4] tst_test.c: Add tst_cmd_present check if a command is present 2026-01-09 19:17 ` Petr Vorel @ 2026-01-12 11:08 ` Petr Vorel 0 siblings, 0 replies; 100+ messages in thread From: Petr Vorel @ 2026-01-12 11:08 UTC (permalink / raw) To: Wei Gao, ltp > ... > > +++ b/lib/tst_test.c > > @@ -1375,6 +1375,24 @@ static const char *default_fs_type(void) > > return tst_dev_fs_type(); > > } > > +bool tst_cmd_present(const char *cmd) > > +{ > > + struct tst_cmd *pcmd = tst_test->needs_cmds; > > + > > + if (!cmd || cmd[0] == '\0') > > + tst_brk(TBROK, "Invalid cmd"); > I'd still prefer tst_brk_() as I described at v6, but that can be done as a > separate change. I keep my RBT :). I see Cyril was OK with keeping tst_brk() in v6, I'm sorry to overlook it. https://lore.kernel.org/ltp/aV4ujjfb7JBB2zaQ@yuki.lan/ > Kind regards, > Petr -- Mailing list info: https://lists.linux.it/listinfo/ltp ^ permalink raw reply [flat|nested] 100+ messages in thread
* Re: [LTP] [PATCH v7 2/4] tst_test.c: Add tst_cmd_present check if a command is present 2026-01-09 6:16 ` [LTP] [PATCH v7 2/4] tst_test.c: Add tst_cmd_present check if a command is present Wei Gao via ltp 2026-01-09 19:17 ` Petr Vorel @ 2026-01-16 13:58 ` Li Wang via ltp 2026-01-19 13:17 ` Cyril Hrubis 2 siblings, 0 replies; 100+ messages in thread From: Li Wang via ltp @ 2026-01-16 13:58 UTC (permalink / raw) To: Wei Gao; +Cc: ltp Hi Wei, I don't get the point why we needs seperately define the tst_cmd_present() function, from what I understand, as long as we fill "commands" in the new struct field, that would be completed the check and store the state in .present, right? Shouldn't we use that .present value in testcase directly? On Fri, Jan 9, 2026 at 2:18 PM Wei Gao via ltp <ltp@lists.linux.it> wrote: > > Signed-off-by: Wei Gao <wegao@suse.com> > Reviewed-by: Petr Vorel <pvorel@suse.cz> > --- > include/tst_test.h | 12 ++++++++++++ > lib/tst_test.c | 18 ++++++++++++++++++ > 2 files changed, 30 insertions(+) > > diff --git a/include/tst_test.h b/include/tst_test.h > index dc2e9a397..d15bf87fd 100644 > --- a/include/tst_test.h > +++ b/include/tst_test.h > @@ -726,6 +726,18 @@ int tst_creat_unlinked(const char *path, int flags, mode_t mode); > */ > const char *tst_get_tmpdir_root(void); > > +/** > + * tst_cmd_present() - Check if a command is present > + * @cmd: The name of the command to check for. > + * > + * This function iterates through the &tst_test->needs_cmds array. It compares > + * the given command name with each entry in the array and returns the > + * &tst_cmd->present flag for the matching command. > + * > + * Return: `true` if the command is present, `false` otherwise. > + */ > +bool tst_cmd_present(const char *cmd); > + > /* > * Validates exit status of child processes > */ > diff --git a/lib/tst_test.c b/lib/tst_test.c > index 09aa7fce2..0c2bbbbd6 100644 > --- a/lib/tst_test.c > +++ b/lib/tst_test.c > @@ -1375,6 +1375,24 @@ static const char *default_fs_type(void) > return tst_dev_fs_type(); > } > > +bool tst_cmd_present(const char *cmd) > +{ > + struct tst_cmd *pcmd = tst_test->needs_cmds; > + > + if (!cmd || cmd[0] == '\0') > + tst_brk(TBROK, "Invalid cmd"); > + > + while (pcmd->cmd) { > + if (!strcmp(pcmd->cmd, cmd)) > + return pcmd->present; > + > + pcmd++; > + } > + > + tst_brk(TBROK, "'%s' not checked", cmd); > + return false; > +} > + > static void do_setup(int argc, char *argv[]) > { > char *tdebug_env = getenv("LTP_ENABLE_DEBUG"); > -- > 2.52.0 > > > -- > Mailing list info: https://lists.linux.it/listinfo/ltp > -- Regards, Li Wang -- Mailing list info: https://lists.linux.it/listinfo/ltp ^ permalink raw reply [flat|nested] 100+ messages in thread
* Re: [LTP] [PATCH v7 2/4] tst_test.c: Add tst_cmd_present check if a command is present 2026-01-09 6:16 ` [LTP] [PATCH v7 2/4] tst_test.c: Add tst_cmd_present check if a command is present Wei Gao via ltp 2026-01-09 19:17 ` Petr Vorel 2026-01-16 13:58 ` Li Wang via ltp @ 2026-01-19 13:17 ` Cyril Hrubis 2 siblings, 0 replies; 100+ messages in thread From: Cyril Hrubis @ 2026-01-19 13:17 UTC (permalink / raw) To: Wei Gao; +Cc: ltp Hi! Reviewed-by: Cyril Hrubis <chrubis@suse.cz> -- Cyril Hrubis chrubis@suse.cz -- Mailing list info: https://lists.linux.it/listinfo/ltp ^ permalink raw reply [flat|nested] 100+ messages in thread
* [LTP] [PATCH v7 3/4] ioctl_loop01.c: Add new support .needs_cmds 2026-01-09 6:16 ` [LTP] [PATCH v7 0/4] new cmd support option for needs_cmds Wei Gao via ltp 2026-01-09 6:16 ` [LTP] [PATCH v7 1/4] lib: Add support option for .needs_cmds Wei Gao via ltp 2026-01-09 6:16 ` [LTP] [PATCH v7 2/4] tst_test.c: Add tst_cmd_present check if a command is present Wei Gao via ltp @ 2026-01-09 6:16 ` Wei Gao via ltp 2026-01-16 13:25 ` Li Wang via ltp ` (2 more replies) 2026-01-09 6:16 ` [LTP] [PATCH v7 4/4] shell_loader_cmd.sh: New test case check needs_cmds Wei Gao via ltp 3 siblings, 3 replies; 100+ messages in thread From: Wei Gao via ltp @ 2026-01-09 6:16 UTC (permalink / raw) To: ltp Signed-off-by: Wei Gao <wegao@suse.com> Reviewed-by: Petr Vorel <pvorel@suse.cz> --- .../kernel/syscalls/ioctl/ioctl_loop01.c | 34 +++++++++---------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/testcases/kernel/syscalls/ioctl/ioctl_loop01.c b/testcases/kernel/syscalls/ioctl/ioctl_loop01.c index 9fbdbb1f2..b8df2d633 100644 --- a/testcases/kernel/syscalls/ioctl/ioctl_loop01.c +++ b/testcases/kernel/syscalls/ioctl/ioctl_loop01.c @@ -79,23 +79,6 @@ static void check_loop_value(int set_flag, int get_flag, int autoclear_field) static void verify_ioctl_loop(void) { - int ret; - const char *const cmd_parted[] = {"parted", "-s", dev_path, "mklabel", "msdos", "mkpart", - "primary", "ext4", "1M", "10M", NULL}; - - tst_fill_file("test.img", 0, 1024 * 1024, 10); - tst_attach_device(dev_path, "test.img"); - - ret = tst_cmd(cmd_parted, NULL, NULL, TST_CMD_PASS_RETVAL); - if (!ret) - parted_sup = 1; - else if (ret == 255) - tst_res(TCONF, "parted binary not installed or failed"); - else - tst_res(TCONF, "parted exited with %i", ret); - - attach_flag = 1; - TST_ASSERT_INT(partscan_path, 0); TST_ASSERT_INT(autoclear_path, 0); TST_ASSERT_STR(backing_path, backing_file_path); @@ -114,10 +97,23 @@ static void verify_ioctl_loop(void) static void setup(void) { + parted_sup = tst_cmd_present("parted"); + + const char *const cmd_parted[] = {"parted", "-s", dev_path, "mklabel", "msdos", "mkpart", + "primary", "ext4", "1M", "10M", NULL}; + dev_num = tst_find_free_loopdev(dev_path, sizeof(dev_path)); if (dev_num < 0) tst_brk(TBROK, "Failed to find free loop device"); + tst_fill_file("test.img", 0, 1024 * 1024, 10); + + tst_attach_device(dev_path, "test.img"); + attach_flag = 1; + + if (parted_sup) + SAFE_CMD(cmd_parted, NULL, NULL); + sprintf(partscan_path, "/sys/block/loop%d/loop/partscan", dev_num); sprintf(autoclear_path, "/sys/block/loop%d/loop/autoclear", dev_num); sprintf(backing_path, "/sys/block/loop%d/loop/backing_file", dev_num); @@ -149,5 +145,9 @@ static struct tst_test test = { {"linux-git", "6ac92fb5cdff"}, {} }, + .needs_cmds = (struct tst_cmd[]) { + {.cmd = "parted", .optional = 1}, + {} + }, .needs_tmpdir = 1, }; -- 2.52.0 -- Mailing list info: https://lists.linux.it/listinfo/ltp ^ permalink raw reply related [flat|nested] 100+ messages in thread
* Re: [LTP] [PATCH v7 3/4] ioctl_loop01.c: Add new support .needs_cmds 2026-01-09 6:16 ` [LTP] [PATCH v7 3/4] ioctl_loop01.c: Add new support .needs_cmds Wei Gao via ltp @ 2026-01-16 13:25 ` Li Wang via ltp 2026-01-17 13:16 ` Wei Gao via ltp 2026-01-19 14:57 ` Cyril Hrubis 2026-01-21 13:08 ` Cyril Hrubis 2 siblings, 1 reply; 100+ messages in thread From: Li Wang via ltp @ 2026-01-16 13:25 UTC (permalink / raw) To: Wei Gao; +Cc: ltp > TST_ASSERT_INT(partscan_path, 0); > TST_ASSERT_INT(autoclear_path, 0); > TST_ASSERT_STR(backing_path, backing_file_path); > @@ -114,10 +97,23 @@ static void verify_ioctl_loop(void) > > static void setup(void) > { > + parted_sup = tst_cmd_present("parted"); In the logic of tst_test.c, there already did check and store the value in tst_test->needs_cmds.present, so why here do the check seperately again? + struct tst_cmd *pcmd = tst_test->needs_cmds; + while (pcmd->cmd) { + pcmd->present = tst_check_cmd(pcmd->cmd, !pcmd->optional) ? 1 : 0; + pcmd++; + } > + const char *const cmd_parted[] = {"parted", "-s", dev_path, "mklabel", "msdos", "mkpart", > + "primary", "ext4", "1M", "10M", NULL}; > + > dev_num = tst_find_free_loopdev(dev_path, sizeof(dev_path)); > if (dev_num < 0) > tst_brk(TBROK, "Failed to find free loop device"); > > + tst_fill_file("test.img", 0, 1024 * 1024, 10); > + > + tst_attach_device(dev_path, "test.img"); > + attach_flag = 1; > + > + if (parted_sup) Can we just reuse the 'tst_test->needs_cmds.present' result? > + SAFE_CMD(cmd_parted, NULL, NULL); -- Regards, Li Wang -- Mailing list info: https://lists.linux.it/listinfo/ltp ^ permalink raw reply [flat|nested] 100+ messages in thread
* Re: [LTP] [PATCH v7 3/4] ioctl_loop01.c: Add new support .needs_cmds 2026-01-16 13:25 ` Li Wang via ltp @ 2026-01-17 13:16 ` Wei Gao via ltp 2026-01-19 3:00 ` Li Wang via ltp 0 siblings, 1 reply; 100+ messages in thread From: Wei Gao via ltp @ 2026-01-17 13:16 UTC (permalink / raw) To: Li Wang; +Cc: ltp On Fri, Jan 16, 2026 at 09:25:05PM +0800, Li Wang wrote: > > TST_ASSERT_INT(partscan_path, 0); > > TST_ASSERT_INT(autoclear_path, 0); > > TST_ASSERT_STR(backing_path, backing_file_path); > > @@ -114,10 +97,23 @@ static void verify_ioctl_loop(void) > > > > static void setup(void) > > { > > + parted_sup = tst_cmd_present("parted"); > > > In the logic of tst_test.c, there already did check and store the > value in tst_test->needs_cmds.present, so why here do the check > seperately again? > > + struct tst_cmd *pcmd = tst_test->needs_cmds; > + while (pcmd->cmd) { > + pcmd->present = tst_check_cmd(pcmd->cmd, > !pcmd->optional) ? 1 : 0; > + pcmd++; > + } > Let me clarify, and please correct me if I’m mistaken :) tst_cmd_present not do tst_check_cmd again but just go through list find specific cmd such as "parted" present status. > > > + const char *const cmd_parted[] = {"parted", "-s", dev_path, "mklabel", "msdos", "mkpart", > > + "primary", "ext4", "1M", "10M", NULL}; > > + > > dev_num = tst_find_free_loopdev(dev_path, sizeof(dev_path)); > > if (dev_num < 0) > > tst_brk(TBROK, "Failed to find free loop device"); > > > > + tst_fill_file("test.img", 0, 1024 * 1024, 10); > > + > > + tst_attach_device(dev_path, "test.img"); > > + attach_flag = 1; > > + > > + if (parted_sup) > > Can we just reuse the 'tst_test->needs_cmds.present' result? > You cannot access tst_test->needs_cmds.present directly as if it were a single variable, because needs_cmds is an array (a list) of structures. To get the status of a specific command like "parted", you must iterate through that list to find the entry matching that name. > > + SAFE_CMD(cmd_parted, NULL, NULL); > > > -- > Regards, > Li Wang > -- Mailing list info: https://lists.linux.it/listinfo/ltp ^ permalink raw reply [flat|nested] 100+ messages in thread
* Re: [LTP] [PATCH v7 3/4] ioctl_loop01.c: Add new support .needs_cmds 2026-01-17 13:16 ` Wei Gao via ltp @ 2026-01-19 3:00 ` Li Wang via ltp 2026-01-19 5:34 ` Wei Gao via ltp 0 siblings, 1 reply; 100+ messages in thread From: Li Wang via ltp @ 2026-01-19 3:00 UTC (permalink / raw) To: Wei Gao; +Cc: ltp Wei Gao <wegao@suse.com> wrote: > > > Can we just reuse the 'tst_test->needs_cmds.present' result? > > > You cannot access tst_test->needs_cmds.present directly as if it were a > single variable, > because needs_cmds is an array (a list) of structures. To get the status > of a specific command > like "parted", you must iterate through that list to find the entry > matching that name. > So how about using: tst_test->needs_cmds[0].present? -- Regards, Li Wang -- Mailing list info: https://lists.linux.it/listinfo/ltp ^ permalink raw reply [flat|nested] 100+ messages in thread
* Re: [LTP] [PATCH v7 3/4] ioctl_loop01.c: Add new support .needs_cmds 2026-01-19 3:00 ` Li Wang via ltp @ 2026-01-19 5:34 ` Wei Gao via ltp 2026-01-19 6:27 ` Li Wang via ltp 0 siblings, 1 reply; 100+ messages in thread From: Wei Gao via ltp @ 2026-01-19 5:34 UTC (permalink / raw) To: Li Wang; +Cc: ltp On Mon, Jan 19, 2026 at 11:00:07AM +0800, Li Wang wrote: > Wei Gao <wegao@suse.com> wrote: > > > > > > > Can we just reuse the 'tst_test->needs_cmds.present' result? > > > > > You cannot access tst_test->needs_cmds.present directly as if it were a > > single variable, > > because needs_cmds is an array (a list) of structures. To get the status > > of a specific command > > like "parted", you must iterate through that list to find the entry > > matching that name. > > > > So how about using: tst_test->needs_cmds[0].present? Yes, i think direct indexing is more efficient, but helper function is more readable and extensible(If someone add more entry into .needs_cmds it possible break the test case). I would like to get more feedback on this topic before next patch. @Petr @Cyril ? > > > -- > Regards, > Li Wang -- Mailing list info: https://lists.linux.it/listinfo/ltp ^ permalink raw reply [flat|nested] 100+ messages in thread
* Re: [LTP] [PATCH v7 3/4] ioctl_loop01.c: Add new support .needs_cmds 2026-01-19 5:34 ` Wei Gao via ltp @ 2026-01-19 6:27 ` Li Wang via ltp 0 siblings, 0 replies; 100+ messages in thread From: Li Wang via ltp @ 2026-01-19 6:27 UTC (permalink / raw) To: Wei Gao; +Cc: ltp Wei Gao <wegao@suse.com> wrote: > > > > Can we just reuse the 'tst_test->needs_cmds.present' result? > > > > > > > You cannot access tst_test->needs_cmds.present directly as if it were a > > > single variable, > > > because needs_cmds is an array (a list) of structures. To get the status > > > of a specific command > > > like "parted", you must iterate through that list to find the entry > > > matching that name. > > > > > > > So how about using: tst_test->needs_cmds[0].present? > Yes, i think direct indexing is more efficient, but helper function is more readable > and extensible(If someone add more entry into .needs_cmds it possible break the > test case). Yes, but not entirely, once we have the function tst_cmd_present(), we need to manually write the "commands" again, and easy to typo. Even if we plan to add this feature, perhaps it's better not to place it in tst_test.h or tst_test.c, as that may not be the best fit. We should respect the principle of high cohesion and low coupling. -- Regards, Li Wang -- Mailing list info: https://lists.linux.it/listinfo/ltp ^ permalink raw reply [flat|nested] 100+ messages in thread
* Re: [LTP] [PATCH v7 3/4] ioctl_loop01.c: Add new support .needs_cmds 2026-01-09 6:16 ` [LTP] [PATCH v7 3/4] ioctl_loop01.c: Add new support .needs_cmds Wei Gao via ltp 2026-01-16 13:25 ` Li Wang via ltp @ 2026-01-19 14:57 ` Cyril Hrubis 2026-01-21 13:08 ` Cyril Hrubis 2 siblings, 0 replies; 100+ messages in thread From: Cyril Hrubis @ 2026-01-19 14:57 UTC (permalink / raw) To: Wei Gao; +Cc: ltp Hi! Reviewed-by: Cyril Hrubis <chrubis@suse.cz> -- Cyril Hrubis chrubis@suse.cz -- Mailing list info: https://lists.linux.it/listinfo/ltp ^ permalink raw reply [flat|nested] 100+ messages in thread
* Re: [LTP] [PATCH v7 3/4] ioctl_loop01.c: Add new support .needs_cmds 2026-01-09 6:16 ` [LTP] [PATCH v7 3/4] ioctl_loop01.c: Add new support .needs_cmds Wei Gao via ltp 2026-01-16 13:25 ` Li Wang via ltp 2026-01-19 14:57 ` Cyril Hrubis @ 2026-01-21 13:08 ` Cyril Hrubis 2 siblings, 0 replies; 100+ messages in thread From: Cyril Hrubis @ 2026-01-21 13:08 UTC (permalink / raw) To: Wei Gao; +Cc: ltp Hi! Reviewed-by: Cyril Hrubis <chrubis@suse.cz> -- Cyril Hrubis chrubis@suse.cz -- Mailing list info: https://lists.linux.it/listinfo/ltp ^ permalink raw reply [flat|nested] 100+ messages in thread
* [LTP] [PATCH v7 4/4] shell_loader_cmd.sh: New test case check needs_cmds 2026-01-09 6:16 ` [LTP] [PATCH v7 0/4] new cmd support option for needs_cmds Wei Gao via ltp ` (2 preceding siblings ...) 2026-01-09 6:16 ` [LTP] [PATCH v7 3/4] ioctl_loop01.c: Add new support .needs_cmds Wei Gao via ltp @ 2026-01-09 6:16 ` Wei Gao via ltp 2026-01-21 13:09 ` Cyril Hrubis 3 siblings, 1 reply; 100+ messages in thread From: Wei Gao via ltp @ 2026-01-09 6:16 UTC (permalink / raw) To: ltp Suggested-by: Petr Vorel <pvorel@suse.cz> Signed-off-by: Wei Gao <wegao@suse.com> Reviewed-by: Petr Vorel <pvorel@suse.cz> --- testcases/lib/run_tests.sh | 1 + testcases/lib/tests/shell_loader_cmd.sh | 28 +++++++++++++++++++++++++ 2 files changed, 29 insertions(+) create mode 100755 testcases/lib/tests/shell_loader_cmd.sh diff --git a/testcases/lib/run_tests.sh b/testcases/lib/run_tests.sh index 5c309bbeb..24ac81a44 100755 --- a/testcases/lib/run_tests.sh +++ b/testcases/lib/run_tests.sh @@ -6,6 +6,7 @@ shell_loader.sh shell_loader_all_filesystems.sh shell_loader_c_child.sh shell_loader_filesystems.sh +shell_loader_cmd.sh shell_loader_kconfigs.sh shell_loader_supported_archs.sh shell_loader_tcnt.sh diff --git a/testcases/lib/tests/shell_loader_cmd.sh b/testcases/lib/tests/shell_loader_cmd.sh new file mode 100755 index 000000000..4e8e61eb6 --- /dev/null +++ b/testcases/lib/tests/shell_loader_cmd.sh @@ -0,0 +1,28 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (c) 2025 Wei Gao <wegao@suse.cz> +# +# --- +# env +# { +# "needs_cmds": [ +# { +# "cmd": "ls", +# "optional": 1 +# }, +# { +# "cmd": "mkfs.ext4 >= 1.0.0", +# "optional": 1 +# } +# ] +# } +# --- + +. tst_loader.sh + +tst_test() +{ + tst_res TPASS "We are running with needs_cmds" +} + +. tst_run.sh -- 2.52.0 -- Mailing list info: https://lists.linux.it/listinfo/ltp ^ permalink raw reply related [flat|nested] 100+ messages in thread
* Re: [LTP] [PATCH v7 4/4] shell_loader_cmd.sh: New test case check needs_cmds 2026-01-09 6:16 ` [LTP] [PATCH v7 4/4] shell_loader_cmd.sh: New test case check needs_cmds Wei Gao via ltp @ 2026-01-21 13:09 ` Cyril Hrubis 2026-01-21 13:11 ` Petr Vorel 0 siblings, 1 reply; 100+ messages in thread From: Cyril Hrubis @ 2026-01-21 13:09 UTC (permalink / raw) To: Wei Gao; +Cc: ltp Hi! Reviewed-by: Cyril Hrubis <chrubis@suse.cz> -- Cyril Hrubis chrubis@suse.cz -- Mailing list info: https://lists.linux.it/listinfo/ltp ^ permalink raw reply [flat|nested] 100+ messages in thread
* Re: [LTP] [PATCH v7 4/4] shell_loader_cmd.sh: New test case check needs_cmds 2026-01-21 13:09 ` Cyril Hrubis @ 2026-01-21 13:11 ` Petr Vorel 0 siblings, 0 replies; 100+ messages in thread From: Petr Vorel @ 2026-01-21 13:11 UTC (permalink / raw) To: Cyril Hrubis; +Cc: ltp Hi Cyril, Wei, thanks, merged! Kind regards, Petr -- Mailing list info: https://lists.linux.it/listinfo/ltp ^ permalink raw reply [flat|nested] 100+ messages in thread
* [LTP] [PATCH v2 2/2] ioctl_loop01.c: Update to new .needs_cmds struct 2025-09-28 23:26 ` [LTP] [PATCH v1 0/2] new cmd support option for needs_cmds Wei Gao via ltp 2025-09-28 23:26 ` [LTP] [PATCH v2 1/2] lib: Add support option for .needs_cmds Wei Gao via ltp @ 2025-09-28 23:26 ` Wei Gao via ltp 2025-09-30 13:12 ` Petr Vorel 1 sibling, 1 reply; 100+ messages in thread From: Wei Gao via ltp @ 2025-09-28 23:26 UTC (permalink / raw) To: ltp Suggested-by: Cyril Hrubis <chrubis@suse.cz> Signed-off-by: Wei Gao <wegao@suse.com> --- .../kernel/syscalls/ioctl/ioctl_loop01.c | 23 ++++++++----------- 1 file changed, 9 insertions(+), 14 deletions(-) diff --git a/testcases/kernel/syscalls/ioctl/ioctl_loop01.c b/testcases/kernel/syscalls/ioctl/ioctl_loop01.c index c9137bf1e..70036d6ef 100644 --- a/testcases/kernel/syscalls/ioctl/ioctl_loop01.c +++ b/testcases/kernel/syscalls/ioctl/ioctl_loop01.c @@ -97,9 +97,10 @@ static void verify_ioctl_loop(void) static void setup(void) { - int ret; + parted_sup = tst_cmd_present("parted"); + const char *const cmd_parted[] = {"parted", "-s", "test.img", "mklabel", "msdos", "mkpart", - "primary", "ext4", "1M", "10M", NULL}; + "primary", "ext4", "1M", "10M", NULL}; dev_num = tst_find_free_loopdev(dev_path, sizeof(dev_path)); if (dev_num < 0) @@ -107,18 +108,8 @@ static void setup(void) tst_fill_file("test.img", 0, 1024 * 1024, 10); - ret = tst_cmd(cmd_parted, NULL, NULL, TST_CMD_PASS_RETVAL); - switch (ret) { - case 0: - parted_sup = 1; - break; - case 255: - tst_res(TCONF, "parted binary not installed or failed"); - break; - default: - tst_res(TCONF, "parted exited with %i", ret); - break; - } + if (parted_sup) + SAFE_CMD(cmd_parted, NULL, NULL); sprintf(partscan_path, "/sys/block/loop%d/loop/partscan", dev_num); sprintf(autoclear_path, "/sys/block/loop%d/loop/autoclear", dev_num); @@ -152,5 +143,9 @@ static struct tst_test test = { {"linux-git", "6ac92fb5cdff"}, {} }, + .needs_cmds = (struct tst_cmd[]) { + {.cmd = "parted", .optional = 1}, + {} + }, .needs_tmpdir = 1, }; -- 2.51.0 -- Mailing list info: https://lists.linux.it/listinfo/ltp ^ permalink raw reply related [flat|nested] 100+ messages in thread
* Re: [LTP] [PATCH v2 2/2] ioctl_loop01.c: Update to new .needs_cmds struct 2025-09-28 23:26 ` [LTP] [PATCH v2 2/2] ioctl_loop01.c: Update to new .needs_cmds struct Wei Gao via ltp @ 2025-09-30 13:12 ` Petr Vorel 0 siblings, 0 replies; 100+ messages in thread From: Petr Vorel @ 2025-09-30 13:12 UTC (permalink / raw) To: Wei Gao; +Cc: ltp Hi Wei, ... > +++ b/testcases/kernel/syscalls/ioctl/ioctl_loop01.c > @@ -97,9 +97,10 @@ static void verify_ioctl_loop(void) Patch does not apply, thus CI fail. Please always rebase before sending. > static void setup(void) > { > - int ret; > + parted_sup = tst_cmd_present("parted"); > + > const char *const cmd_parted[] = {"parted", "-s", "test.img", "mklabel", "msdos", "mkpart", > - "primary", "ext4", "1M", "10M", NULL}; > + "primary", "ext4", "1M", "10M", NULL}; This change just changes whitespace. I would avoid it. > dev_num = tst_find_free_loopdev(dev_path, sizeof(dev_path)); > if (dev_num < 0) > @@ -107,18 +108,8 @@ static void setup(void) > tst_fill_file("test.img", 0, 1024 * 1024, 10); > - ret = tst_cmd(cmd_parted, NULL, NULL, TST_CMD_PASS_RETVAL); > - switch (ret) { > - case 0: > - parted_sup = 1; > - break; > - case 255: > - tst_res(TCONF, "parted binary not installed or failed"); > - break; > - default: > - tst_res(TCONF, "parted exited with %i", ret); > - break; > - } > + if (parted_sup) > + SAFE_CMD(cmd_parted, NULL, NULL); > sprintf(partscan_path, "/sys/block/loop%d/loop/partscan", dev_num); > sprintf(autoclear_path, "/sys/block/loop%d/loop/autoclear", dev_num); > @@ -152,5 +143,9 @@ static struct tst_test test = { > {"linux-git", "6ac92fb5cdff"}, > {} > }, > + .needs_cmds = (struct tst_cmd[]) { > + {.cmd = "parted", .optional = 1}, > + {} > + }, Otherwise LGTM. With above fixed: Reviewed-by: Petr Vorel <pvorel@suse.cz> Kind regards, Petr -- Mailing list info: https://lists.linux.it/listinfo/ltp ^ permalink raw reply [flat|nested] 100+ messages in thread
end of thread, other threads:[~2026-01-21 13:11 UTC | newest] Thread overview: 100+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2025-09-26 8:50 [LTP] [PATCH v1 0/2] new cmd support option for needs_cmds Wei Gao via ltp 2025-09-26 8:50 ` [LTP] [PATCH v1 1/2] lib: Add support option for .needs_cmds Wei Gao via ltp 2025-09-26 9:31 ` Cyril Hrubis 2025-09-26 8:50 ` [LTP] [PATCH v1 2/2] ioctl_loop01.c: Update to new .needs_cmds struct Wei Gao via ltp 2025-09-26 9:32 ` Cyril Hrubis 2025-09-28 23:26 ` [LTP] [PATCH v1 0/2] new cmd support option for needs_cmds Wei Gao via ltp 2025-09-28 23:26 ` [LTP] [PATCH v2 1/2] lib: Add support option for .needs_cmds Wei Gao via ltp 2025-09-30 13:36 ` Petr Vorel 2025-10-10 6:32 ` Wei Gao via ltp 2025-10-10 6:45 ` [LTP] [PATCH v3 0/4] new cmd support option for needs_cmds Wei Gao via ltp 2025-10-10 6:45 ` [LTP] [PATCH v3 1/4] lib: Add support option for .needs_cmds Wei Gao via ltp 2025-10-10 9:13 ` Petr Vorel 2025-10-10 9:45 ` Petr Vorel 2025-10-10 6:45 ` [LTP] [PATCH v3 2/4] ioctl_loop01.c: Update to new .needs_cmds struct Wei Gao via ltp 2025-10-10 6:45 ` [LTP] [PATCH v3 3/4] Update test cases use new needs_cmds Wei Gao via ltp 2025-10-10 6:45 ` [LTP] [PATCH v3 4/4] tst_run_shell.c: Add new function handle " Wei Gao via ltp 2025-10-17 10:09 ` [LTP] [PATCH v4 0/3] new cmd support option for needs_cmds Wei Gao via ltp 2025-10-17 10:09 ` [LTP] [PATCH v4 1/3] lib: Add support option for .needs_cmds Wei Gao via ltp 2025-10-17 14:35 ` Petr Vorel 2025-10-20 1:22 ` Wei Gao via ltp 2025-10-20 13:21 ` Petr Vorel 2025-10-21 3:42 ` Wei Gao via ltp 2025-10-22 9:23 ` Li Wang via ltp 2025-10-22 14:19 ` Wei Gao via ltp 2025-10-17 15:37 ` Petr Vorel 2025-10-20 1:24 ` Wei Gao via ltp 2025-10-20 13:33 ` Petr Vorel 2025-10-21 3:17 ` Wei Gao via ltp 2025-10-17 10:09 ` [LTP] [PATCH v4 2/3] Update test cases use new needs_cmds Wei Gao via ltp 2025-10-17 10:09 ` [LTP] [PATCH v4 3/3] tst_run_shell.c: Add new function handle " Wei Gao via ltp 2025-10-17 15:30 ` Petr Vorel 2025-10-17 15:41 ` Petr Vorel 2025-10-20 1:41 ` Wei Gao via ltp 2025-11-07 0:30 ` [LTP] [PATCH v4 0/4] new cmd support option for needs_cmds Wei Gao via ltp 2025-11-07 0:30 ` [LTP] [PATCH v4 1/4] tst_cmd.c: Check brk_nosupp when tst_get_path failed Wei Gao via ltp 2025-11-07 10:33 ` Petr Vorel 2025-11-07 0:30 ` [LTP] [PATCH v4 2/4] lib: Add support option for .needs_cmds Wei Gao via ltp 2025-11-07 0:30 ` [LTP] [PATCH v4 3/4] ioctl_loop01.c: Add new support .needs_cmds Wei Gao via ltp 2025-11-07 11:04 ` Petr Vorel 2025-11-08 12:58 ` Wei Gao via ltp 2025-11-07 0:30 ` [LTP] [PATCH v4 4/4] shell_loader_cmd.sh: New test case check needs_cmds Wei Gao via ltp 2025-11-07 11:41 ` Petr Vorel 2025-11-10 2:47 ` [LTP] [PATCH v5 0/3] new cmd support option for needs_cmds Wei Gao via ltp 2025-11-10 2:47 ` [LTP] [PATCH v5 1/3] lib: Add support option for .needs_cmds Wei Gao via ltp 2025-11-11 11:06 ` Petr Vorel 2025-12-12 10:30 ` Cyril Hrubis 2025-12-12 11:16 ` Petr Vorel 2025-12-15 7:33 ` Wei Gao via ltp 2025-12-15 9:36 ` Petr Vorel 2025-12-15 10:59 ` Wei Gao via ltp 2025-12-17 13:18 ` Petr Vorel 2026-01-07 8:05 ` Petr Vorel 2025-11-10 2:47 ` [LTP] [PATCH v5 2/3] ioctl_loop01.c: Add new support .needs_cmds Wei Gao via ltp 2025-11-11 11:14 ` Petr Vorel 2025-11-10 2:47 ` [LTP] [PATCH v5 3/3] shell_loader_cmd.sh: New test case check needs_cmds Wei Gao via ltp 2025-11-11 10:41 ` Wei Gao via ltp 2025-11-11 11:15 ` Petr Vorel 2025-12-23 2:08 ` [LTP] [PATCH v6 0/4] new cmd support option for needs_cmds Wei Gao via ltp 2025-12-23 2:08 ` [LTP] [PATCH v6 1/4] lib: Add support option for .needs_cmds Wei Gao via ltp 2026-01-05 13:48 ` Petr Vorel 2026-01-06 10:01 ` Cyril Hrubis 2025-12-23 2:08 ` [LTP] [PATCH v6 2/4] tst_test.c: Add tst_cmd_present check if a command is present Wei Gao via ltp 2026-01-05 13:52 ` Petr Vorel 2026-01-06 10:02 ` Cyril Hrubis 2026-01-07 6:16 ` Wei Gao via ltp 2026-01-07 8:09 ` Petr Vorel 2026-01-07 8:27 ` Petr Vorel 2026-01-07 9:59 ` Cyril Hrubis 2026-01-09 6:11 ` Wei Gao via ltp 2026-01-12 11:05 ` Petr Vorel 2026-01-07 9:56 ` Cyril Hrubis 2025-12-23 2:08 ` [LTP] [PATCH v6 3/4] ioctl_loop01.c: Add new support .needs_cmds Wei Gao via ltp 2026-01-05 13:56 ` Petr Vorel 2025-12-23 2:08 ` [LTP] [PATCH v6 4/4] shell_loader_cmd.sh: New test case check needs_cmds Wei Gao via ltp 2026-01-05 13:57 ` Petr Vorel 2026-01-09 6:16 ` [LTP] [PATCH v7 0/4] new cmd support option for needs_cmds Wei Gao via ltp 2026-01-09 6:16 ` [LTP] [PATCH v7 1/4] lib: Add support option for .needs_cmds Wei Gao via ltp 2026-01-09 19:15 ` Petr Vorel 2026-01-09 19:21 ` Petr Vorel 2026-01-16 14:03 ` Li Wang via ltp 2026-01-19 14:51 ` Cyril Hrubis 2026-01-20 6:42 ` Petr Vorel 2026-01-09 6:16 ` [LTP] [PATCH v7 2/4] tst_test.c: Add tst_cmd_present check if a command is present Wei Gao via ltp 2026-01-09 19:17 ` Petr Vorel 2026-01-12 11:08 ` Petr Vorel 2026-01-16 13:58 ` Li Wang via ltp 2026-01-19 13:17 ` Cyril Hrubis 2026-01-09 6:16 ` [LTP] [PATCH v7 3/4] ioctl_loop01.c: Add new support .needs_cmds Wei Gao via ltp 2026-01-16 13:25 ` Li Wang via ltp 2026-01-17 13:16 ` Wei Gao via ltp 2026-01-19 3:00 ` Li Wang via ltp 2026-01-19 5:34 ` Wei Gao via ltp 2026-01-19 6:27 ` Li Wang via ltp 2026-01-19 14:57 ` Cyril Hrubis 2026-01-21 13:08 ` Cyril Hrubis 2026-01-09 6:16 ` [LTP] [PATCH v7 4/4] shell_loader_cmd.sh: New test case check needs_cmds Wei Gao via ltp 2026-01-21 13:09 ` Cyril Hrubis 2026-01-21 13:11 ` Petr Vorel 2025-09-28 23:26 ` [LTP] [PATCH v2 2/2] ioctl_loop01.c: Update to new .needs_cmds struct Wei Gao via ltp 2025-09-30 13:12 ` Petr Vorel
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox