169 lines · python
1#!/usr/bin/env python32# SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause)3import unittest4from metric import Constant5from metric import Event6from metric import Expression7from metric import ParsePerfJson8from metric import RewriteMetricsInTermsOfOthers9 10 11class TestMetricExpressions(unittest.TestCase):12 13 def test_Operators(self):14 a = Event('a')15 b = Event('b')16 self.assertEqual((a | b).ToPerfJson(), 'a | b')17 self.assertEqual((a ^ b).ToPerfJson(), 'a ^ b')18 self.assertEqual((a & b).ToPerfJson(), 'a & b')19 self.assertEqual((a < b).ToPerfJson(), 'a < b')20 self.assertEqual((a > b).ToPerfJson(), 'a > b')21 self.assertEqual((a + b).ToPerfJson(), 'a + b')22 self.assertEqual((a - b).ToPerfJson(), 'a - b')23 self.assertEqual((a * b).ToPerfJson(), 'a * b')24 self.assertEqual((a / b).ToPerfJson(), 'a / b')25 self.assertEqual((a % b).ToPerfJson(), 'a % b')26 one = Constant(1)27 self.assertEqual((a + one).ToPerfJson(), 'a + 1')28 29 def test_Brackets(self):30 a = Event('a')31 b = Event('b')32 c = Event('c')33 self.assertEqual((a * b + c).ToPerfJson(), 'a * b + c')34 self.assertEqual((a + b * c).ToPerfJson(), 'a + b * c')35 self.assertEqual(((a + a) + a).ToPerfJson(), 'a + a + a')36 self.assertEqual(((a + b) * c).ToPerfJson(), '(a + b) * c')37 self.assertEqual((a + (b * c)).ToPerfJson(), 'a + b * c')38 self.assertEqual(((a / b) * c).ToPerfJson(), 'a / b * c')39 self.assertEqual((a / (b * c)).ToPerfJson(), 'a / (b * c)')40 41 def test_ParsePerfJson(self):42 # Based on an example of a real metric.43 before = '(a + b + c + d) / (2 * e)'44 after = before45 self.assertEqual(ParsePerfJson(before).ToPerfJson(), after)46 47 # Parsing should handle events with '-' in their name. Note, in48 # the json file the '\' are doubled to '\\'.49 before = r'topdown\-fe\-bound / topdown\-slots - 1'50 after = before51 self.assertEqual(ParsePerfJson(before).ToPerfJson(), after)52 53 # Parsing should handle escaped modifiers. Note, in the json file54 # the '\' are doubled to '\\'.55 before = r'arb@event\=0x81\,umask\=0x1@ + arb@event\=0x84\,umask\=0x1@'56 after = before57 self.assertEqual(ParsePerfJson(before).ToPerfJson(), after)58 59 # Parsing should handle exponents in numbers.60 before = r'a + 1e12 + b'61 after = before62 self.assertEqual(ParsePerfJson(before).ToPerfJson(), after)63 64 def test_IfElseTests(self):65 # if-else needs rewriting to Select and back.66 before = r'Event1 if #smt_on else Event2'67 after = f'({before})'68 self.assertEqual(ParsePerfJson(before).ToPerfJson(), after)69 70 before = r'Event1 if 0 else Event2'71 after = f'({before})'72 self.assertEqual(ParsePerfJson(before).ToPerfJson(), after)73 74 before = r'Event1 if 1 else Event2'75 after = f'({before})'76 self.assertEqual(ParsePerfJson(before).ToPerfJson(), after)77 78 # Ensure the select is evaluate last.79 before = r'Event1 + 1 if Event2 < 2 else Event3 + 3'80 after = (r'Select(Event(r"Event1") + Constant(1), Event(r"Event2") < '81 r'Constant(2), Event(r"Event3") + Constant(3))')82 self.assertEqual(ParsePerfJson(before).ToPython(), after)83 84 before = r'Event1 > 1 if Event2 < 2 else Event3 > 3'85 after = (r'Select(Event(r"Event1") > Constant(1), Event(r"Event2") < '86 r'Constant(2), Event(r"Event3") > Constant(3))')87 self.assertEqual(ParsePerfJson(before).ToPython(), after)88 89 before = r'min(a + b if c > 1 else c + d, e + f)'90 after = r'min((a + b if c > 1 else c + d), e + f)'91 self.assertEqual(ParsePerfJson(before).ToPerfJson(), after)92 93 before = r'a if b else c if d else e'94 after = r'(a if b else (c if d else e))'95 self.assertEqual(ParsePerfJson(before).ToPerfJson(), after)96 97 def test_ToPython(self):98 # pylint: disable=eval-used99 # Based on an example of a real metric.100 before = '(a + b + c + d) / (2 * e)'101 py = ParsePerfJson(before).ToPython()102 after = eval(py).ToPerfJson()103 self.assertEqual(before, after)104 105 def test_Simplify(self):106 before = '1 + 2 + 3'107 after = '6'108 self.assertEqual(ParsePerfJson(before).Simplify().ToPerfJson(), after)109 110 before = 'a + 0'111 after = 'a'112 self.assertEqual(ParsePerfJson(before).Simplify().ToPerfJson(), after)113 114 before = '0 + a'115 after = 'a'116 self.assertEqual(ParsePerfJson(before).Simplify().ToPerfJson(), after)117 118 before = 'a | 0'119 after = 'a'120 self.assertEqual(ParsePerfJson(before).Simplify().ToPerfJson(), after)121 122 before = '0 | a'123 after = 'a'124 self.assertEqual(ParsePerfJson(before).Simplify().ToPerfJson(), after)125 126 before = 'a * 0'127 after = '0'128 self.assertEqual(ParsePerfJson(before).Simplify().ToPerfJson(), after)129 130 before = '0 * a'131 after = '0'132 self.assertEqual(ParsePerfJson(before).Simplify().ToPerfJson(), after)133 134 before = 'a * 1'135 after = 'a'136 self.assertEqual(ParsePerfJson(before).Simplify().ToPerfJson(), after)137 138 before = '1 * a'139 after = 'a'140 self.assertEqual(ParsePerfJson(before).Simplify().ToPerfJson(), after)141 142 before = 'a if 0 else b'143 after = 'b'144 self.assertEqual(ParsePerfJson(before).Simplify().ToPerfJson(), after)145 146 before = 'a if 1 else b'147 after = 'a'148 self.assertEqual(ParsePerfJson(before).Simplify().ToPerfJson(), after)149 150 before = 'a if b else a'151 after = 'a'152 self.assertEqual(ParsePerfJson(before).Simplify().ToPerfJson(), after)153 154 # Pattern used to add a slots event to metrics that require it.155 before = '0 * SLOTS'156 after = '0 * SLOTS'157 self.assertEqual(ParsePerfJson(before).Simplify().ToPerfJson(), after)158 159 def test_RewriteMetricsInTermsOfOthers(self):160 Expression.__eq__ = lambda e1, e2: e1.Equals(e2)161 before = [('cpu', 'm1', ParsePerfJson('a + b + c + d')),162 ('cpu', 'm2', ParsePerfJson('a + b + c'))]163 after = {('cpu', 'm1'): ParsePerfJson('m2 + d')}164 self.assertEqual(RewriteMetricsInTermsOfOthers(before), after)165 Expression.__eq__ = None166 167if __name__ == '__main__':168 unittest.main()169