1b2441318SGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0 209b73fe9SIan Rogers #include "util/cputopo.h" 307516736SAndi Kleen #include "util/debug.h" 407516736SAndi Kleen #include "util/expr.h" 56923397cSIan Rogers #include "util/header.h" 6a8e4e880SIan Rogers #include "util/smt.h" 707516736SAndi Kleen #include "tests.h" 86923397cSIan Rogers #include <math.h> 907516736SAndi Kleen #include <stdlib.h> 108520a98dSArnaldo Carvalho de Melo #include <string.h> 11d8f9da24SArnaldo Carvalho de Melo #include <linux/zalloc.h> 1207516736SAndi Kleen 13114a9d6eSIan Rogers static int test_ids_union(void) 14114a9d6eSIan Rogers { 15114a9d6eSIan Rogers struct hashmap *ids1, *ids2; 16114a9d6eSIan Rogers 17114a9d6eSIan Rogers /* Empty union. */ 18114a9d6eSIan Rogers ids1 = ids__new(); 19114a9d6eSIan Rogers TEST_ASSERT_VAL("ids__new", ids1); 20114a9d6eSIan Rogers ids2 = ids__new(); 21114a9d6eSIan Rogers TEST_ASSERT_VAL("ids__new", ids2); 22114a9d6eSIan Rogers 23114a9d6eSIan Rogers ids1 = ids__union(ids1, ids2); 24114a9d6eSIan Rogers TEST_ASSERT_EQUAL("union", (int)hashmap__size(ids1), 0); 25114a9d6eSIan Rogers 26114a9d6eSIan Rogers /* Union {foo, bar} against {}. */ 27114a9d6eSIan Rogers ids2 = ids__new(); 28114a9d6eSIan Rogers TEST_ASSERT_VAL("ids__new", ids2); 29114a9d6eSIan Rogers 3080be6434SIan Rogers TEST_ASSERT_EQUAL("ids__insert", ids__insert(ids1, strdup("foo")), 0); 3180be6434SIan Rogers TEST_ASSERT_EQUAL("ids__insert", ids__insert(ids1, strdup("bar")), 0); 32114a9d6eSIan Rogers 33114a9d6eSIan Rogers ids1 = ids__union(ids1, ids2); 34114a9d6eSIan Rogers TEST_ASSERT_EQUAL("union", (int)hashmap__size(ids1), 2); 35114a9d6eSIan Rogers 36114a9d6eSIan Rogers /* Union {foo, bar} against {foo}. */ 37114a9d6eSIan Rogers ids2 = ids__new(); 38114a9d6eSIan Rogers TEST_ASSERT_VAL("ids__new", ids2); 3980be6434SIan Rogers TEST_ASSERT_EQUAL("ids__insert", ids__insert(ids2, strdup("foo")), 0); 40114a9d6eSIan Rogers 41114a9d6eSIan Rogers ids1 = ids__union(ids1, ids2); 42114a9d6eSIan Rogers TEST_ASSERT_EQUAL("union", (int)hashmap__size(ids1), 2); 43114a9d6eSIan Rogers 44114a9d6eSIan Rogers /* Union {foo, bar} against {bar,baz}. */ 45114a9d6eSIan Rogers ids2 = ids__new(); 46114a9d6eSIan Rogers TEST_ASSERT_VAL("ids__new", ids2); 4780be6434SIan Rogers TEST_ASSERT_EQUAL("ids__insert", ids__insert(ids2, strdup("bar")), 0); 4880be6434SIan Rogers TEST_ASSERT_EQUAL("ids__insert", ids__insert(ids2, strdup("baz")), 0); 49114a9d6eSIan Rogers 50114a9d6eSIan Rogers ids1 = ids__union(ids1, ids2); 51114a9d6eSIan Rogers TEST_ASSERT_EQUAL("union", (int)hashmap__size(ids1), 3); 52114a9d6eSIan Rogers 53114a9d6eSIan Rogers ids__free(ids1); 54114a9d6eSIan Rogers 55114a9d6eSIan Rogers return 0; 56114a9d6eSIan Rogers } 57114a9d6eSIan Rogers 58aecce63eSJiri Olsa static int test(struct expr_parse_ctx *ctx, const char *e, double val2) 5907516736SAndi Kleen { 6007516736SAndi Kleen double val; 6107516736SAndi Kleen 62fa831fbbSIan Rogers if (expr__parse(&val, ctx, e)) 6307516736SAndi Kleen TEST_ASSERT_VAL("parse test failed", 0); 6407516736SAndi Kleen TEST_ASSERT_VAL("unexpected value", val == val2); 6507516736SAndi Kleen return 0; 6607516736SAndi Kleen } 6707516736SAndi Kleen 6833f44bfdSIan Rogers static int test__expr(struct test_suite *t __maybe_unused, int subtest __maybe_unused) 6907516736SAndi Kleen { 70070b3b5aSJiri Olsa struct expr_id_data *val_ptr; 7107516736SAndi Kleen const char *p; 72fdf1e29bSIan Rogers double val, num_cpus, num_cores, num_dies, num_packages; 73ded80bdaSIan Rogers int ret; 74cb94a02eSIan Rogers struct expr_parse_ctx *ctx; 756923397cSIan Rogers bool is_intel = false; 766923397cSIan Rogers char buf[128]; 776923397cSIan Rogers 786923397cSIan Rogers if (!get_cpuid(buf, sizeof(buf))) 796923397cSIan Rogers is_intel = strstr(buf, "Intel") != NULL; 8007516736SAndi Kleen 81114a9d6eSIan Rogers TEST_ASSERT_EQUAL("ids_union", test_ids_union(), 0); 82114a9d6eSIan Rogers 83cb94a02eSIan Rogers ctx = expr__ctx_new(); 84cb94a02eSIan Rogers TEST_ASSERT_VAL("expr__ctx_new", ctx); 85cb94a02eSIan Rogers expr__add_id_val(ctx, strdup("FOO"), 1); 86cb94a02eSIan Rogers expr__add_id_val(ctx, strdup("BAR"), 2); 8707516736SAndi Kleen 88cb94a02eSIan Rogers ret = test(ctx, "1+1", 2); 89cb94a02eSIan Rogers ret |= test(ctx, "FOO+BAR", 3); 90cb94a02eSIan Rogers ret |= test(ctx, "(BAR/2)%2", 1); 91cb94a02eSIan Rogers ret |= test(ctx, "1 - -4", 5); 92cb94a02eSIan Rogers ret |= test(ctx, "(FOO-1)*2 + (BAR/2)%2 - -4", 5); 93cb94a02eSIan Rogers ret |= test(ctx, "1-1 | 1", 1); 94cb94a02eSIan Rogers ret |= test(ctx, "1-1 & 1", 0); 95cb94a02eSIan Rogers ret |= test(ctx, "min(1,2) + 1", 2); 96cb94a02eSIan Rogers ret |= test(ctx, "max(1,2) + 1", 3); 97cb94a02eSIan Rogers ret |= test(ctx, "1+1 if 3*4 else 0", 2); 98cb94a02eSIan Rogers ret |= test(ctx, "1.1 + 2.1", 3.2); 99cb94a02eSIan Rogers ret |= test(ctx, ".1 + 2.", 2.1); 100cb94a02eSIan Rogers ret |= test(ctx, "d_ratio(1, 2)", 0.5); 101cb94a02eSIan Rogers ret |= test(ctx, "d_ratio(2.5, 0)", 0); 102cb94a02eSIan Rogers ret |= test(ctx, "1.1 < 2.2", 1); 103cb94a02eSIan Rogers ret |= test(ctx, "2.2 > 1.1", 1); 104cb94a02eSIan Rogers ret |= test(ctx, "1.1 < 1.1", 0); 105cb94a02eSIan Rogers ret |= test(ctx, "2.2 > 2.2", 0); 106cb94a02eSIan Rogers ret |= test(ctx, "2.2 < 1.1", 0); 107cb94a02eSIan Rogers ret |= test(ctx, "1.1 > 2.2", 0); 108e5287e6dSIan Rogers ret |= test(ctx, "1.1e10 < 1.1e100", 1); 109e5287e6dSIan Rogers ret |= test(ctx, "1.1e2 > 1.1e-2", 1); 11007516736SAndi Kleen 111cb94a02eSIan Rogers if (ret) { 112cb94a02eSIan Rogers expr__ctx_free(ctx); 11307516736SAndi Kleen return ret; 114cb94a02eSIan Rogers } 11507516736SAndi Kleen 11607516736SAndi Kleen p = "FOO/0"; 117fa831fbbSIan Rogers ret = expr__parse(&val, ctx, p); 118d942815aSJiri Olsa TEST_ASSERT_VAL("division by zero", ret == -1); 11907516736SAndi Kleen 12007516736SAndi Kleen p = "BAR/"; 121fa831fbbSIan Rogers ret = expr__parse(&val, ctx, p); 122d942815aSJiri Olsa TEST_ASSERT_VAL("missing operand", ret == -1); 12307516736SAndi Kleen 124cb94a02eSIan Rogers expr__ctx_clear(ctx); 1257e06a5e3SIan Rogers TEST_ASSERT_VAL("find ids", 1267e06a5e3SIan Rogers expr__find_ids("FOO + BAR + BAZ + BOZO", "FOO", 127fa831fbbSIan Rogers ctx) == 0); 1287e06a5e3SIan Rogers TEST_ASSERT_VAL("find ids", hashmap__size(ctx->ids) == 3); 1297e06a5e3SIan Rogers TEST_ASSERT_VAL("find ids", hashmap__find(ctx->ids, "BAR", 130ded80bdaSIan Rogers (void **)&val_ptr)); 1317e06a5e3SIan Rogers TEST_ASSERT_VAL("find ids", hashmap__find(ctx->ids, "BAZ", 132ded80bdaSIan Rogers (void **)&val_ptr)); 1337e06a5e3SIan Rogers TEST_ASSERT_VAL("find ids", hashmap__find(ctx->ids, "BOZO", 134ded80bdaSIan Rogers (void **)&val_ptr)); 135f97a8991SChangbin Du 136cb94a02eSIan Rogers expr__ctx_clear(ctx); 1371a6abddeSIan Rogers ctx->sctx.runtime = 3; 1387e06a5e3SIan Rogers TEST_ASSERT_VAL("find ids", 1397e06a5e3SIan Rogers expr__find_ids("EVENT1\\,param\\=?@ + EVENT2\\,param\\=?@", 140fa831fbbSIan Rogers NULL, ctx) == 0); 1417e06a5e3SIan Rogers TEST_ASSERT_VAL("find ids", hashmap__size(ctx->ids) == 2); 142ec5c5b3dSIan Rogers TEST_ASSERT_VAL("find ids", hashmap__find(ctx->ids, "EVENT1,param=3@", 143ded80bdaSIan Rogers (void **)&val_ptr)); 144ec5c5b3dSIan Rogers TEST_ASSERT_VAL("find ids", hashmap__find(ctx->ids, "EVENT2,param=3@", 145ded80bdaSIan Rogers (void **)&val_ptr)); 1469022608eSKajol Jain 147604ce2f0SIan Rogers expr__ctx_clear(ctx); 148604ce2f0SIan Rogers TEST_ASSERT_VAL("find ids", 149604ce2f0SIan Rogers expr__find_ids("dash\\-event1 - dash\\-event2", 150604ce2f0SIan Rogers NULL, ctx) == 0); 151604ce2f0SIan Rogers TEST_ASSERT_VAL("find ids", hashmap__size(ctx->ids) == 2); 152604ce2f0SIan Rogers TEST_ASSERT_VAL("find ids", hashmap__find(ctx->ids, "dash-event1", 153604ce2f0SIan Rogers (void **)&val_ptr)); 154604ce2f0SIan Rogers TEST_ASSERT_VAL("find ids", hashmap__find(ctx->ids, "dash-event2", 155604ce2f0SIan Rogers (void **)&val_ptr)); 156604ce2f0SIan Rogers 157a8e4e880SIan Rogers /* Only EVENT1 or EVENT2 need be measured depending on the value of smt_on. */ 15809b73fe9SIan Rogers { 15909b73fe9SIan Rogers struct cpu_topology *topology = cpu_topology__new(); 16009b73fe9SIan Rogers bool smton = smt_on(topology); 161*f0c4b97aSIan Rogers bool corewide = core_wide(/*system_wide=*/false, 162*f0c4b97aSIan Rogers /*user_requested_cpus=*/false, 163*f0c4b97aSIan Rogers topology); 16409b73fe9SIan Rogers 16509b73fe9SIan Rogers cpu_topology__delete(topology); 166a8e4e880SIan Rogers expr__ctx_clear(ctx); 167a8e4e880SIan Rogers TEST_ASSERT_VAL("find ids", 168a8e4e880SIan Rogers expr__find_ids("EVENT1 if #smt_on else EVENT2", 169fa831fbbSIan Rogers NULL, ctx) == 0); 170a8e4e880SIan Rogers TEST_ASSERT_VAL("find ids", hashmap__size(ctx->ids) == 1); 171a8e4e880SIan Rogers TEST_ASSERT_VAL("find ids", hashmap__find(ctx->ids, 17209b73fe9SIan Rogers smton ? "EVENT1" : "EVENT2", 173a8e4e880SIan Rogers (void **)&val_ptr)); 174*f0c4b97aSIan Rogers 175*f0c4b97aSIan Rogers expr__ctx_clear(ctx); 176*f0c4b97aSIan Rogers TEST_ASSERT_VAL("find ids", 177*f0c4b97aSIan Rogers expr__find_ids("EVENT1 if #core_wide else EVENT2", 178*f0c4b97aSIan Rogers NULL, ctx) == 0); 179*f0c4b97aSIan Rogers TEST_ASSERT_VAL("find ids", hashmap__size(ctx->ids) == 1); 180*f0c4b97aSIan Rogers TEST_ASSERT_VAL("find ids", hashmap__find(ctx->ids, 181*f0c4b97aSIan Rogers corewide ? "EVENT1" : "EVENT2", 182*f0c4b97aSIan Rogers (void **)&val_ptr)); 183*f0c4b97aSIan Rogers 18409b73fe9SIan Rogers } 18594886961SIan Rogers /* The expression is a constant 1.0 without needing to evaluate EVENT1. */ 18694886961SIan Rogers expr__ctx_clear(ctx); 18794886961SIan Rogers TEST_ASSERT_VAL("find ids", 18894886961SIan Rogers expr__find_ids("1.0 if EVENT1 > 100.0 else 1.0", 189fa831fbbSIan Rogers NULL, ctx) == 0); 19094886961SIan Rogers TEST_ASSERT_VAL("find ids", hashmap__size(ctx->ids) == 0); 19194886961SIan Rogers 192fdf1e29bSIan Rogers /* Test toplogy constants appear well ordered. */ 193fdf1e29bSIan Rogers expr__ctx_clear(ctx); 194fdf1e29bSIan Rogers TEST_ASSERT_VAL("#num_cpus", expr__parse(&num_cpus, ctx, "#num_cpus") == 0); 195fdf1e29bSIan Rogers TEST_ASSERT_VAL("#num_cores", expr__parse(&num_cores, ctx, "#num_cores") == 0); 196fdf1e29bSIan Rogers TEST_ASSERT_VAL("#num_cpus >= #num_cores", num_cpus >= num_cores); 197fdf1e29bSIan Rogers TEST_ASSERT_VAL("#num_dies", expr__parse(&num_dies, ctx, "#num_dies") == 0); 198fdf1e29bSIan Rogers TEST_ASSERT_VAL("#num_cores >= #num_dies", num_cores >= num_dies); 199fdf1e29bSIan Rogers TEST_ASSERT_VAL("#num_packages", expr__parse(&num_packages, ctx, "#num_packages") == 0); 2006c481031SThomas Richter 2016c481031SThomas Richter if (num_dies) // Some platforms do not have CPU die support, for example s390 202fdf1e29bSIan Rogers TEST_ASSERT_VAL("#num_dies >= #num_packages", num_dies >= num_packages); 203fdf1e29bSIan Rogers 2046923397cSIan Rogers TEST_ASSERT_VAL("#system_tsc_freq", expr__parse(&val, ctx, "#system_tsc_freq") == 0); 2056923397cSIan Rogers if (is_intel) 2066923397cSIan Rogers TEST_ASSERT_VAL("#system_tsc_freq > 0", val > 0); 2076923397cSIan Rogers else 2086923397cSIan Rogers TEST_ASSERT_VAL("#system_tsc_freq == 0", fpclassify(val) == FP_ZERO); 2096923397cSIan Rogers 2109aba0adaSIan Rogers /* 2119aba0adaSIan Rogers * Source count returns the number of events aggregating in a leader 2129aba0adaSIan Rogers * event including the leader. Check parsing yields an id. 2139aba0adaSIan Rogers */ 2149aba0adaSIan Rogers expr__ctx_clear(ctx); 2159aba0adaSIan Rogers TEST_ASSERT_VAL("source count", 2169aba0adaSIan Rogers expr__find_ids("source_count(EVENT1)", 2179aba0adaSIan Rogers NULL, ctx) == 0); 2189aba0adaSIan Rogers TEST_ASSERT_VAL("source count", hashmap__size(ctx->ids) == 1); 2199aba0adaSIan Rogers TEST_ASSERT_VAL("source count", hashmap__find(ctx->ids, "EVENT1", 2209aba0adaSIan Rogers (void **)&val_ptr)); 2219aba0adaSIan Rogers 222cb94a02eSIan Rogers expr__ctx_free(ctx); 22307516736SAndi Kleen 22407516736SAndi Kleen return 0; 22507516736SAndi Kleen } 226d68f0365SIan Rogers 227d68f0365SIan Rogers DEFINE_SUITE("Simple expression parser", expr); 228