diff options
author | Andi Kleen <ak@linux.intel.com> | 2017-03-20 21:17:05 +0100 |
---|---|---|
committer | Arnaldo Carvalho de Melo <acme@redhat.com> | 2017-03-23 15:39:27 +0100 |
commit | 075167363f8b53ade702cd83f5818eb47119b659 (patch) | |
tree | 9db9e13f8085f1a03f4e3fd47dcb902e7a11a727 /tools/perf/tests | |
parent | perf pmu: Special case uncore_ prefix (diff) | |
download | linux-075167363f8b53ade702cd83f5818eb47119b659.tar.xz linux-075167363f8b53ade702cd83f5818eb47119b659.zip |
perf tools: Add a simple expression parser for JSON
Add a simple expression parser good enough to parse JSON relation
expressions. The parser is implemented using bison.
This is just intended as an simple parser for internal usage in the
event lists, not the beginning of a "perf scripting language"
v2: Use expr__ prefix instead of expr_
Support multiple free variables for parser
Committer note:
The v2 patch had:
%define api.pure full
In expr.y, that is a feature introduced in bison 2.7, to have reentrant
parsers, not using global variables, which would make tools/perf stop
building with the bison version shipped in older distros, so Andi
realised that the other parsers (e.g. parse-events.y) were using:
%pure-parser
Which is present in older versions of bison and fits the bill.
I added:
CFLAGS_expr-bison.o += -DYYENABLE_NLS=0 -DYYLTYPE_IS_TRIVIAL=0 -w
To finally make it build, copying what was there for pmu-bison.o,
another parser.
Signed-off-by: Andi Kleen <ak@linux.intel.com>
Acked-by: Jiri Olsa <jolsa@kernel.org>
Link: http://lkml.kernel.org/r/20170320201711.14142-8-andi@firstfloor.org
[ stdlib.h is needed in tests/expr.c for free() fixing build in systems such as ubuntu:16.04-x-s390 ]
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Diffstat (limited to 'tools/perf/tests')
-rw-r--r-- | tools/perf/tests/Build | 1 | ||||
-rw-r--r-- | tools/perf/tests/builtin-test.c | 4 | ||||
-rw-r--r-- | tools/perf/tests/expr.c | 56 | ||||
-rw-r--r-- | tools/perf/tests/tests.h | 1 |
4 files changed, 62 insertions, 0 deletions
diff --git a/tools/perf/tests/Build b/tools/perf/tests/Build index 1cb3d9b540e9..af58ebc243ef 100644 --- a/tools/perf/tests/Build +++ b/tools/perf/tests/Build @@ -38,6 +38,7 @@ perf-y += cpumap.o perf-y += stat.o perf-y += event_update.o perf-y += event-times.o +perf-y += expr.o perf-y += backward-ring-buffer.o perf-y += sdt.o perf-y += is_printable_array.o diff --git a/tools/perf/tests/builtin-test.c b/tools/perf/tests/builtin-test.c index 83c4669cbc5b..86822969e8a8 100644 --- a/tools/perf/tests/builtin-test.c +++ b/tools/perf/tests/builtin-test.c @@ -44,6 +44,10 @@ static struct test generic_tests[] = { .func = test__parse_events, }, { + .desc = "Simple expression parser", + .func = test__expr, + }, + { .desc = "PERF_RECORD_* events & perf_sample fields", .func = test__PERF_RECORD, }, diff --git a/tools/perf/tests/expr.c b/tools/perf/tests/expr.c new file mode 100644 index 000000000000..6c6a3749aaf6 --- /dev/null +++ b/tools/perf/tests/expr.c @@ -0,0 +1,56 @@ +#include "util/debug.h" +#include "util/expr.h" +#include "tests.h" +#include <stdlib.h> + +static int test(struct parse_ctx *ctx, const char *e, double val2) +{ + double val; + + if (expr__parse(&val, ctx, &e)) + TEST_ASSERT_VAL("parse test failed", 0); + TEST_ASSERT_VAL("unexpected value", val == val2); + return 0; +} + +int test__expr(int subtest __maybe_unused) +{ + const char *p; + const char **other; + double val; + int ret; + struct parse_ctx ctx; + int num_other; + + expr__ctx_init(&ctx); + expr__add_id(&ctx, "FOO", 1); + expr__add_id(&ctx, "BAR", 2); + + ret = test(&ctx, "1+1", 2); + ret |= test(&ctx, "FOO+BAR", 3); + ret |= test(&ctx, "(BAR/2)%2", 1); + ret |= test(&ctx, "1 - -4", 5); + ret |= test(&ctx, "(FOO-1)*2 + (BAR/2)%2 - -4", 5); + + if (ret) + return ret; + + p = "FOO/0"; + ret = expr__parse(&val, &ctx, &p); + TEST_ASSERT_VAL("division by zero", ret == 1); + + p = "BAR/"; + ret = expr__parse(&val, &ctx, &p); + TEST_ASSERT_VAL("missing operand", ret == 1); + + TEST_ASSERT_VAL("find other", + expr__find_other("FOO + BAR + BAZ + BOZO", "FOO", &other, &num_other) == 0); + TEST_ASSERT_VAL("find other", num_other == 3); + TEST_ASSERT_VAL("find other", !strcmp(other[0], "BAR")); + TEST_ASSERT_VAL("find other", !strcmp(other[1], "BAZ")); + TEST_ASSERT_VAL("find other", !strcmp(other[2], "BOZO")); + TEST_ASSERT_VAL("find other", other[3] == NULL); + free((void *)other); + + return 0; +} diff --git a/tools/perf/tests/tests.h b/tools/perf/tests/tests.h index 1fa9b9d83aa5..631859629403 100644 --- a/tools/perf/tests/tests.h +++ b/tools/perf/tests/tests.h @@ -62,6 +62,7 @@ int test__sample_parsing(int subtest); int test__keep_tracking(int subtest); int test__parse_no_sample_id_all(int subtest); int test__dwarf_unwind(int subtest); +int test__expr(int subtest); int test__hists_filter(int subtest); int test__mmap_thread_lookup(int subtest); int test__thread_mg_share(int subtest); |