169 lines
		
	
	
		
			5.9 KiB
		
	
	
	
		
			Python
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			169 lines
		
	
	
		
			5.9 KiB
		
	
	
	
		
			Python
		
	
	
		
			Executable File
		
	
	
	
	
| #! /usr/bin/python3 -sP
 | |
| # 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()
 |