diff options
| -rw-r--r-- | lldb/test/.categories | 0 | ||||
| -rwxr-xr-x | lldb/test/attic/tester.py | 4 | ||||
| -rwxr-xr-x | lldb/test/dotest.py | 72 | ||||
| -rw-r--r-- | lldb/test/example/TestSequenceFunctions.py | 2 | ||||
| -rw-r--r-- | lldb/test/expression_command/.categories | 1 | ||||
| -rw-r--r-- | lldb/test/functionalities/completion/TestCompletion.py | 7 | ||||
| -rw-r--r-- | lldb/test/functionalities/data-formatter/.categories | 1 | ||||
| -rw-r--r-- | lldb/test/functionalities/data-formatter/data-formatter-objc/.categories | 1 | ||||
| -rw-r--r-- | lldb/test/functionalities/data-formatter/data-formatter-objc/TestDataFormatterObjC.py | 4 | ||||
| -rw-r--r-- | lldb/test/functionalities/expr-doesnt-deadlock/.categories | 1 | ||||
| -rw-r--r-- | lldb/test/functionalities/single-quote-in-filename-to-lldb/TestSingleQuoteInFilename.py | 9 | ||||
| -rw-r--r-- | lldb/test/lang/objc/.categories | 1 | ||||
| -rw-r--r-- | lldb/test/lldbtest.py | 24 | ||||
| -rw-r--r-- | lldb/test/python_api/.categories | 1 |
14 files changed, 123 insertions, 5 deletions
diff --git a/lldb/test/.categories b/lldb/test/.categories new file mode 100644 index 00000000000..e69de29bb2d --- /dev/null +++ b/lldb/test/.categories diff --git a/lldb/test/attic/tester.py b/lldb/test/attic/tester.py index 5d2495a024d..3f05fbed25d 100755 --- a/lldb/test/attic/tester.py +++ b/lldb/test/attic/tester.py @@ -98,11 +98,15 @@ class LLDBTestCase(unittest.TestCase): else: self.fail("Command " + command + " returned an error") return None + def getCategories(self): + return [] class SanityCheckTestCase(LLDBTestCase): def runTest(self): ret = self.runCommand("show arch", "show-arch") #print ret + def getCategories(self): + return [] suite = unittest.TestLoader().loadTestsFromTestCase(SanityCheckTestCase) unittest.TextTestRunner(verbosity=2).run(suite) diff --git a/lldb/test/dotest.py b/lldb/test/dotest.py index 7b6685d4689..c69b9dce0e7 100755 --- a/lldb/test/dotest.py +++ b/lldb/test/dotest.py @@ -66,6 +66,17 @@ class _WritelnDecorator(object): # Global variables: # +# Dictionary of categories +# When you define a new category for your testcases, be sure to add it here, or the test suite +# will gladly complain as soon as you try to use it. This allows us to centralize which categories +# exist, and to provide a description for each one +validCategories = { +'dataformatters':'Tests related to the type command and the data formatters subsystem', +'expression':'Tests related to the expression parser', +'objc':'Tests related to the Objective-C programming language support', +'pyapi':'Tests related to the Python API' +} + # The test suite. suite = unittest2.TestSuite() @@ -94,6 +105,13 @@ blacklist = None # The dictionary as a result of sourcing blacklistFile. blacklistConfig = {} +# The list of categories we said we care about +categoriesList = None +# set to true if we are going to use categories for cherry-picking test cases +useCategories = False +# use this to track per-category failures +failuresPerCategory = {} + # The config file is optional. configFile = None @@ -296,6 +314,9 @@ def parseOptionsAndInitTestdirs(): global dont_do_dwarf_test global blacklist global blacklistConfig + global categoriesList + global validCategories + global useCategories global configFile global archs global compilers @@ -353,6 +374,7 @@ def parseOptionsAndInitTestdirs(): X('-l', "Don't skip long running tests") group.add_argument('-p', metavar='pattern', help='Specify a regexp filename pattern for inclusion in the test suite') group.add_argument('-X', metavar='directory', help="Exclude a directory from consideration for test discovery. -X types => if 'types' appear in the pathname components of a potential testfile, it will be ignored") + group.add_argument('-G', '--category', metavar='category', action='append', dest='categoriesList', help=textwrap.dedent('''Specify categories of test cases of interest. Can be specified more than once.''')) # Configuration options group = parser.add_argument_group('Configuration options') @@ -400,6 +422,16 @@ def parseOptionsAndInitTestdirs(): else: archs = [platform_machine] + if args.categoriesList: + for category in args.categoriesList: + if not(category in validCategories): + print "fatal error: category '" + category + "' is not a valid category - edit dotest.py or correct your invocation" + sys.exit(1) + categoriesList = set(args.categoriesList) + useCategories = True + else: + categoriesList = [] + if args.compilers: compilers = args.compilers else: @@ -1228,7 +1260,34 @@ for ia in range(len(archs) if iterArchs else 1): else: return str(test) + def getCategoriesForTest(self,test): + if hasattr(test,"getCategories"): + test_categories = test.getCategories() + elif inspect.ismethod(test) and test.__self__ != None and hasattr(test.__self__,"getCategories"): + test_categories = test.__self__.getCategories() + else: + test_categories = [] + if test_categories == None: + test_categories = [] + return test_categories + + def shouldSkipBecauseOfCategories(self,test): + global useCategories + import inspect + if useCategories: + global categoriesList + test_categories = self.getCategoriesForTest(test) + if len(test_categories) == 0 or len(categoriesList & set(test_categories)) == 0: + return True + return False + + def hardMarkAsSkipped(self,test): + getattr(test, test._testMethodName).__func__.__unittest_skip__ = True + getattr(test, test._testMethodName).__func__.__unittest_skip_why__ = "test case does not fall in any category of interest for this run" + def startTest(self, test): + if self.shouldSkipBecauseOfCategories(test): + self.hardMarkAsSkipped(test) self.counter += 1 if self.showAll: self.stream.write(self.fmt % self.counter) @@ -1244,11 +1303,19 @@ for ia in range(len(archs) if iterArchs else 1): def addFailure(self, test, err): global sdir_has_content + global failuresPerCategory sdir_has_content = True super(LLDBTestResult, self).addFailure(test, err) method = getattr(test, "markFailure", None) if method: method() + if useCategories: + test_categories = self.getCategoriesForTest(test) + for category in test_categories: + if category in failuresPerCategory: + failuresPerCategory[category] = failuresPerCategory[category] + 1 + else: + failuresPerCategory[category] = 1 def addExpectedFailure(self, test, err): global sdir_has_content @@ -1296,6 +1363,11 @@ if sdir_has_content: sys.stderr.write("Session logs for test failures/errors/unexpected successes" " can be found in directory '%s'\n" % sdir_name) +if useCategories and len(failuresPerCategory) > 0: + sys.stderr.write("Failures per category:\n") + for category in failuresPerCategory: + sys.stderr.write("%s - %d\n" % (category,failuresPerCategory[category])) + fname = os.path.join(sdir_name, "TestFinished") with open(fname, "w") as f: print >> f, "Test finished at: %s\n" % datetime.datetime.now().strftime("%Y-%m-%d-%H_%M_%S") diff --git a/lldb/test/example/TestSequenceFunctions.py b/lldb/test/example/TestSequenceFunctions.py index e9bfd6a27ee..f4f3d019e42 100644 --- a/lldb/test/example/TestSequenceFunctions.py +++ b/lldb/test/example/TestSequenceFunctions.py @@ -29,6 +29,8 @@ class SequenceFunctionsTestCase(unittest.TestCase): for element in random.sample(self.seq, 5): self.assertTrue(element in self.seq) + def getCategories(self): + return [] if __name__ == '__main__': unittest.main() diff --git a/lldb/test/expression_command/.categories b/lldb/test/expression_command/.categories new file mode 100644 index 00000000000..897e40a99dd --- /dev/null +++ b/lldb/test/expression_command/.categories @@ -0,0 +1 @@ +expression diff --git a/lldb/test/functionalities/completion/TestCompletion.py b/lldb/test/functionalities/completion/TestCompletion.py index 8967a2204da..2017a3090f4 100644 --- a/lldb/test/functionalities/completion/TestCompletion.py +++ b/lldb/test/functionalities/completion/TestCompletion.py @@ -15,8 +15,11 @@ class CommandLineCompletionTestCase(TestBase): @classmethod def classCleanup(cls): """Cleanup the test byproducts.""" - os.remove("child_send.txt") - os.remove("child_read.txt") + try: + os.remove("child_send.txt") + os.remove("child_read.txt") + except: + pass def test_at(self): """Test that 'at' completes to 'attach '.""" diff --git a/lldb/test/functionalities/data-formatter/.categories b/lldb/test/functionalities/data-formatter/.categories new file mode 100644 index 00000000000..fe1da0247c6 --- /dev/null +++ b/lldb/test/functionalities/data-formatter/.categories @@ -0,0 +1 @@ +dataformatters diff --git a/lldb/test/functionalities/data-formatter/data-formatter-objc/.categories b/lldb/test/functionalities/data-formatter/data-formatter-objc/.categories new file mode 100644 index 00000000000..77b5ffcad61 --- /dev/null +++ b/lldb/test/functionalities/data-formatter/data-formatter-objc/.categories @@ -0,0 +1 @@ +dataformatter,objc diff --git a/lldb/test/functionalities/data-formatter/data-formatter-objc/TestDataFormatterObjC.py b/lldb/test/functionalities/data-formatter/data-formatter-objc/TestDataFormatterObjC.py index b4340d5cb80..95022b497f1 100644 --- a/lldb/test/functionalities/data-formatter/data-formatter-objc/TestDataFormatterObjC.py +++ b/lldb/test/functionalities/data-formatter/data-formatter-objc/TestDataFormatterObjC.py @@ -89,6 +89,8 @@ class ObjCDataFormatterTestCase(TestBase): """Test common cases of expression parser <--> formatters interaction.""" self.buildDsym() self.expr_objc_data_formatter_commands() + def getCategories(self): + return ['dataformatters','expression','objc'] @unittest2.skipUnless(sys.platform.startswith("darwin"), "requires Darwin") @dwarf_test @@ -96,6 +98,8 @@ class ObjCDataFormatterTestCase(TestBase): """Test common cases of expression parser <--> formatters interaction.""" self.buildDwarf() self.expr_objc_data_formatter_commands() + def getCategories(self): + return ['dataformatters','expression','objc'] def setUp(self): # Call super's setUp(). diff --git a/lldb/test/functionalities/expr-doesnt-deadlock/.categories b/lldb/test/functionalities/expr-doesnt-deadlock/.categories new file mode 100644 index 00000000000..897e40a99dd --- /dev/null +++ b/lldb/test/functionalities/expr-doesnt-deadlock/.categories @@ -0,0 +1 @@ +expression diff --git a/lldb/test/functionalities/single-quote-in-filename-to-lldb/TestSingleQuoteInFilename.py b/lldb/test/functionalities/single-quote-in-filename-to-lldb/TestSingleQuoteInFilename.py index ae9749617d5..eb7abc27653 100644 --- a/lldb/test/functionalities/single-quote-in-filename-to-lldb/TestSingleQuoteInFilename.py +++ b/lldb/test/functionalities/single-quote-in-filename-to-lldb/TestSingleQuoteInFilename.py @@ -16,9 +16,12 @@ class SingleQuoteInCommandLineTestCase(TestBase): @classmethod def classCleanup(cls): """Cleanup the test byproducts.""" - os.remove("child_send.txt") - os.remove("child_read.txt") - os.remove(cls.myexe) + try: + os.remove("child_send.txt") + os.remove("child_read.txt") + os.remove(cls.myexe) + except: + pass def test_lldb_invocation_with_single_quote_in_filename(self): """Test that 'lldb my_file_name' works where my_file_name is a string with a single quote char in it.""" diff --git a/lldb/test/lang/objc/.categories b/lldb/test/lang/objc/.categories new file mode 100644 index 00000000000..72cf07c1efe --- /dev/null +++ b/lldb/test/lang/objc/.categories @@ -0,0 +1 @@ +objc diff --git a/lldb/test/lldbtest.py b/lldb/test/lldbtest.py index b14eacd02c5..4aa3f861cd0 100644 --- a/lldb/test/lldbtest.py +++ b/lldb/test/lldbtest.py @@ -946,6 +946,30 @@ class TestBase(Base): waitTime = float(os.environ["LLDB_TIME_WAIT_BETWEEN_TEST_CASES"]) time.sleep(waitTime) + # Returns the list of categories to which this test case belongs + # by default, look for a ".categories" file, and read its contents + # if no such file exists, traverse the hierarchy - we guarantee + # a .categories to exist at the top level directory so we do not end up + # looping endlessly - subclasses are free to define their own categories + # in whatever way makes sense to them + def getCategories(self): + import inspect + import os.path + folder = inspect.getfile(self.__class__) + folder = os.path.dirname(folder) + while folder != '/': + categories_file_name = os.path.join(folder,".categories") + if os.path.exists(categories_file_name): + categories_file = open(categories_file_name,'r') + categories = categories_file.readline() + categories_file.close() + categories = str.replace(categories,'\n','') + categories = str.replace(categories,'\r','') + return categories.split(',') + else: + folder = os.path.dirname(folder) + continue + def setUp(self): #import traceback #traceback.print_stack() diff --git a/lldb/test/python_api/.categories b/lldb/test/python_api/.categories new file mode 100644 index 00000000000..db8069c3b9f --- /dev/null +++ b/lldb/test/python_api/.categories @@ -0,0 +1 @@ +pyapi |

