Skip to content

Commit

Permalink
perf test: Add infrastructure to run shell based tests
Browse files Browse the repository at this point in the history
To allow testing by directly using perf tools in scripts, checking that
the effects on the system are the ones expected and that the output
produced is as well the desired one.

For instance, adding a probe at a well known location with 'perf probe',
then checking that the results from using that probe to record are the
desired ones, etc.

The next csets will introduce tests using this new testing
infrastructure.

The scripts should return 0 for Ok, 1 for FAIL and 2 for SKIP.

Cc: Adrian Hunter <[email protected]>
Cc: David Ahern <[email protected]>
Cc: Jiri Olsa <[email protected]>
Cc: Michael Petlan <[email protected]>
Cc: Namhyung Kim <[email protected]>
Cc: Thomas Richter <[email protected]>
Cc: Wang Nan <[email protected]>
Link: http://lkml.kernel.org/n/[email protected]
Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
  • Loading branch information
acmel committed Aug 11, 2017
1 parent 81f17c9 commit 1209b27
Show file tree
Hide file tree
Showing 2 changed files with 170 additions and 1 deletion.
170 changes: 169 additions & 1 deletion tools/perf/tests/builtin-test.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,21 @@
#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 "tests.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;

Expand Down Expand Up @@ -383,12 +388,143 @@ static int test_and_print(struct test *t, bool force_skip, int subtest)
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);
Expand Down Expand Up @@ -455,6 +591,36 @@ static int __cmd_test(int argc, const char *argv[], struct intlist *skiplist)
}
}

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;
}

Expand All @@ -473,6 +639,8 @@ static int perf_test__list(int argc, const char **argv)
pr_info("%2d: %s\n", i, t->desc);
}

perf_test__list_shell(argc, argv, i);

return 0;
}

Expand Down
1 change: 1 addition & 0 deletions tools/perf/tests/tests.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ struct test {
const char *(*get_desc)(int subtest);
} subtest;
bool (*is_supported)(void);
void *priv;
};

/* Tests */
Expand Down

0 comments on commit 1209b27

Please sign in to comment.