109467b48Spatrick# RUN: %{python} %s 209467b48Spatrick# 309467b48Spatrick# END. 409467b48Spatrick 509467b48Spatrick 609467b48Spatrickimport os.path 709467b48Spatrickimport platform 809467b48Spatrickimport unittest 909467b48Spatrick 1009467b48Spatrickimport lit.discovery 1109467b48Spatrickimport lit.LitConfig 1209467b48Spatrickimport lit.Test as Test 1309467b48Spatrickfrom lit.TestRunner import ParserKind, IntegratedTestKeywordParser, \ 1409467b48Spatrick parseIntegratedTestScript 1509467b48Spatrick 1609467b48Spatrick 1709467b48Spatrickclass TestIntegratedTestKeywordParser(unittest.TestCase): 1809467b48Spatrick inputTestCase = None 1909467b48Spatrick 2009467b48Spatrick @staticmethod 2109467b48Spatrick def load_keyword_parser_lit_tests(): 2209467b48Spatrick """ 2309467b48Spatrick Create and load the LIT test suite and test objects used by 2409467b48Spatrick TestIntegratedTestKeywordParser 2509467b48Spatrick """ 2609467b48Spatrick # Create the global config object. 2709467b48Spatrick lit_config = lit.LitConfig.LitConfig(progname='lit', 2809467b48Spatrick path=[], 2909467b48Spatrick quiet=False, 3009467b48Spatrick useValgrind=False, 3109467b48Spatrick valgrindLeakCheck=False, 3209467b48Spatrick valgrindArgs=[], 3309467b48Spatrick noExecute=False, 3409467b48Spatrick debug=False, 3509467b48Spatrick isWindows=( 3609467b48Spatrick platform.system() == 'Windows'), 37*d415bd75Srobert order='smart', 3809467b48Spatrick params={}) 3909467b48Spatrick TestIntegratedTestKeywordParser.litConfig = lit_config 4009467b48Spatrick # Perform test discovery. 4109467b48Spatrick test_path = os.path.dirname(os.path.dirname(__file__)) 4209467b48Spatrick inputs = [os.path.join(test_path, 'Inputs/testrunner-custom-parsers/')] 4309467b48Spatrick assert os.path.isdir(inputs[0]) 4473471bf0Spatrick tests = lit.discovery.find_tests_for_inputs(lit_config, inputs, False) 4509467b48Spatrick assert len(tests) == 1 and "there should only be one test" 4609467b48Spatrick TestIntegratedTestKeywordParser.inputTestCase = tests[0] 4709467b48Spatrick 4809467b48Spatrick @staticmethod 4909467b48Spatrick def make_parsers(): 5009467b48Spatrick def custom_parse(line_number, line, output): 5109467b48Spatrick if output is None: 5209467b48Spatrick output = [] 5309467b48Spatrick output += [part for part in line.split(' ') if part.strip()] 5409467b48Spatrick return output 5509467b48Spatrick 5609467b48Spatrick return [ 5709467b48Spatrick IntegratedTestKeywordParser("MY_TAG.", ParserKind.TAG), 5809467b48Spatrick IntegratedTestKeywordParser("MY_DNE_TAG.", ParserKind.TAG), 5909467b48Spatrick IntegratedTestKeywordParser("MY_LIST:", ParserKind.LIST), 6009467b48Spatrick IntegratedTestKeywordParser("MY_BOOL:", ParserKind.BOOLEAN_EXPR), 61097a140dSpatrick IntegratedTestKeywordParser("MY_INT:", ParserKind.INTEGER), 6209467b48Spatrick IntegratedTestKeywordParser("MY_RUN:", ParserKind.COMMAND), 6309467b48Spatrick IntegratedTestKeywordParser("MY_CUSTOM:", ParserKind.CUSTOM, 6409467b48Spatrick custom_parse), 65*d415bd75Srobert IntegratedTestKeywordParser("MY_DEFINE:", ParserKind.DEFINE), 66*d415bd75Srobert IntegratedTestKeywordParser("MY_REDEFINE:", ParserKind.REDEFINE), 6709467b48Spatrick ] 6809467b48Spatrick 6909467b48Spatrick @staticmethod 7009467b48Spatrick def get_parser(parser_list, keyword): 7109467b48Spatrick for p in parser_list: 7209467b48Spatrick if p.keyword == keyword: 7309467b48Spatrick return p 7409467b48Spatrick assert False and "parser not found" 7509467b48Spatrick 7609467b48Spatrick @staticmethod 77097a140dSpatrick def parse_test(parser_list, allow_result=False): 7809467b48Spatrick script = parseIntegratedTestScript( 7909467b48Spatrick TestIntegratedTestKeywordParser.inputTestCase, 8009467b48Spatrick additional_parsers=parser_list, require_script=False) 81097a140dSpatrick if isinstance(script, lit.Test.Result): 82097a140dSpatrick assert allow_result 83097a140dSpatrick else: 8409467b48Spatrick assert isinstance(script, list) 8509467b48Spatrick assert len(script) == 0 86097a140dSpatrick return script 8709467b48Spatrick 8809467b48Spatrick def test_tags(self): 8909467b48Spatrick parsers = self.make_parsers() 9009467b48Spatrick self.parse_test(parsers) 9109467b48Spatrick tag_parser = self.get_parser(parsers, 'MY_TAG.') 9209467b48Spatrick dne_tag_parser = self.get_parser(parsers, 'MY_DNE_TAG.') 9309467b48Spatrick self.assertTrue(tag_parser.getValue()) 9409467b48Spatrick self.assertFalse(dne_tag_parser.getValue()) 9509467b48Spatrick 9609467b48Spatrick def test_lists(self): 9709467b48Spatrick parsers = self.make_parsers() 9809467b48Spatrick self.parse_test(parsers) 9909467b48Spatrick list_parser = self.get_parser(parsers, 'MY_LIST:') 10009467b48Spatrick self.assertEqual(list_parser.getValue(), 10109467b48Spatrick ['one', 'two', 'three', 'four']) 10209467b48Spatrick 10309467b48Spatrick def test_commands(self): 10409467b48Spatrick parsers = self.make_parsers() 10509467b48Spatrick self.parse_test(parsers) 10609467b48Spatrick cmd_parser = self.get_parser(parsers, 'MY_RUN:') 10709467b48Spatrick value = cmd_parser.getValue() 10809467b48Spatrick self.assertEqual(len(value), 2) # there are only two run lines 109*d415bd75Srobert self.assertEqual(value[0].command.strip(), 110*d415bd75Srobert "%dbg(MY_RUN: at line 4) baz") 111*d415bd75Srobert self.assertEqual(value[1].command.strip(), 112*d415bd75Srobert "%dbg(MY_RUN: at line 7) foo bar") 11309467b48Spatrick 11409467b48Spatrick def test_boolean(self): 11509467b48Spatrick parsers = self.make_parsers() 11609467b48Spatrick self.parse_test(parsers) 11709467b48Spatrick bool_parser = self.get_parser(parsers, 'MY_BOOL:') 11809467b48Spatrick value = bool_parser.getValue() 11909467b48Spatrick self.assertEqual(len(value), 2) # there are only two run lines 12009467b48Spatrick self.assertEqual(value[0].strip(), "a && (b)") 12109467b48Spatrick self.assertEqual(value[1].strip(), "d") 12209467b48Spatrick 123097a140dSpatrick def test_integer(self): 124097a140dSpatrick parsers = self.make_parsers() 125097a140dSpatrick self.parse_test(parsers) 126097a140dSpatrick int_parser = self.get_parser(parsers, 'MY_INT:') 127097a140dSpatrick value = int_parser.getValue() 128097a140dSpatrick self.assertEqual(len(value), 2) # there are only two MY_INT: lines 129097a140dSpatrick self.assertEqual(type(value[0]), int) 130097a140dSpatrick self.assertEqual(value[0], 4) 131097a140dSpatrick self.assertEqual(type(value[1]), int) 132097a140dSpatrick self.assertEqual(value[1], 6) 133097a140dSpatrick 134097a140dSpatrick def test_bad_parser_type(self): 135097a140dSpatrick parsers = self.make_parsers() + ["BAD_PARSER_TYPE"] 136097a140dSpatrick script = self.parse_test(parsers, allow_result=True) 137097a140dSpatrick self.assertTrue(isinstance(script, lit.Test.Result)) 138097a140dSpatrick self.assertEqual(script.code, lit.Test.UNRESOLVED) 139097a140dSpatrick self.assertEqual('Additional parser must be an instance of ' 140097a140dSpatrick 'IntegratedTestKeywordParser', 141097a140dSpatrick script.output) 142097a140dSpatrick 143097a140dSpatrick def test_duplicate_keyword(self): 144097a140dSpatrick parsers = self.make_parsers() + \ 145097a140dSpatrick [IntegratedTestKeywordParser("KEY:", ParserKind.BOOLEAN_EXPR), 146097a140dSpatrick IntegratedTestKeywordParser("KEY:", ParserKind.BOOLEAN_EXPR)] 147097a140dSpatrick script = self.parse_test(parsers, allow_result=True) 148097a140dSpatrick self.assertTrue(isinstance(script, lit.Test.Result)) 149097a140dSpatrick self.assertEqual(script.code, lit.Test.UNRESOLVED) 150097a140dSpatrick self.assertEqual("Parser for keyword 'KEY:' already exists", 151097a140dSpatrick script.output) 152097a140dSpatrick 15309467b48Spatrick def test_boolean_unterminated(self): 15409467b48Spatrick parsers = self.make_parsers() + \ 15509467b48Spatrick [IntegratedTestKeywordParser("MY_BOOL_UNTERMINATED:", ParserKind.BOOLEAN_EXPR)] 156097a140dSpatrick script = self.parse_test(parsers, allow_result=True) 157097a140dSpatrick self.assertTrue(isinstance(script, lit.Test.Result)) 158097a140dSpatrick self.assertEqual(script.code, lit.Test.UNRESOLVED) 159097a140dSpatrick self.assertEqual("Test has unterminated 'MY_BOOL_UNTERMINATED:' lines " 160097a140dSpatrick "(with '\\')", 161097a140dSpatrick script.output) 16209467b48Spatrick 16309467b48Spatrick def test_custom(self): 16409467b48Spatrick parsers = self.make_parsers() 16509467b48Spatrick self.parse_test(parsers) 16609467b48Spatrick custom_parser = self.get_parser(parsers, 'MY_CUSTOM:') 16709467b48Spatrick value = custom_parser.getValue() 16809467b48Spatrick self.assertEqual(value, ['a', 'b', 'c']) 16909467b48Spatrick 170*d415bd75Srobert def test_defines(self): 171*d415bd75Srobert parsers = self.make_parsers() 172*d415bd75Srobert self.parse_test(parsers) 173*d415bd75Srobert cmd_parser = self.get_parser(parsers, 'MY_DEFINE:') 174*d415bd75Srobert value = cmd_parser.getValue() 175*d415bd75Srobert self.assertEqual(len(value), 1) # there's only one MY_DEFINE directive 176*d415bd75Srobert self.assertEqual(value[0].new_subst, True) 177*d415bd75Srobert self.assertEqual(value[0].name, '%{name}') 178*d415bd75Srobert self.assertEqual(value[0].value, 'value one') 179*d415bd75Srobert 180*d415bd75Srobert def test_redefines(self): 181*d415bd75Srobert parsers = self.make_parsers() 182*d415bd75Srobert self.parse_test(parsers) 183*d415bd75Srobert cmd_parser = self.get_parser(parsers, 'MY_REDEFINE:') 184*d415bd75Srobert value = cmd_parser.getValue() 185*d415bd75Srobert self.assertEqual(len(value), 1) # there's only one MY_REDEFINE directive 186*d415bd75Srobert self.assertEqual(value[0].new_subst, False) 187*d415bd75Srobert self.assertEqual(value[0].name, '%{name}') 188*d415bd75Srobert self.assertEqual(value[0].value, 'value two') 189*d415bd75Srobert 19009467b48Spatrick def test_bad_keywords(self): 19109467b48Spatrick def custom_parse(line_number, line, output): 19209467b48Spatrick return output 19309467b48Spatrick 19409467b48Spatrick try: 19509467b48Spatrick IntegratedTestKeywordParser("TAG_NO_SUFFIX", ParserKind.TAG), 19609467b48Spatrick self.fail("TAG_NO_SUFFIX failed to raise an exception") 19709467b48Spatrick except ValueError as e: 19809467b48Spatrick pass 19909467b48Spatrick except BaseException as e: 20009467b48Spatrick self.fail("TAG_NO_SUFFIX raised the wrong exception: %r" % e) 20109467b48Spatrick 20209467b48Spatrick try: 20309467b48Spatrick IntegratedTestKeywordParser("TAG_WITH_COLON:", ParserKind.TAG), 20409467b48Spatrick self.fail("TAG_WITH_COLON: failed to raise an exception") 20509467b48Spatrick except ValueError as e: 20609467b48Spatrick pass 20709467b48Spatrick except BaseException as e: 20809467b48Spatrick self.fail("TAG_WITH_COLON: raised the wrong exception: %r" % e) 20909467b48Spatrick 21009467b48Spatrick try: 21109467b48Spatrick IntegratedTestKeywordParser("LIST_WITH_DOT.", ParserKind.LIST), 21209467b48Spatrick self.fail("LIST_WITH_DOT. failed to raise an exception") 21309467b48Spatrick except ValueError as e: 21409467b48Spatrick pass 21509467b48Spatrick except BaseException as e: 21609467b48Spatrick self.fail("LIST_WITH_DOT. raised the wrong exception: %r" % e) 21709467b48Spatrick 21809467b48Spatrick try: 21909467b48Spatrick IntegratedTestKeywordParser("CUSTOM_NO_SUFFIX", 22009467b48Spatrick ParserKind.CUSTOM, custom_parse), 22109467b48Spatrick self.fail("CUSTOM_NO_SUFFIX failed to raise an exception") 22209467b48Spatrick except ValueError as e: 22309467b48Spatrick pass 22409467b48Spatrick except BaseException as e: 22509467b48Spatrick self.fail("CUSTOM_NO_SUFFIX raised the wrong exception: %r" % e) 22609467b48Spatrick 22709467b48Spatrick # Both '.' and ':' are allowed for CUSTOM keywords. 22809467b48Spatrick try: 22909467b48Spatrick IntegratedTestKeywordParser("CUSTOM_WITH_DOT.", 23009467b48Spatrick ParserKind.CUSTOM, custom_parse), 23109467b48Spatrick except BaseException as e: 23209467b48Spatrick self.fail("CUSTOM_WITH_DOT. raised an exception: %r" % e) 23309467b48Spatrick try: 23409467b48Spatrick IntegratedTestKeywordParser("CUSTOM_WITH_COLON:", 23509467b48Spatrick ParserKind.CUSTOM, custom_parse), 23609467b48Spatrick except BaseException as e: 23709467b48Spatrick self.fail("CUSTOM_WITH_COLON: raised an exception: %r" % e) 23809467b48Spatrick 23909467b48Spatrick try: 24009467b48Spatrick IntegratedTestKeywordParser("CUSTOM_NO_PARSER:", 24109467b48Spatrick ParserKind.CUSTOM), 24209467b48Spatrick self.fail("CUSTOM_NO_PARSER: failed to raise an exception") 24309467b48Spatrick except ValueError as e: 24409467b48Spatrick pass 24509467b48Spatrick except BaseException as e: 24609467b48Spatrick self.fail("CUSTOM_NO_PARSER: raised the wrong exception: %r" % e) 24709467b48Spatrick 248097a140dSpatrickclass TestApplySubtitutions(unittest.TestCase): 249097a140dSpatrick def test_simple(self): 250097a140dSpatrick script = ["echo %bar"] 251097a140dSpatrick substitutions = [("%bar", "hello")] 252097a140dSpatrick result = lit.TestRunner.applySubstitutions(script, substitutions) 253097a140dSpatrick self.assertEqual(result, ["echo hello"]) 254097a140dSpatrick 255097a140dSpatrick def test_multiple_substitutions(self): 256097a140dSpatrick script = ["echo %bar %baz"] 257097a140dSpatrick substitutions = [("%bar", "hello"), 258097a140dSpatrick ("%baz", "world"), 259097a140dSpatrick ("%useless", "shouldnt expand")] 260097a140dSpatrick result = lit.TestRunner.applySubstitutions(script, substitutions) 261097a140dSpatrick self.assertEqual(result, ["echo hello world"]) 262097a140dSpatrick 263097a140dSpatrick def test_multiple_script_lines(self): 264097a140dSpatrick script = ["%cxx %compile_flags -c -o %t.o", 265097a140dSpatrick "%cxx %link_flags %t.o -o %t.exe"] 266097a140dSpatrick substitutions = [("%cxx", "clang++"), 267097a140dSpatrick ("%compile_flags", "-std=c++11 -O3"), 268097a140dSpatrick ("%link_flags", "-lc++")] 269097a140dSpatrick result = lit.TestRunner.applySubstitutions(script, substitutions) 270097a140dSpatrick self.assertEqual(result, ["clang++ -std=c++11 -O3 -c -o %t.o", 271097a140dSpatrick "clang++ -lc++ %t.o -o %t.exe"]) 272097a140dSpatrick 273097a140dSpatrick def test_recursive_substitution_real(self): 274097a140dSpatrick script = ["%build %s"] 275097a140dSpatrick substitutions = [("%cxx", "clang++"), 276097a140dSpatrick ("%compile_flags", "-std=c++11 -O3"), 277097a140dSpatrick ("%link_flags", "-lc++"), 278097a140dSpatrick ("%build", "%cxx %compile_flags %link_flags %s -o %t.exe")] 279097a140dSpatrick result = lit.TestRunner.applySubstitutions(script, substitutions, recursion_limit=3) 280097a140dSpatrick self.assertEqual(result, ["clang++ -std=c++11 -O3 -lc++ %s -o %t.exe %s"]) 281097a140dSpatrick 282097a140dSpatrick def test_recursive_substitution_limit(self): 283097a140dSpatrick script = ["%rec5"] 284097a140dSpatrick # Make sure the substitutions are not in an order where the global 285097a140dSpatrick # substitution would appear to be recursive just because they are 286097a140dSpatrick # processed in the right order. 287097a140dSpatrick substitutions = [("%rec1", "STOP"), ("%rec2", "%rec1"), 288097a140dSpatrick ("%rec3", "%rec2"), ("%rec4", "%rec3"), ("%rec5", "%rec4")] 289097a140dSpatrick for limit in [5, 6, 7]: 290097a140dSpatrick result = lit.TestRunner.applySubstitutions(script, substitutions, recursion_limit=limit) 291097a140dSpatrick self.assertEqual(result, ["STOP"]) 292097a140dSpatrick 293097a140dSpatrick def test_recursive_substitution_limit_exceeded(self): 294097a140dSpatrick script = ["%rec5"] 295097a140dSpatrick substitutions = [("%rec1", "STOP"), ("%rec2", "%rec1"), 296097a140dSpatrick ("%rec3", "%rec2"), ("%rec4", "%rec3"), ("%rec5", "%rec4")] 297097a140dSpatrick for limit in [0, 1, 2, 3, 4]: 298097a140dSpatrick try: 299097a140dSpatrick lit.TestRunner.applySubstitutions(script, substitutions, recursion_limit=limit) 300097a140dSpatrick self.fail("applySubstitutions should have raised an exception") 301097a140dSpatrick except ValueError: 302097a140dSpatrick pass 303097a140dSpatrick 304097a140dSpatrick def test_recursive_substitution_invalid_value(self): 305097a140dSpatrick script = ["%rec5"] 306097a140dSpatrick substitutions = [("%rec1", "STOP"), ("%rec2", "%rec1"), 307097a140dSpatrick ("%rec3", "%rec2"), ("%rec4", "%rec3"), ("%rec5", "%rec4")] 308097a140dSpatrick for limit in [-1, -2, -3, "foo"]: 309097a140dSpatrick try: 310097a140dSpatrick lit.TestRunner.applySubstitutions(script, substitutions, recursion_limit=limit) 311097a140dSpatrick self.fail("applySubstitutions should have raised an exception") 312097a140dSpatrick except AssertionError: 313097a140dSpatrick pass 314097a140dSpatrick 315097a140dSpatrick 31609467b48Spatrickif __name__ == '__main__': 31709467b48Spatrick TestIntegratedTestKeywordParser.load_keyword_parser_lit_tests() 31809467b48Spatrick unittest.main(verbosity=2) 319