0001
0002 #include <dirent.h>
0003 #include <errno.h>
0004 #include <fcntl.h>
0005 #include <linux/ctype.h>
0006 #include <linux/kernel.h>
0007 #include <linux/string.h>
0008 #include <linux/zalloc.h>
0009 #include <string.h>
0010 #include <stdlib.h>
0011 #include <sys/types.h>
0012 #include <unistd.h>
0013 #include <subcmd/exec-cmd.h>
0014 #include <subcmd/parse-options.h>
0015 #include <sys/wait.h>
0016 #include <sys/stat.h>
0017 #include "builtin.h"
0018 #include "builtin-test-list.h"
0019 #include "color.h"
0020 #include "debug.h"
0021 #include "hist.h"
0022 #include "intlist.h"
0023 #include "string2.h"
0024 #include "symbol.h"
0025 #include "tests.h"
0026 #include "util/rlimit.h"
0027
0028
0029
0030
0031
0032
0033
0034 static size_t files_num = 0;
0035 static struct script_file *files = NULL;
0036 static int files_max_width = 0;
0037
0038 static const char *shell_tests__dir(char *path, size_t size)
0039 {
0040 const char *devel_dirs[] = { "./tools/perf/tests", "./tests", };
0041 char *exec_path;
0042 unsigned int i;
0043
0044 for (i = 0; i < ARRAY_SIZE(devel_dirs); ++i) {
0045 struct stat st;
0046
0047 if (!lstat(devel_dirs[i], &st)) {
0048 scnprintf(path, size, "%s/shell", devel_dirs[i]);
0049 if (!lstat(devel_dirs[i], &st))
0050 return path;
0051 }
0052 }
0053
0054
0055 exec_path = get_argv_exec_path();
0056 scnprintf(path, size, "%s/tests/shell", exec_path);
0057 free(exec_path);
0058 return path;
0059 }
0060
0061 static const char *shell_test__description(char *description, size_t size,
0062 const char *path, const char *name)
0063 {
0064 FILE *fp;
0065 char filename[PATH_MAX];
0066 int ch;
0067
0068 path__join(filename, sizeof(filename), path, name);
0069 fp = fopen(filename, "r");
0070 if (!fp)
0071 return NULL;
0072
0073
0074 do {
0075 ch = fgetc(fp);
0076 } while (ch != EOF && ch != '\n');
0077
0078 description = fgets(description, size, fp);
0079 fclose(fp);
0080
0081
0082 return description ? strim(description + 1) : NULL;
0083 }
0084
0085
0086 static bool is_shell_script(const char *path)
0087 {
0088 const char *ext;
0089
0090 ext = strrchr(path, '.');
0091 if (!ext)
0092 return false;
0093 if (!strcmp(ext, ".sh")) {
0094 if (access(path, R_OK | X_OK) == 0)
0095 return true;
0096 }
0097 return false;
0098 }
0099
0100
0101 static bool is_test_script(const char *path, const char *name)
0102 {
0103 char filename[PATH_MAX];
0104
0105 path__join(filename, sizeof(filename), path, name);
0106 if (!is_shell_script(filename)) return false;
0107 return true;
0108 }
0109
0110
0111 static char *strdup_check(const char *str)
0112 {
0113 char *newstr;
0114
0115 newstr = strdup(str);
0116 if (!newstr) {
0117 pr_err("Out of memory while duplicating test script string\n");
0118 abort();
0119 }
0120 return newstr;
0121 }
0122
0123 static void append_script(const char *dir, const char *file, const char *desc)
0124 {
0125 struct script_file *files_tmp;
0126 size_t files_num_tmp;
0127 int width;
0128
0129 files_num_tmp = files_num + 1;
0130 if (files_num_tmp >= SIZE_MAX) {
0131 pr_err("Too many script files\n");
0132 abort();
0133 }
0134
0135
0136 files_tmp = realloc(files,
0137 (files_num_tmp + 1) * sizeof(struct script_file));
0138 if (files_tmp == NULL) {
0139 pr_err("Out of memory while building test list\n");
0140 abort();
0141 }
0142
0143 files = files_tmp;
0144 files_num = files_num_tmp;
0145 files[files_num - 1].dir = strdup_check(dir);
0146 files[files_num - 1].file = strdup_check(file);
0147 files[files_num - 1].desc = strdup_check(desc);
0148 files[files_num].dir = NULL;
0149 files[files_num].file = NULL;
0150 files[files_num].desc = NULL;
0151
0152 width = strlen(desc);
0153 if (width > files_max_width)
0154 files_max_width = width;
0155 }
0156
0157 static void append_scripts_in_dir(const char *path)
0158 {
0159 struct dirent **entlist;
0160 struct dirent *ent;
0161 int n_dirs, i;
0162 char filename[PATH_MAX];
0163
0164
0165 n_dirs = scandir(path, &entlist, NULL, alphasort);
0166 if (n_dirs == -1)
0167 return;
0168 for (i = 0; i < n_dirs && (ent = entlist[i]); i++) {
0169 if (ent->d_name[0] == '.')
0170 continue;
0171 if (is_test_script(path, ent->d_name)) {
0172 char bf[256];
0173 const char *desc = shell_test__description
0174 (bf, sizeof(bf), path, ent->d_name);
0175
0176 if (desc)
0177 append_script(path, ent->d_name, desc);
0178 } else if (is_directory(path, ent)) {
0179 path__join(filename, sizeof(filename),
0180 path, ent->d_name);
0181 append_scripts_in_dir(filename);
0182 }
0183 }
0184 for (i = 0; i < n_dirs; i++)
0185 zfree(&entlist[i]);
0186 free(entlist);
0187 }
0188
0189 const struct script_file *list_script_files(void)
0190 {
0191 char path_dir[PATH_MAX];
0192 const char *path;
0193
0194 if (files)
0195 return files;
0196
0197 path = shell_tests__dir(path_dir, sizeof(path_dir));
0198 append_scripts_in_dir(path);
0199
0200 return files;
0201 }
0202
0203 int list_script_max_width(void)
0204 {
0205 list_script_files();
0206 return files_max_width;
0207 }