1# SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) 2import unittest 3from metric import Constant 4from metric import Event 5from metric import ParsePerfJson 6 7 8class TestMetricExpressions(unittest.TestCase): 9 10 def test_Operators(self): 11 a = Event('a') 12 b = Event('b') 13 self.assertEqual((a | b).ToPerfJson(), 'a | b') 14 self.assertEqual((a ^ b).ToPerfJson(), 'a ^ b') 15 self.assertEqual((a & b).ToPerfJson(), 'a & 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 one = Constant(1) 24 self.assertEqual((a + one).ToPerfJson(), 'a + 1') 25 26 def test_Brackets(self): 27 a = Event('a') 28 b = Event('b') 29 c = Event('c') 30 self.assertEqual((a * b + c).ToPerfJson(), 'a * b + c') 31 self.assertEqual((a + b * c).ToPerfJson(), 'a + b * c') 32 self.assertEqual(((a + a) + a).ToPerfJson(), 'a + a + a') 33 self.assertEqual(((a + b) * c).ToPerfJson(), '(a + b) * c') 34 self.assertEqual((a + (b * c)).ToPerfJson(), 'a + b * c') 35 self.assertEqual(((a / b) * c).ToPerfJson(), 'a / b * c') 36 self.assertEqual((a / (b * c)).ToPerfJson(), 'a / (b * c)') 37 38 def test_ParsePerfJson(self): 39 # Based on an example of a real metric. 40 before = '(a + b + c + d) / (2 * e)' 41 after = before 42 self.assertEqual(ParsePerfJson(before).ToPerfJson(), after) 43 44 # Parsing should handle events with '-' in their name. Note, in 45 # the json file the '\' are doubled to '\\'. 46 before = r'topdown\-fe\-bound / topdown\-slots - 1' 47 after = before 48 self.assertEqual(ParsePerfJson(before).ToPerfJson(), after) 49 50 # Parsing should handle escaped modifiers. Note, in the json file 51 # the '\' are doubled to '\\'. 52 before = r'arb@event\=0x81\,umask\=0x1@ + arb@event\=0x84\,umask\=0x1@' 53 after = before 54 self.assertEqual(ParsePerfJson(before).ToPerfJson(), after) 55 56 # Parsing should handle exponents in numbers. 57 before = r'a + 1e12 + b' 58 after = before 59 self.assertEqual(ParsePerfJson(before).ToPerfJson(), after) 60 61 def test_IfElseTests(self): 62 # if-else needs rewriting to Select and back. 63 before = r'Event1 if #smt_on else Event2' 64 after = f'({before})' 65 self.assertEqual(ParsePerfJson(before).ToPerfJson(), after) 66 67 before = r'Event1 if 0 else Event2' 68 after = f'({before})' 69 self.assertEqual(ParsePerfJson(before).ToPerfJson(), after) 70 71 before = r'Event1 if 1 else Event2' 72 after = f'({before})' 73 self.assertEqual(ParsePerfJson(before).ToPerfJson(), after) 74 75 # Ensure the select is evaluate last. 76 before = r'Event1 + 1 if Event2 < 2 else Event3 + 3' 77 after = (r'Select(Event(r"Event1") + Constant(1), Event(r"Event2") < ' 78 r'Constant(2), Event(r"Event3") + Constant(3))') 79 self.assertEqual(ParsePerfJson(before).ToPython(), after) 80 81 before = r'Event1 > 1 if Event2 < 2 else Event3 > 3' 82 after = (r'Select(Event(r"Event1") > Constant(1), Event(r"Event2") < ' 83 r'Constant(2), Event(r"Event3") > Constant(3))') 84 self.assertEqual(ParsePerfJson(before).ToPython(), after) 85 86 before = r'min(a + b if c > 1 else c + d, e + f)' 87 after = r'min((a + b if c > 1 else c + d), e + f)' 88 self.assertEqual(ParsePerfJson(before).ToPerfJson(), after) 89 90 before =3D r'a if b else c if d else e' 91 after =3D r'(a if b else (c if d else e))' 92 self.assertEqual(ParsePerfJson(before).ToPerfJson(), after) 93 94 def test_ToPython(self): 95 # pylint: disable=eval-used 96 # Based on an example of a real metric. 97 before = '(a + b + c + d) / (2 * e)' 98 py = ParsePerfJson(before).ToPython() 99 after = eval(py).ToPerfJson() 100 self.assertEqual(before, after) 101 102 def test_Simplify(self): 103 before = '1 + 2 + 3' 104 after = '6' 105 self.assertEqual(ParsePerfJson(before).Simplify().ToPerfJson(), after) 106 107 before = 'a + 0' 108 after = 'a' 109 self.assertEqual(ParsePerfJson(before).Simplify().ToPerfJson(), after) 110 111 before = '0 + a' 112 after = 'a' 113 self.assertEqual(ParsePerfJson(before).Simplify().ToPerfJson(), after) 114 115 before = 'a | 0' 116 after = 'a' 117 self.assertEqual(ParsePerfJson(before).Simplify().ToPerfJson(), after) 118 119 before = '0 | a' 120 after = 'a' 121 self.assertEqual(ParsePerfJson(before).Simplify().ToPerfJson(), after) 122 123 before = 'a * 0' 124 after = '0' 125 self.assertEqual(ParsePerfJson(before).Simplify().ToPerfJson(), after) 126 127 before = '0 * a' 128 after = '0' 129 self.assertEqual(ParsePerfJson(before).Simplify().ToPerfJson(), after) 130 131 before = 'a * 1' 132 after = 'a' 133 self.assertEqual(ParsePerfJson(before).Simplify().ToPerfJson(), after) 134 135 before = '1 * a' 136 after = 'a' 137 self.assertEqual(ParsePerfJson(before).Simplify().ToPerfJson(), after) 138 139 before = 'a if 0 else b' 140 after = 'b' 141 self.assertEqual(ParsePerfJson(before).Simplify().ToPerfJson(), after) 142 143 before = 'a if 1 else b' 144 after = 'a' 145 self.assertEqual(ParsePerfJson(before).Simplify().ToPerfJson(), after) 146 147 before = 'a if b else a' 148 after = 'a' 149 self.assertEqual(ParsePerfJson(before).Simplify().ToPerfJson(), after) 150 151 # Pattern used to add a slots event to metrics that require it. 152 before = '0 * SLOTS' 153 after = '0 * SLOTS' 154 self.assertEqual(ParsePerfJson(before).Simplify().ToPerfJson(), after) 155 156if __name__ == '__main__': 157 unittest.main() 158