summaryrefslogtreecommitdiff
path: root/test/gtest_filter_unittest.py
diff options
context:
space:
mode:
Diffstat (limited to 'test/gtest_filter_unittest.py')
-rwxr-xr-xtest/gtest_filter_unittest.py162
1 files changed, 151 insertions, 11 deletions
diff --git a/test/gtest_filter_unittest.py b/test/gtest_filter_unittest.py
index 35307a2..c3a016c 100755
--- a/test/gtest_filter_unittest.py
+++ b/test/gtest_filter_unittest.py
@@ -36,6 +36,9 @@ the GTEST_FILTER environment variable or the --gtest_filter flag.
This script tests such functionality by invoking
gtest_filter_unittest_ (a program written with Google Test) with different
environments and command line flags.
+
+Note that test sharding may also influence which tests are filtered. Therefore,
+we test that here also.
"""
__author__ = 'wan@google.com (Zhanyong Wan)'
@@ -43,6 +46,7 @@ __author__ = 'wan@google.com (Zhanyong Wan)'
import os
import re
import sets
+import tempfile
import unittest
import gtest_test_utils
@@ -51,6 +55,11 @@ import gtest_test_utils
# The environment variable for specifying the test filters.
FILTER_ENV_VAR = 'GTEST_FILTER'
+# The environment variables for test sharding.
+TOTAL_SHARDS_ENV_VAR = 'GTEST_TOTAL_SHARDS'
+SHARD_INDEX_ENV_VAR = 'GTEST_SHARD_INDEX'
+SHARD_STATUS_FILE_ENV_VAR = 'GTEST_SHARD_STATUS_FILE'
+
# The command line flag for specifying the test filters.
FILTER_FLAG = 'gtest_filter'
@@ -103,6 +112,9 @@ ACTIVE_TESTS = [
'BazTest.TestOne',
'BazTest.TestA',
'BazTest.TestB',
+
+ 'HasDeathTest.Test1',
+ 'HasDeathTest.Test2',
] + PARAM_TESTS
param_tests_present = None
@@ -121,7 +133,7 @@ def SetEnvVar(env_var, value):
def Run(command):
"""Runs a Google Test program and returns a list of full names of the
- tests that were run.
+ tests that were run along with the test exit code.
"""
stdout_file = os.popen(command, 'r')
@@ -137,9 +149,32 @@ def Run(command):
if match is not None:
test = match.group(1)
tests_run += [test_case + '.' + test]
- stdout_file.close()
- return tests_run
+ exit_code = stdout_file.close()
+ return (tests_run, exit_code)
+
+
+def InvokeWithModifiedEnv(extra_env, function, *args, **kwargs):
+ """Runs the given function and arguments in a modified environment."""
+ try:
+ original_env = os.environ.copy()
+ os.environ.update(extra_env)
+ return function(*args, **kwargs)
+ finally:
+ for key in extra_env.iterkeys():
+ if key in original_env:
+ os.environ[key] = original_env[key]
+ else:
+ del os.environ[key]
+
+
+def RunWithSharding(total_shards, shard_index, command):
+ """Runs the Google Test program shard and returns a list of full names of the
+ tests that were run along with the exit code.
+ """
+ extra_env = {SHARD_INDEX_ENV_VAR: str(shard_index),
+ TOTAL_SHARDS_ENV_VAR: str(total_shards)}
+ return InvokeWithModifiedEnv(extra_env, Run, command)
# The unit test.
@@ -160,6 +195,15 @@ class GTestFilterUnitTest(unittest.TestCase):
for elem in rhs:
self.assert_(elem in lhs, '%s in %s' % (elem, lhs))
+ def AssertPartitionIsValid(self, set_var, list_of_sets):
+ """Asserts that list_of_sets is a valid partition of set_var."""
+
+ full_partition = []
+ for slice_var in list_of_sets:
+ full_partition.extend(slice_var)
+ self.assertEqual(len(set_var), len(full_partition))
+ self.assertEqual(sorted(set_var), sorted(full_partition))
+
def RunAndVerify(self, gtest_filter, tests_to_run):
"""Runs gtest_flag_unittest_ with the given filter, and verifies
that the right set of tests were run.
@@ -173,7 +217,7 @@ class GTestFilterUnitTest(unittest.TestCase):
# First, tests using GTEST_FILTER.
SetEnvVar(FILTER_ENV_VAR, gtest_filter)
- tests_run = Run(COMMAND)
+ tests_run = Run(COMMAND)[0]
SetEnvVar(FILTER_ENV_VAR, None)
self.AssertSetEqual(tests_run, tests_to_run)
@@ -185,9 +229,27 @@ class GTestFilterUnitTest(unittest.TestCase):
else:
command = '%s --%s=%s' % (COMMAND, FILTER_FLAG, gtest_filter)
- tests_run = Run(command)
+ tests_run = Run(command)[0]
self.AssertSetEqual(tests_run, tests_to_run)
+ def RunAndVerifyWithSharding(self, gtest_filter, total_shards, tests_to_run,
+ command=COMMAND, check_exit_0=False):
+ """Runs all shards of gtest_flag_unittest_ with the given filter, and
+ verifies that the right set of tests were run. The union of tests run
+ on each shard should be identical to tests_to_run, without duplicates.
+ If check_exit_0, make sure that all shards returned 0.
+ """
+ SetEnvVar(FILTER_ENV_VAR, gtest_filter)
+ partition = []
+ for i in range(0, total_shards):
+ (tests_run, exit_code) = RunWithSharding(total_shards, i, command)
+ if check_exit_0:
+ self.assert_(exit_code is None)
+ partition.append(tests_run)
+
+ self.AssertPartitionIsValid(tests_to_run, partition)
+ SetEnvVar(FILTER_ENV_VAR, None)
+
def RunAndVerifyAllowingDisabled(self, gtest_filter, tests_to_run):
"""Runs gtest_flag_unittest_ with the given filter, and enables
disabled tests. Verifies that the right set of tests were run.
@@ -197,7 +259,7 @@ class GTestFilterUnitTest(unittest.TestCase):
if gtest_filter is not None:
command = '%s --%s=%s' % (command, FILTER_FLAG, gtest_filter)
- tests_run = Run(command)
+ tests_run = Run(command)[0]
self.AssertSetEqual(tests_run, tests_to_run)
def setUp(self):
@@ -214,10 +276,22 @@ class GTestFilterUnitTest(unittest.TestCase):
self.RunAndVerify(None, ACTIVE_TESTS)
+ def testDefaultBehaviorWithShards(self):
+ """Tests the behavior of not specifying the filter, with sharding
+ enabled.
+ """
+ self.RunAndVerifyWithSharding(None, 1, ACTIVE_TESTS)
+ self.RunAndVerifyWithSharding(None, 2, ACTIVE_TESTS)
+ self.RunAndVerifyWithSharding(None, len(ACTIVE_TESTS) - 1, ACTIVE_TESTS)
+ self.RunAndVerifyWithSharding(None, len(ACTIVE_TESTS), ACTIVE_TESTS)
+ self.RunAndVerifyWithSharding(None, len(ACTIVE_TESTS) + 1, ACTIVE_TESTS)
+
def testEmptyFilter(self):
"""Tests an empty filter."""
self.RunAndVerify('', [])
+ self.RunAndVerifyWithSharding('', 1, [])
+ self.RunAndVerifyWithSharding('', 2, [])
def testBadFilter(self):
"""Tests a filter that matches nothing."""
@@ -230,12 +304,14 @@ class GTestFilterUnitTest(unittest.TestCase):
self.RunAndVerify('FooTest.Xyz', ['FooTest.Xyz'])
self.RunAndVerifyAllowingDisabled('FooTest.Xyz', ['FooTest.Xyz'])
+ self.RunAndVerifyWithSharding('FooTest.Xyz', 5, ['FooTest.Xyz'])
def testUniversalFilters(self):
"""Tests filters that match everything."""
self.RunAndVerify('*', ACTIVE_TESTS)
self.RunAndVerify('*.*', ACTIVE_TESTS)
+ self.RunAndVerifyWithSharding('*.*', len(ACTIVE_TESTS) - 3, ACTIVE_TESTS)
self.RunAndVerifyAllowingDisabled('*', ACTIVE_TESTS + DISABLED_TESTS)
self.RunAndVerifyAllowingDisabled('*.*', ACTIVE_TESTS + DISABLED_TESTS)
@@ -289,7 +365,10 @@ class GTestFilterUnitTest(unittest.TestCase):
'BazTest.TestOne',
'BazTest.TestA',
- 'BazTest.TestB' ] + PARAM_TESTS)
+ 'BazTest.TestB',
+
+ 'HasDeathTest.Test1',
+ 'HasDeathTest.Test2', ] + PARAM_TESTS)
def testWildcardInTestName(self):
"""Tests using wildcard in the test name."""
@@ -350,7 +429,8 @@ class GTestFilterUnitTest(unittest.TestCase):
])
def testNegativeFilters(self):
- self.RunAndVerify('*-FooTest.Abc', [
+ self.RunAndVerify('*-HasDeathTest.Test1', [
+ 'FooTest.Abc',
'FooTest.Xyz',
'BarTest.TestOne',
@@ -360,14 +440,20 @@ class GTestFilterUnitTest(unittest.TestCase):
'BazTest.TestOne',
'BazTest.TestA',
'BazTest.TestB',
+
+ 'HasDeathTest.Test2',
] + PARAM_TESTS)
- self.RunAndVerify('*-FooTest.Abc:BazTest.*', [
+ self.RunAndVerify('*-FooTest.Abc:HasDeathTest.*', [
'FooTest.Xyz',
'BarTest.TestOne',
'BarTest.TestTwo',
'BarTest.TestThree',
+
+ 'BazTest.TestOne',
+ 'BazTest.TestA',
+ 'BazTest.TestB',
] + PARAM_TESTS)
self.RunAndVerify('BarTest.*-BarTest.TestOne', [
@@ -376,7 +462,7 @@ class GTestFilterUnitTest(unittest.TestCase):
])
# Tests without leading '*'.
- self.RunAndVerify('-FooTest.Abc:FooTest.Xyz', [
+ self.RunAndVerify('-FooTest.Abc:FooTest.Xyz:HasDeathTest.*', [
'BarTest.TestOne',
'BarTest.TestTwo',
'BarTest.TestThree',
@@ -412,11 +498,65 @@ class GTestFilterUnitTest(unittest.TestCase):
SetEnvVar(FILTER_ENV_VAR, 'Foo*')
command = '%s --%s=%s' % (COMMAND, FILTER_FLAG, '*One')
- tests_run = Run(command)
+ tests_run = Run(command)[0]
SetEnvVar(FILTER_ENV_VAR, None)
self.AssertSetEqual(tests_run, ['BarTest.TestOne', 'BazTest.TestOne'])
+ def testShardStatusFileIsCreated(self):
+ """Tests that the shard file is created if specified in the environment."""
+
+ test_tmpdir = tempfile.mkdtemp()
+ shard_status_file = os.path.join(test_tmpdir, 'shard_status_file')
+ self.assert_(not os.path.exists(shard_status_file))
+
+ extra_env = {SHARD_STATUS_FILE_ENV_VAR: shard_status_file}
+ stdout_file = InvokeWithModifiedEnv(extra_env, os.popen, COMMAND, 'r')
+ try:
+ stdout_file.readlines()
+ finally:
+ stdout_file.close()
+ self.assert_(os.path.exists(shard_status_file))
+ os.remove(shard_status_file)
+ os.removedirs(test_tmpdir)
+
+ def testShardStatusFileIsCreatedWithListTests(self):
+ """Tests that the shard file is created with --gtest_list_tests."""
+
+ test_tmpdir = tempfile.mkdtemp()
+ shard_status_file = os.path.join(test_tmpdir, 'shard_status_file2')
+ self.assert_(not os.path.exists(shard_status_file))
+
+ extra_env = {SHARD_STATUS_FILE_ENV_VAR: shard_status_file}
+ stdout_file = InvokeWithModifiedEnv(extra_env, os.popen,
+ '%s --gtest_list_tests' % COMMAND, 'r')
+ try:
+ stdout_file.readlines()
+ finally:
+ stdout_file.close()
+ self.assert_(os.path.exists(shard_status_file))
+ os.remove(shard_status_file)
+ os.removedirs(test_tmpdir)
+
+ def testShardingWorksWithDeathTests(self):
+ """Tests integration with death tests and sharding."""
+ gtest_filter = 'HasDeathTest.*:SeqP/*'
+ expected_tests = [
+ 'HasDeathTest.Test1',
+ 'HasDeathTest.Test2',
+
+ 'SeqP/ParamTest.TestX/0',
+ 'SeqP/ParamTest.TestX/1',
+ 'SeqP/ParamTest.TestY/0',
+ 'SeqP/ParamTest.TestY/1',
+ ]
+
+ for command in (COMMAND + ' --gtest_death_test_style=threadsafe',
+ COMMAND + ' --gtest_death_test_style=fast'):
+ self.RunAndVerifyWithSharding(gtest_filter, 3, expected_tests,
+ check_exit_0=True, command=command)
+ self.RunAndVerifyWithSharding(gtest_filter, 5, expected_tests,
+ check_exit_0=True, command=command)
if __name__ == '__main__':
gtest_test_utils.Main()