#include <errno.h>
#include <unistd.h>
#include <string.h>
+#include <sys/types.h>
+#include <dirent.h>
#include <sys/wait.h>
+#include <sys/stat.h>
#include "builtin.h"
#include "hist.h"
#include "intlist.h"
#include "debug.h"
#include "color.h"
#include <subcmd/parse-options.h>
+#include "string2.h"
#include "symbol.h"
#include <linux/kernel.h>
+#include <subcmd/exec-cmd.h>
static bool dont_fork;
return err;
}
+static const char *shell_test__description(char *description, size_t size,
+ const char *path, const char *name)
+{
+ FILE *fp;
+ char filename[PATH_MAX];
+
+ path__join(filename, sizeof(filename), path, name);
+ fp = fopen(filename, "r");
+ if (!fp)
+ return NULL;
+
+ description = fgets(description, size, fp);
+ fclose(fp);
+
+ return description ? trim(description + 1) : NULL;
+}
+
+#define for_each_shell_test(dir, ent) \
+ while ((ent = readdir(dir)) != NULL) \
+ if (ent->d_type == DT_REG && ent->d_name[0] != '.')
+
+static const char *shell_tests__dir(char *path, size_t size)
+{
+ const char *devel_dirs[] = { "./tools/perf/tests", "./tests", };
+ char *exec_path;
+ unsigned int i;
+
+ for (i = 0; i < ARRAY_SIZE(devel_dirs); ++i) {
+ struct stat st;
+ if (!lstat(devel_dirs[i], &st)) {
+ scnprintf(path, size, "%s/shell", devel_dirs[i]);
+ if (!lstat(devel_dirs[i], &st))
+ return path;
+ }
+ }
+
+ /* Then installed path. */
+ exec_path = get_argv_exec_path();
+ scnprintf(path, size, "%s/tests/shell", exec_path);
+ free(exec_path);
+ return path;
+}
+
+static int shell_tests__max_desc_width(void)
+{
+ DIR *dir;
+ struct dirent *ent;
+ char path_dir[PATH_MAX];
+ const char *path = shell_tests__dir(path_dir, sizeof(path_dir));
+ int width = 0;
+
+ if (path == NULL)
+ return -1;
+
+ dir = opendir(path);
+ if (!dir)
+ return -1;
+
+ for_each_shell_test(dir, ent) {
+ char bf[256];
+ const char *desc = shell_test__description(bf, sizeof(bf), path, ent->d_name);
+
+ if (desc) {
+ int len = strlen(desc);
+
+ if (width < len)
+ width = len;
+ }
+ }
+
+ closedir(dir);
+ return width;
+}
+
+struct shell_test {
+ const char *dir;
+ const char *file;
+};
+
+static int shell_test__run(struct test *test, int subdir __maybe_unused)
+{
+ int err;
+ char script[PATH_MAX];
+ struct shell_test *st = test->priv;
+
+ path__join(script, sizeof(script), st->dir, st->file);
+
+ err = system(script);
+ if (!err)
+ return TEST_OK;
+
+ return WEXITSTATUS(err) == 2 ? TEST_SKIP : TEST_FAIL;
+}
+
+static int run_shell_tests(int argc, const char *argv[], int i, int width)
+{
+ DIR *dir;
+ struct dirent *ent;
+ char path_dir[PATH_MAX];
+ struct shell_test st = {
+ .dir = shell_tests__dir(path_dir, sizeof(path_dir)),
+ };
+
+ if (st.dir == NULL)
+ return -1;
+
+ dir = opendir(st.dir);
+ if (!dir)
+ return -1;
+
+ for_each_shell_test(dir, ent) {
+ int curr = i++;
+ char desc[256];
+ struct test test = {
+ .desc = shell_test__description(desc, sizeof(desc), st.dir, ent->d_name),
+ .func = shell_test__run,
+ .priv = &st,
+ };
+
+ if (!perf_test__matches(&test, curr, argc, argv))
+ continue;
+
+ st.file = ent->d_name;
+ pr_info("%2d: %-*s:", i, width, test.desc);
+ test_and_print(&test, false, -1);
+ }
+
+ closedir(dir);
+ return 0;
+}
+
static int __cmd_test(int argc, const char *argv[], struct intlist *skiplist)
{
struct test *t;
unsigned int j;
int i = 0;
- int width = 0;
+ int width = shell_tests__max_desc_width();
for_each_test(j, t) {
int len = strlen(t->desc);
}
}
+ return run_shell_tests(argc, argv, i, width);
+}
+
+static int perf_test__list_shell(int argc, const char **argv, int i)
+{
+ DIR *dir;
+ struct dirent *ent;
+ char path_dir[PATH_MAX];
+ const char *path = shell_tests__dir(path_dir, sizeof(path_dir));
+
+ if (path == NULL)
+ return -1;
+
+ dir = opendir(path);
+ if (!dir)
+ return -1;
+
+ for_each_shell_test(dir, ent) {
+ char bf[256];
+ const char *desc = shell_test__description(bf, sizeof(bf), path, ent->d_name);
+
+ ++i;
+
+ if (argc > 1 && !strstr(desc, argv[1]))
+ continue;
+
+ pr_info("%2d: %s\n", i, desc);
+ }
+
+ closedir(dir);
return 0;
}
pr_info("%2d: %s\n", i, t->desc);
}
+ perf_test__list_shell(argc, argv, i);
+
return 0;
}