162306a36Sopenharmony_ci#!/usr/bin/env python3 262306a36Sopenharmony_ci# SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) 362306a36Sopenharmony_ciimport unittest 462306a36Sopenharmony_cifrom metric import Constant 562306a36Sopenharmony_cifrom metric import Event 662306a36Sopenharmony_cifrom metric import Expression 762306a36Sopenharmony_cifrom metric import ParsePerfJson 862306a36Sopenharmony_cifrom metric import RewriteMetricsInTermsOfOthers 962306a36Sopenharmony_ci 1062306a36Sopenharmony_ci 1162306a36Sopenharmony_ciclass TestMetricExpressions(unittest.TestCase): 1262306a36Sopenharmony_ci 1362306a36Sopenharmony_ci def test_Operators(self): 1462306a36Sopenharmony_ci a = Event('a') 1562306a36Sopenharmony_ci b = Event('b') 1662306a36Sopenharmony_ci self.assertEqual((a | b).ToPerfJson(), 'a | b') 1762306a36Sopenharmony_ci self.assertEqual((a ^ b).ToPerfJson(), 'a ^ b') 1862306a36Sopenharmony_ci self.assertEqual((a & b).ToPerfJson(), 'a & b') 1962306a36Sopenharmony_ci self.assertEqual((a < b).ToPerfJson(), 'a < b') 2062306a36Sopenharmony_ci self.assertEqual((a > b).ToPerfJson(), 'a > b') 2162306a36Sopenharmony_ci self.assertEqual((a + b).ToPerfJson(), 'a + b') 2262306a36Sopenharmony_ci self.assertEqual((a - b).ToPerfJson(), 'a - b') 2362306a36Sopenharmony_ci self.assertEqual((a * b).ToPerfJson(), 'a * b') 2462306a36Sopenharmony_ci self.assertEqual((a / b).ToPerfJson(), 'a / b') 2562306a36Sopenharmony_ci self.assertEqual((a % b).ToPerfJson(), 'a % b') 2662306a36Sopenharmony_ci one = Constant(1) 2762306a36Sopenharmony_ci self.assertEqual((a + one).ToPerfJson(), 'a + 1') 2862306a36Sopenharmony_ci 2962306a36Sopenharmony_ci def test_Brackets(self): 3062306a36Sopenharmony_ci a = Event('a') 3162306a36Sopenharmony_ci b = Event('b') 3262306a36Sopenharmony_ci c = Event('c') 3362306a36Sopenharmony_ci self.assertEqual((a * b + c).ToPerfJson(), 'a * b + c') 3462306a36Sopenharmony_ci self.assertEqual((a + b * c).ToPerfJson(), 'a + b * c') 3562306a36Sopenharmony_ci self.assertEqual(((a + a) + a).ToPerfJson(), 'a + a + a') 3662306a36Sopenharmony_ci self.assertEqual(((a + b) * c).ToPerfJson(), '(a + b) * c') 3762306a36Sopenharmony_ci self.assertEqual((a + (b * c)).ToPerfJson(), 'a + b * c') 3862306a36Sopenharmony_ci self.assertEqual(((a / b) * c).ToPerfJson(), 'a / b * c') 3962306a36Sopenharmony_ci self.assertEqual((a / (b * c)).ToPerfJson(), 'a / (b * c)') 4062306a36Sopenharmony_ci 4162306a36Sopenharmony_ci def test_ParsePerfJson(self): 4262306a36Sopenharmony_ci # Based on an example of a real metric. 4362306a36Sopenharmony_ci before = '(a + b + c + d) / (2 * e)' 4462306a36Sopenharmony_ci after = before 4562306a36Sopenharmony_ci self.assertEqual(ParsePerfJson(before).ToPerfJson(), after) 4662306a36Sopenharmony_ci 4762306a36Sopenharmony_ci # Parsing should handle events with '-' in their name. Note, in 4862306a36Sopenharmony_ci # the json file the '\' are doubled to '\\'. 4962306a36Sopenharmony_ci before = r'topdown\-fe\-bound / topdown\-slots - 1' 5062306a36Sopenharmony_ci after = before 5162306a36Sopenharmony_ci self.assertEqual(ParsePerfJson(before).ToPerfJson(), after) 5262306a36Sopenharmony_ci 5362306a36Sopenharmony_ci # Parsing should handle escaped modifiers. Note, in the json file 5462306a36Sopenharmony_ci # the '\' are doubled to '\\'. 5562306a36Sopenharmony_ci before = r'arb@event\=0x81\,umask\=0x1@ + arb@event\=0x84\,umask\=0x1@' 5662306a36Sopenharmony_ci after = before 5762306a36Sopenharmony_ci self.assertEqual(ParsePerfJson(before).ToPerfJson(), after) 5862306a36Sopenharmony_ci 5962306a36Sopenharmony_ci # Parsing should handle exponents in numbers. 6062306a36Sopenharmony_ci before = r'a + 1e12 + b' 6162306a36Sopenharmony_ci after = before 6262306a36Sopenharmony_ci self.assertEqual(ParsePerfJson(before).ToPerfJson(), after) 6362306a36Sopenharmony_ci 6462306a36Sopenharmony_ci def test_IfElseTests(self): 6562306a36Sopenharmony_ci # if-else needs rewriting to Select and back. 6662306a36Sopenharmony_ci before = r'Event1 if #smt_on else Event2' 6762306a36Sopenharmony_ci after = f'({before})' 6862306a36Sopenharmony_ci self.assertEqual(ParsePerfJson(before).ToPerfJson(), after) 6962306a36Sopenharmony_ci 7062306a36Sopenharmony_ci before = r'Event1 if 0 else Event2' 7162306a36Sopenharmony_ci after = f'({before})' 7262306a36Sopenharmony_ci self.assertEqual(ParsePerfJson(before).ToPerfJson(), after) 7362306a36Sopenharmony_ci 7462306a36Sopenharmony_ci before = r'Event1 if 1 else Event2' 7562306a36Sopenharmony_ci after = f'({before})' 7662306a36Sopenharmony_ci self.assertEqual(ParsePerfJson(before).ToPerfJson(), after) 7762306a36Sopenharmony_ci 7862306a36Sopenharmony_ci # Ensure the select is evaluate last. 7962306a36Sopenharmony_ci before = r'Event1 + 1 if Event2 < 2 else Event3 + 3' 8062306a36Sopenharmony_ci after = (r'Select(Event(r"Event1") + Constant(1), Event(r"Event2") < ' 8162306a36Sopenharmony_ci r'Constant(2), Event(r"Event3") + Constant(3))') 8262306a36Sopenharmony_ci self.assertEqual(ParsePerfJson(before).ToPython(), after) 8362306a36Sopenharmony_ci 8462306a36Sopenharmony_ci before = r'Event1 > 1 if Event2 < 2 else Event3 > 3' 8562306a36Sopenharmony_ci after = (r'Select(Event(r"Event1") > Constant(1), Event(r"Event2") < ' 8662306a36Sopenharmony_ci r'Constant(2), Event(r"Event3") > Constant(3))') 8762306a36Sopenharmony_ci self.assertEqual(ParsePerfJson(before).ToPython(), after) 8862306a36Sopenharmony_ci 8962306a36Sopenharmony_ci before = r'min(a + b if c > 1 else c + d, e + f)' 9062306a36Sopenharmony_ci after = r'min((a + b if c > 1 else c + d), e + f)' 9162306a36Sopenharmony_ci self.assertEqual(ParsePerfJson(before).ToPerfJson(), after) 9262306a36Sopenharmony_ci 9362306a36Sopenharmony_ci before = r'a if b else c if d else e' 9462306a36Sopenharmony_ci after = r'(a if b else (c if d else e))' 9562306a36Sopenharmony_ci self.assertEqual(ParsePerfJson(before).ToPerfJson(), after) 9662306a36Sopenharmony_ci 9762306a36Sopenharmony_ci def test_ToPython(self): 9862306a36Sopenharmony_ci # pylint: disable=eval-used 9962306a36Sopenharmony_ci # Based on an example of a real metric. 10062306a36Sopenharmony_ci before = '(a + b + c + d) / (2 * e)' 10162306a36Sopenharmony_ci py = ParsePerfJson(before).ToPython() 10262306a36Sopenharmony_ci after = eval(py).ToPerfJson() 10362306a36Sopenharmony_ci self.assertEqual(before, after) 10462306a36Sopenharmony_ci 10562306a36Sopenharmony_ci def test_Simplify(self): 10662306a36Sopenharmony_ci before = '1 + 2 + 3' 10762306a36Sopenharmony_ci after = '6' 10862306a36Sopenharmony_ci self.assertEqual(ParsePerfJson(before).Simplify().ToPerfJson(), after) 10962306a36Sopenharmony_ci 11062306a36Sopenharmony_ci before = 'a + 0' 11162306a36Sopenharmony_ci after = 'a' 11262306a36Sopenharmony_ci self.assertEqual(ParsePerfJson(before).Simplify().ToPerfJson(), after) 11362306a36Sopenharmony_ci 11462306a36Sopenharmony_ci before = '0 + a' 11562306a36Sopenharmony_ci after = 'a' 11662306a36Sopenharmony_ci self.assertEqual(ParsePerfJson(before).Simplify().ToPerfJson(), after) 11762306a36Sopenharmony_ci 11862306a36Sopenharmony_ci before = 'a | 0' 11962306a36Sopenharmony_ci after = 'a' 12062306a36Sopenharmony_ci self.assertEqual(ParsePerfJson(before).Simplify().ToPerfJson(), after) 12162306a36Sopenharmony_ci 12262306a36Sopenharmony_ci before = '0 | a' 12362306a36Sopenharmony_ci after = 'a' 12462306a36Sopenharmony_ci self.assertEqual(ParsePerfJson(before).Simplify().ToPerfJson(), after) 12562306a36Sopenharmony_ci 12662306a36Sopenharmony_ci before = 'a * 0' 12762306a36Sopenharmony_ci after = '0' 12862306a36Sopenharmony_ci self.assertEqual(ParsePerfJson(before).Simplify().ToPerfJson(), after) 12962306a36Sopenharmony_ci 13062306a36Sopenharmony_ci before = '0 * a' 13162306a36Sopenharmony_ci after = '0' 13262306a36Sopenharmony_ci self.assertEqual(ParsePerfJson(before).Simplify().ToPerfJson(), after) 13362306a36Sopenharmony_ci 13462306a36Sopenharmony_ci before = 'a * 1' 13562306a36Sopenharmony_ci after = 'a' 13662306a36Sopenharmony_ci self.assertEqual(ParsePerfJson(before).Simplify().ToPerfJson(), after) 13762306a36Sopenharmony_ci 13862306a36Sopenharmony_ci before = '1 * a' 13962306a36Sopenharmony_ci after = 'a' 14062306a36Sopenharmony_ci self.assertEqual(ParsePerfJson(before).Simplify().ToPerfJson(), after) 14162306a36Sopenharmony_ci 14262306a36Sopenharmony_ci before = 'a if 0 else b' 14362306a36Sopenharmony_ci after = 'b' 14462306a36Sopenharmony_ci self.assertEqual(ParsePerfJson(before).Simplify().ToPerfJson(), after) 14562306a36Sopenharmony_ci 14662306a36Sopenharmony_ci before = 'a if 1 else b' 14762306a36Sopenharmony_ci after = 'a' 14862306a36Sopenharmony_ci self.assertEqual(ParsePerfJson(before).Simplify().ToPerfJson(), after) 14962306a36Sopenharmony_ci 15062306a36Sopenharmony_ci before = 'a if b else a' 15162306a36Sopenharmony_ci after = 'a' 15262306a36Sopenharmony_ci self.assertEqual(ParsePerfJson(before).Simplify().ToPerfJson(), after) 15362306a36Sopenharmony_ci 15462306a36Sopenharmony_ci # Pattern used to add a slots event to metrics that require it. 15562306a36Sopenharmony_ci before = '0 * SLOTS' 15662306a36Sopenharmony_ci after = '0 * SLOTS' 15762306a36Sopenharmony_ci self.assertEqual(ParsePerfJson(before).Simplify().ToPerfJson(), after) 15862306a36Sopenharmony_ci 15962306a36Sopenharmony_ci def test_RewriteMetricsInTermsOfOthers(self): 16062306a36Sopenharmony_ci Expression.__eq__ = lambda e1, e2: e1.Equals(e2) 16162306a36Sopenharmony_ci before = [('cpu', 'm1', ParsePerfJson('a + b + c + d')), 16262306a36Sopenharmony_ci ('cpu', 'm2', ParsePerfJson('a + b + c'))] 16362306a36Sopenharmony_ci after = {('cpu', 'm1'): ParsePerfJson('m2 + d')} 16462306a36Sopenharmony_ci self.assertEqual(RewriteMetricsInTermsOfOthers(before), after) 16562306a36Sopenharmony_ci Expression.__eq__ = None 16662306a36Sopenharmony_ci 16762306a36Sopenharmony_ciif __name__ == '__main__': 16862306a36Sopenharmony_ci unittest.main() 169