perf test: Iterate over shell tests in alphabetical order

The for_each_shell_test macro iterated over all shell tests in the
directory using readdir, which does not guarantee any ordering, causing
problems on certain fs. However, the order in which they are visited
determines the id of the test, in case one wants to run a single test.

This patch replaces readdir with scandir using alphabetical sorting.
This guarantees that, given the same set of tests, all machines will
see the tests in the same order, and, thus, that test ids are
consistent.

Signed-off-by: Riccardo Mancini <rickyman7@gmail.com>
Reported-by: Ian Rogers <irogers@google.com>
Acked-by: Ian Rogers <irogers@google.com>
Acked-by: Jiri Olsa <jolsa@redhat.com>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Fabian Hemmer <copy@copy.sh>
Cc: Leo Yan <leo.yan@linaro.org>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Stephane Eranian <eranian@google.com>
Cc: Tommi Rantala <tommi.t.rantala@nokia.com>
Link: http://lore.kernel.org/lkml/20210525230521.244553-1-rickyman7@gmail.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
This commit is contained in:
Riccardo Mancini 2021-05-26 01:05:17 +02:00 committed by Arnaldo Carvalho de Melo
parent 41ca1d1e88
commit da963834fe

View file

@ -510,8 +510,8 @@ static const char *shell_test__description(char *description, size_t size,
return description ? strim(description + 1) : NULL; return description ? strim(description + 1) : NULL;
} }
#define for_each_shell_test(dir, base, ent) \ #define for_each_shell_test(entlist, nr, base, ent) \
while ((ent = readdir(dir)) != NULL) \ for (int __i = 0; __i < nr && (ent = entlist[__i]); __i++) \
if (!is_directory(base, ent) && ent->d_name[0] != '.') if (!is_directory(base, ent) && ent->d_name[0] != '.')
static const char *shell_tests__dir(char *path, size_t size) static const char *shell_tests__dir(char *path, size_t size)
@ -538,8 +538,9 @@ static const char *shell_tests__dir(char *path, size_t size)
static int shell_tests__max_desc_width(void) static int shell_tests__max_desc_width(void)
{ {
DIR *dir; struct dirent **entlist;
struct dirent *ent; struct dirent *ent;
int n_dirs;
char path_dir[PATH_MAX]; char path_dir[PATH_MAX];
const char *path = shell_tests__dir(path_dir, sizeof(path_dir)); const char *path = shell_tests__dir(path_dir, sizeof(path_dir));
int width = 0; int width = 0;
@ -547,11 +548,11 @@ static int shell_tests__max_desc_width(void)
if (path == NULL) if (path == NULL)
return -1; return -1;
dir = opendir(path); n_dirs = scandir(path, &entlist, NULL, alphasort);
if (!dir) if (n_dirs == -1)
return -1; return -1;
for_each_shell_test(dir, path, ent) { for_each_shell_test(entlist, n_dirs, path, ent) {
char bf[256]; char bf[256];
const char *desc = shell_test__description(bf, sizeof(bf), path, ent->d_name); const char *desc = shell_test__description(bf, sizeof(bf), path, ent->d_name);
@ -563,7 +564,8 @@ static int shell_tests__max_desc_width(void)
} }
} }
closedir(dir); free(entlist);
return width; return width;
} }
@ -589,8 +591,9 @@ static int shell_test__run(struct test *test, int subdir __maybe_unused)
static int run_shell_tests(int argc, const char *argv[], int i, int width) static int run_shell_tests(int argc, const char *argv[], int i, int width)
{ {
DIR *dir; struct dirent **entlist;
struct dirent *ent; struct dirent *ent;
int n_dirs;
char path_dir[PATH_MAX]; char path_dir[PATH_MAX];
struct shell_test st = { struct shell_test st = {
.dir = shell_tests__dir(path_dir, sizeof(path_dir)), .dir = shell_tests__dir(path_dir, sizeof(path_dir)),
@ -599,14 +602,14 @@ static int run_shell_tests(int argc, const char *argv[], int i, int width)
if (st.dir == NULL) if (st.dir == NULL)
return -1; return -1;
dir = opendir(st.dir); n_dirs = scandir(st.dir, &entlist, NULL, alphasort);
if (!dir) { if (n_dirs == -1) {
pr_err("failed to open shell test directory: %s\n", pr_err("failed to open shell test directory: %s\n",
st.dir); st.dir);
return -1; return -1;
} }
for_each_shell_test(dir, st.dir, ent) { for_each_shell_test(entlist, n_dirs, st.dir, ent) {
int curr = i++; int curr = i++;
char desc[256]; char desc[256];
struct test test = { struct test test = {
@ -623,7 +626,7 @@ static int run_shell_tests(int argc, const char *argv[], int i, int width)
test_and_print(&test, false, -1); test_and_print(&test, false, -1);
} }
closedir(dir); free(entlist);
return 0; return 0;
} }
@ -722,19 +725,20 @@ static int __cmd_test(int argc, const char *argv[], struct intlist *skiplist)
static int perf_test__list_shell(int argc, const char **argv, int i) static int perf_test__list_shell(int argc, const char **argv, int i)
{ {
DIR *dir; struct dirent **entlist;
struct dirent *ent; struct dirent *ent;
int n_dirs;
char path_dir[PATH_MAX]; char path_dir[PATH_MAX];
const char *path = shell_tests__dir(path_dir, sizeof(path_dir)); const char *path = shell_tests__dir(path_dir, sizeof(path_dir));
if (path == NULL) if (path == NULL)
return -1; return -1;
dir = opendir(path); n_dirs = scandir(path, &entlist, NULL, alphasort);
if (!dir) if (n_dirs == -1)
return -1; return -1;
for_each_shell_test(dir, path, ent) { for_each_shell_test(entlist, n_dirs, path, ent) {
int curr = i++; int curr = i++;
char bf[256]; char bf[256];
struct test t = { struct test t = {
@ -747,7 +751,7 @@ static int perf_test__list_shell(int argc, const char **argv, int i)
pr_info("%2d: %s\n", i, t.desc); pr_info("%2d: %s\n", i, t.desc);
} }
closedir(dir); free(entlist);
return 0; return 0;
} }