diff options
Diffstat (limited to 'tools/perf/pmu-events/metric_test.py')
-rwxr-xr-x | tools/perf/pmu-events/metric_test.py | 168 |
1 files changed, 168 insertions, 0 deletions
diff --git a/tools/perf/pmu-events/metric_test.py b/tools/perf/pmu-events/metric_test.py new file mode 100755 index 0000000000..ee22ff43dd --- /dev/null +++ b/tools/perf/pmu-events/metric_test.py @@ -0,0 +1,168 @@ +#!/usr/bin/env python3 +# SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) +import unittest +from metric import Constant +from metric import Event +from metric import Expression +from metric import ParsePerfJson +from metric import RewriteMetricsInTermsOfOthers + + +class TestMetricExpressions(unittest.TestCase): + + def test_Operators(self): + a = Event('a') + b = Event('b') + self.assertEqual((a | b).ToPerfJson(), 'a | b') + self.assertEqual((a ^ b).ToPerfJson(), 'a ^ b') + self.assertEqual((a & b).ToPerfJson(), 'a & b') + self.assertEqual((a < b).ToPerfJson(), 'a < b') + self.assertEqual((a > b).ToPerfJson(), 'a > b') + self.assertEqual((a + b).ToPerfJson(), 'a + b') + self.assertEqual((a - b).ToPerfJson(), 'a - b') + self.assertEqual((a * b).ToPerfJson(), 'a * b') + self.assertEqual((a / b).ToPerfJson(), 'a / b') + self.assertEqual((a % b).ToPerfJson(), 'a % b') + one = Constant(1) + self.assertEqual((a + one).ToPerfJson(), 'a + 1') + + def test_Brackets(self): + a = Event('a') + b = Event('b') + c = Event('c') + self.assertEqual((a * b + c).ToPerfJson(), 'a * b + c') + self.assertEqual((a + b * c).ToPerfJson(), 'a + b * c') + self.assertEqual(((a + a) + a).ToPerfJson(), 'a + a + a') + self.assertEqual(((a + b) * c).ToPerfJson(), '(a + b) * c') + self.assertEqual((a + (b * c)).ToPerfJson(), 'a + b * c') + self.assertEqual(((a / b) * c).ToPerfJson(), 'a / b * c') + self.assertEqual((a / (b * c)).ToPerfJson(), 'a / (b * c)') + + def test_ParsePerfJson(self): + # Based on an example of a real metric. + before = '(a + b + c + d) / (2 * e)' + after = before + self.assertEqual(ParsePerfJson(before).ToPerfJson(), after) + + # Parsing should handle events with '-' in their name. Note, in + # the json file the '\' are doubled to '\\'. + before = r'topdown\-fe\-bound / topdown\-slots - 1' + after = before + self.assertEqual(ParsePerfJson(before).ToPerfJson(), after) + + # Parsing should handle escaped modifiers. Note, in the json file + # the '\' are doubled to '\\'. + before = r'arb@event\=0x81\,umask\=0x1@ + arb@event\=0x84\,umask\=0x1@' + after = before + self.assertEqual(ParsePerfJson(before).ToPerfJson(), after) + + # Parsing should handle exponents in numbers. + before = r'a + 1e12 + b' + after = before + self.assertEqual(ParsePerfJson(before).ToPerfJson(), after) + + def test_IfElseTests(self): + # if-else needs rewriting to Select and back. + before = r'Event1 if #smt_on else Event2' + after = f'({before})' + self.assertEqual(ParsePerfJson(before).ToPerfJson(), after) + + before = r'Event1 if 0 else Event2' + after = f'({before})' + self.assertEqual(ParsePerfJson(before).ToPerfJson(), after) + + before = r'Event1 if 1 else Event2' + after = f'({before})' + self.assertEqual(ParsePerfJson(before).ToPerfJson(), after) + + # Ensure the select is evaluate last. + before = r'Event1 + 1 if Event2 < 2 else Event3 + 3' + after = (r'Select(Event(r"Event1") + Constant(1), Event(r"Event2") < ' + r'Constant(2), Event(r"Event3") + Constant(3))') + self.assertEqual(ParsePerfJson(before).ToPython(), after) + + before = r'Event1 > 1 if Event2 < 2 else Event3 > 3' + after = (r'Select(Event(r"Event1") > Constant(1), Event(r"Event2") < ' + r'Constant(2), Event(r"Event3") > Constant(3))') + self.assertEqual(ParsePerfJson(before).ToPython(), after) + + before = r'min(a + b if c > 1 else c + d, e + f)' + after = r'min((a + b if c > 1 else c + d), e + f)' + self.assertEqual(ParsePerfJson(before).ToPerfJson(), after) + + before = r'a if b else c if d else e' + after = r'(a if b else (c if d else e))' + self.assertEqual(ParsePerfJson(before).ToPerfJson(), after) + + def test_ToPython(self): + # pylint: disable=eval-used + # Based on an example of a real metric. + before = '(a + b + c + d) / (2 * e)' + py = ParsePerfJson(before).ToPython() + after = eval(py).ToPerfJson() + self.assertEqual(before, after) + + def test_Simplify(self): + before = '1 + 2 + 3' + after = '6' + self.assertEqual(ParsePerfJson(before).Simplify().ToPerfJson(), after) + + before = 'a + 0' + after = 'a' + self.assertEqual(ParsePerfJson(before).Simplify().ToPerfJson(), after) + + before = '0 + a' + after = 'a' + self.assertEqual(ParsePerfJson(before).Simplify().ToPerfJson(), after) + + before = 'a | 0' + after = 'a' + self.assertEqual(ParsePerfJson(before).Simplify().ToPerfJson(), after) + + before = '0 | a' + after = 'a' + self.assertEqual(ParsePerfJson(before).Simplify().ToPerfJson(), after) + + before = 'a * 0' + after = '0' + self.assertEqual(ParsePerfJson(before).Simplify().ToPerfJson(), after) + + before = '0 * a' + after = '0' + self.assertEqual(ParsePerfJson(before).Simplify().ToPerfJson(), after) + + before = 'a * 1' + after = 'a' + self.assertEqual(ParsePerfJson(before).Simplify().ToPerfJson(), after) + + before = '1 * a' + after = 'a' + self.assertEqual(ParsePerfJson(before).Simplify().ToPerfJson(), after) + + before = 'a if 0 else b' + after = 'b' + self.assertEqual(ParsePerfJson(before).Simplify().ToPerfJson(), after) + + before = 'a if 1 else b' + after = 'a' + self.assertEqual(ParsePerfJson(before).Simplify().ToPerfJson(), after) + + before = 'a if b else a' + after = 'a' + self.assertEqual(ParsePerfJson(before).Simplify().ToPerfJson(), after) + + # Pattern used to add a slots event to metrics that require it. + before = '0 * SLOTS' + after = '0 * SLOTS' + self.assertEqual(ParsePerfJson(before).Simplify().ToPerfJson(), after) + + def test_RewriteMetricsInTermsOfOthers(self): + Expression.__eq__ = lambda e1, e2: e1.Equals(e2) + before = [('cpu', 'm1', ParsePerfJson('a + b + c + d')), + ('cpu', 'm2', ParsePerfJson('a + b + c'))] + after = {('cpu', 'm1'): ParsePerfJson('m2 + d')} + self.assertEqual(RewriteMetricsInTermsOfOthers(before), after) + Expression.__eq__ = None + +if __name__ == '__main__': + unittest.main() |