diff options
Diffstat (limited to 'test')
| -rwxr-xr-x | test/gtest_filter_unittest.py | 162 | ||||
| -rw-r--r-- | test/gtest_filter_unittest_.cc | 19 | ||||
| -rwxr-xr-x | test/gtest_output_test.py | 68 | ||||
| -rw-r--r-- | test/gtest_output_test_.cc | 6 | ||||
| -rw-r--r-- | test/gtest_output_test_golden_lin.txt | 24 | ||||
| -rw-r--r-- | test/gtest_output_test_golden_win.txt | 24 | ||||
| -rw-r--r-- | test/gtest_unittest.cc | 158 | 
7 files changed, 420 insertions, 41 deletions
| diff --git a/test/gtest_filter_unittest.py b/test/gtest_filter_unittest.py index 35307a26..c3a016cf 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() diff --git a/test/gtest_filter_unittest_.cc b/test/gtest_filter_unittest_.cc index 99610796..22638e0d 100644 --- a/test/gtest_filter_unittest_.cc +++ b/test/gtest_filter_unittest_.cc @@ -91,6 +91,25 @@ TEST(BazTest, DISABLED_TestC) {    FAIL() << "Expected failure.";  } +// Test case HasDeathTest + +TEST(HasDeathTest, Test1) { +#ifdef GTEST_HAS_DEATH_TEST +  EXPECT_DEATH({exit(1);}, +    ".*"); +#endif  // GTEST_HAS_DEATH_TEST +} + +// We need at least two death tests to make sure that the all death tests +// aren't on the first shard. +TEST(HasDeathTest, Test2) { +#ifdef GTEST_HAS_DEATH_TEST +  EXPECT_DEATH({exit(1);}, +    ".*"); +#endif  // GTEST_HAS_DEATH_TEST +} + +  // Test case FoobarTest  TEST(DISABLED_FoobarTest, Test1) { diff --git a/test/gtest_output_test.py b/test/gtest_output_test.py index 9aaade2e..f35e0024 100755 --- a/test/gtest_output_test.py +++ b/test/gtest_output_test.py @@ -64,13 +64,17 @@ PROGRAM_PATH = os.path.join(gtest_test_utils.GetBuildDir(), PROGRAM)  # At least one command we exercise must not have the  # --gtest_internal_skip_environment_and_ad_hoc_tests flag. -COMMAND_WITH_COLOR = PROGRAM_PATH + ' --gtest_color=yes' -COMMAND_WITH_TIME = (PROGRAM_PATH + ' --gtest_print_time ' +COMMAND_WITH_COLOR = ({}, PROGRAM_PATH + ' --gtest_color=yes') +COMMAND_WITH_TIME = ({}, PROGRAM_PATH + ' --gtest_print_time '                       '--gtest_internal_skip_environment_and_ad_hoc_tests '                       '--gtest_filter="FatalFailureTest.*:LoggingTest.*"') -COMMAND_WITH_DISABLED = (PROGRAM_PATH + ' --gtest_also_run_disabled_tests ' +COMMAND_WITH_DISABLED = ({}, PROGRAM_PATH + ' --gtest_also_run_disabled_tests '                           '--gtest_internal_skip_environment_and_ad_hoc_tests '                           '--gtest_filter="*DISABLED_*"') +COMMAND_WITH_SHARDING = ({'GTEST_SHARD_INDEX': '1', 'GTEST_TOTAL_SHARDS': '2'}, +                         PROGRAM_PATH + +                         ' --gtest_internal_skip_environment_and_ad_hoc_tests ' +                         ' --gtest_filter="PassingTest.*"')  GOLDEN_PATH = os.path.join(gtest_test_utils.GetSourceDir(),                             GOLDEN_NAME) @@ -136,19 +140,26 @@ def NormalizeOutput(output):    return output -def IterShellCommandOutput(cmd, stdin_string=None): +def IterShellCommandOutput(env_cmd, stdin_string=None):    """Runs a command in a sub-process, and iterates the lines in its STDOUT.    Args: -    cmd:           The shell command. -    stdin_string:  The string to be fed to the STDIN of the sub-process; -                   If None, the sub-process will inherit the STDIN -                   from the parent process. +    env_cmd:           The shell command. A 2-tuple where element 0 is a dict +                       of extra environment variables to set, and element 1 +                       is a string with the command and any flags. +    stdin_string:      The string to be fed to the STDIN of the sub-process; +                       If None, the sub-process will inherit the STDIN +                       from the parent process.    """    # Spawns cmd in a sub-process, and gets its standard I/O file objects. -  stdin_file, stdout_file = os.popen2(cmd, 'b') +  # Set and save the environment properly. +  old_env_vars = dict(os.environ) +  os.environ.update(env_cmd[0]) +  stdin_file, stdout_file = os.popen2(env_cmd[1], 'b') +  os.environ.clear() +  os.environ.update(old_env_vars)    # If the caller didn't specify a string for STDIN, gets it from the    # parent process. @@ -168,39 +179,50 @@ def IterShellCommandOutput(cmd, stdin_string=None):      yield line -def GetShellCommandOutput(cmd, stdin_string=None): +def GetShellCommandOutput(env_cmd, stdin_string=None):    """Runs a command in a sub-process, and returns its STDOUT in a string.    Args: -    cmd:           The shell command. -    stdin_string:  The string to be fed to the STDIN of the sub-process; -                   If None, the sub-process will inherit the STDIN -                   from the parent process. +    env_cmd:           The shell command. A 2-tuple where element 0 is a dict +                       of extra environment variables to set, and element 1 +                       is a string with the command and any flags. +    stdin_string:      The string to be fed to the STDIN of the sub-process; +                       If None, the sub-process will inherit the STDIN +                       from the parent process.    """ -  lines = list(IterShellCommandOutput(cmd, stdin_string)) +  lines = list(IterShellCommandOutput(env_cmd, stdin_string))    return string.join(lines, '') -def GetCommandOutput(cmd): +def GetCommandOutput(env_cmd):    """Runs a command and returns its output with all file location    info stripped off.    Args: -    cmd:  the shell command. +    env_cmd:  The shell command. A 2-tuple where element 0 is a dict of extra +              environment variables to set, and element 1 is a string with +              the command and any flags.    """    # Disables exception pop-ups on Windows.    os.environ['GTEST_CATCH_EXCEPTIONS'] = '1' -  return NormalizeOutput(GetShellCommandOutput(cmd, '')) +  return NormalizeOutput(GetShellCommandOutput(env_cmd, '')) + + +def GetOutputOfAllCommands(): +  """Returns concatenated output from several representative commands.""" + +  return (GetCommandOutput(COMMAND_WITH_COLOR) + +          GetCommandOutput(COMMAND_WITH_TIME) + +          GetCommandOutput(COMMAND_WITH_DISABLED) + +          GetCommandOutput(COMMAND_WITH_SHARDING))  class GTestOutputTest(unittest.TestCase):    def testOutput(self): -    output = (GetCommandOutput(COMMAND_WITH_COLOR) + -              GetCommandOutput(COMMAND_WITH_TIME) + -              GetCommandOutput(COMMAND_WITH_DISABLED)) +    output = GetOutputOfAllCommands()      golden_file = open(GOLDEN_PATH, 'rb')      golden = golden_file.read()      golden_file.close() @@ -214,9 +236,7 @@ class GTestOutputTest(unittest.TestCase):  if __name__ == '__main__':    if sys.argv[1:] == [GENGOLDEN_FLAG]: -    output = (GetCommandOutput(COMMAND_WITH_COLOR) + -              GetCommandOutput(COMMAND_WITH_TIME) + -              GetCommandOutput(COMMAND_WITH_DISABLED)) +    output = GetOutputOfAllCommands()      golden_file = open(GOLDEN_PATH, 'wb')      golden_file.write(output)      golden_file.close() diff --git a/test/gtest_output_test_.cc b/test/gtest_output_test_.cc index 5c76609f..f5748d17 100644 --- a/test/gtest_output_test_.cc +++ b/test/gtest_output_test_.cc @@ -85,6 +85,12 @@ void TryTestSubroutine() {    FAIL() << "This should never be reached.";  } +TEST(PassingTest, PassingTest1) { +} + +TEST(PassingTest, PassingTest2) { +} +  // Tests catching a fatal failure in a subroutine.  TEST(FatalFailureTest, FatalFailureInSubroutine) {    printf("(expecting a failure that x should be 1)\n"); diff --git a/test/gtest_output_test_golden_lin.txt b/test/gtest_output_test_golden_lin.txt index 74ed7371..46a90fb5 100644 --- a/test/gtest_output_test_golden_lin.txt +++ b/test/gtest_output_test_golden_lin.txt @@ -7,7 +7,7 @@ Expected: true  gtest_output_test_.cc:#: Failure  Value of: 3  Expected: 2 -[0;32m[==========] [mRunning 54 tests from 22 test cases. +[0;32m[==========] [mRunning 56 tests from 23 test cases.  [0;32m[----------] [mGlobal test environment set-up.  FooEnvironment::SetUp() called.  BarEnvironment::SetUp() called. @@ -26,6 +26,11 @@ BarEnvironment::SetUp() called.  [0;32m[----------] [m1 test from My/ATypeParamDeathTest/1, where TypeParam = double  [0;32m[ RUN      ] [mMy/ATypeParamDeathTest/1.ShouldRunFirst  [0;32m[       OK ] [mMy/ATypeParamDeathTest/1.ShouldRunFirst +[0;32m[----------] [m2 tests from PassingTest +[0;32m[ RUN      ] [mPassingTest.PassingTest1 +[0;32m[       OK ] [mPassingTest.PassingTest1 +[0;32m[ RUN      ] [mPassingTest.PassingTest2 +[0;32m[       OK ] [mPassingTest.PassingTest2  [0;32m[----------] [m3 tests from FatalFailureTest  [0;32m[ RUN      ] [mFatalFailureTest.FatalFailureInSubroutine  (expecting a failure that x should be 1) @@ -508,8 +513,8 @@ FooEnvironment::TearDown() called.  gtest_output_test_.cc:#: Failure  Failed  Expected fatal failure. -[0;32m[==========] [m54 tests from 22 test cases ran. -[0;32m[  PASSED  ] [m19 tests. +[0;32m[==========] [m56 tests from 23 test cases ran. +[0;32m[  PASSED  ] [m21 tests.  [0;31m[  FAILED  ] [m35 tests, listed below:  [0;31m[  FAILED  ] [mFatalFailureTest.FatalFailureInSubroutine  [0;31m[  FAILED  ] [mFatalFailureTest.FatalFailureInNestedSubroutine @@ -612,3 +617,16 @@ Note: Google Test filter = *DISABLED_*  [----------] Global test environment tear-down  [==========] 1 test from 1 test case ran.  [  PASSED  ] 1 test. +Note: Google Test filter = PassingTest.* +Note: This is test shard 1 of 2. +[==========] Running 1 test from 1 test case. +[----------] Global test environment set-up. +[----------] 1 test from PassingTest +[ RUN      ] PassingTest.PassingTest2 +[       OK ] PassingTest.PassingTest2 +[----------] Global test environment tear-down +[==========] 1 test from 1 test case ran. +[  PASSED  ] 1 test. + +  YOU HAVE 1 DISABLED TEST + diff --git a/test/gtest_output_test_golden_win.txt b/test/gtest_output_test_golden_win.txt index 17be5c04..77903ba1 100644 --- a/test/gtest_output_test_golden_win.txt +++ b/test/gtest_output_test_golden_win.txt @@ -5,10 +5,15 @@ gtest_output_test_.cc:#: error: Value of: false  Expected: true  gtest_output_test_.cc:#: error: Value of: 3  Expected: 2 -[==========] Running 50 tests from 20 test cases. +[==========] Running 52 tests from 21 test cases.  [----------] Global test environment set-up.  FooEnvironment::SetUp() called.  BarEnvironment::SetUp() called. +[----------] 2 tests from PassingTest +[ RUN      ] PassingTest.PassingTest1 +[       OK ] PassingTest.PassingTest1 +[ RUN      ] PassingTest.PassingTest2 +[       OK ] PassingTest.PassingTest2  [----------] 3 tests from FatalFailureTest  [ RUN      ] FatalFailureTest.FatalFailureInSubroutine  (expecting a failure that x should be 1) @@ -440,8 +445,8 @@ Expected non-fatal failure.  FooEnvironment::TearDown() called.  gtest_output_test_.cc:#: error: Failed  Expected fatal failure. -[==========] 50 tests from 20 test cases ran. -[  PASSED  ] 14 tests. +[==========] 52 tests from 21 test cases ran. +[  PASSED  ] 16 tests.  [  FAILED  ] 36 tests, listed below:  [  FAILED  ] FatalFailureTest.FatalFailureInSubroutine  [  FAILED  ] FatalFailureTest.FatalFailureInNestedSubroutine @@ -540,3 +545,16 @@ Note: Google Test filter = *DISABLED_*  [----------] Global test environment tear-down  [==========] 1 test from 1 test case ran.  [  PASSED  ] 1 test. +Note: Google Test filter = PassingTest.* +Note: This is test shard 1 of 2. +[==========] Running 1 test from 1 test case. +[----------] Global test environment set-up. +[----------] 1 test from PassingTest +[ RUN      ] PassingTest.PassingTest2 +[       OK ] PassingTest.PassingTest2 +[----------] Global test environment tear-down +[==========] 1 test from 1 test case ran. +[  PASSED  ] 1 test. + +  YOU HAVE 1 DISABLED TEST + diff --git a/test/gtest_unittest.cc b/test/gtest_unittest.cc index 4bac8a69..335b9e06 100644 --- a/test/gtest_unittest.cc +++ b/test/gtest_unittest.cc @@ -138,7 +138,10 @@ using testing::internal::GetTestTypeId;  using testing::internal::GetTypeId;  using testing::internal::GTestFlagSaver;  using testing::internal::Int32; +using testing::internal::Int32FromEnvOrDie;  using testing::internal::List; +using testing::internal::ShouldRunTestOnShard; +using testing::internal::ShouldShard;  using testing::internal::ShouldUseColor;  using testing::internal::StreamableToString;  using testing::internal::String; @@ -1375,6 +1378,161 @@ TEST(ParseInt32FlagTest, ParsesAndReturnsValidValue) {    EXPECT_EQ(-789, value);  } +// Tests that Int32FromEnvOrDie() parses the value of the var or +// returns the correct default. +TEST(Int32FromEnvOrDieTest, ParsesAndReturnsValidValue) { +  EXPECT_EQ(333, Int32FromEnvOrDie(GTEST_FLAG_PREFIX_UPPER "UnsetVar", 333)); +  SetEnv(GTEST_FLAG_PREFIX_UPPER "UnsetVar", "123"); +  EXPECT_EQ(123, Int32FromEnvOrDie(GTEST_FLAG_PREFIX_UPPER "UnsetVar", 333)); +  SetEnv(GTEST_FLAG_PREFIX_UPPER "UnsetVar", "-123"); +  EXPECT_EQ(-123, Int32FromEnvOrDie(GTEST_FLAG_PREFIX_UPPER "UnsetVar", 333)); +} + +#ifdef GTEST_HAS_DEATH_TEST + +// Tests that Int32FromEnvOrDie() aborts with an error message +// if the variable is not an Int32. +TEST(Int32FromEnvOrDieDeathTest, AbortsOnFailure) { +  SetEnv(GTEST_FLAG_PREFIX_UPPER "VAR", "xxx"); +  EXPECT_DEATH({Int32FromEnvOrDie(GTEST_FLAG_PREFIX_UPPER "VAR", 123);}, +               ".*"); +} + +// Tests that Int32FromEnvOrDie() aborts with an error message +// if the variable cannot be represnted by an Int32. +TEST(Int32FromEnvOrDieDeathTest, AbortsOnInt32Overflow) { +  SetEnv(GTEST_FLAG_PREFIX_UPPER "VAR", "1234567891234567891234"); +  EXPECT_DEATH({Int32FromEnvOrDie(GTEST_FLAG_PREFIX_UPPER "VAR", 123);}, +               ".*"); +} + +#endif  // GTEST_HAS_DEATH_TEST + + +// Tests that ShouldRunTestOnShard() selects all tests +// where there is 1 shard. +TEST(ShouldRunTestOnShardTest, IsPartitionWhenThereIsOneShard) { +  EXPECT_TRUE(ShouldRunTestOnShard(1, 0, 0)); +  EXPECT_TRUE(ShouldRunTestOnShard(1, 0, 1)); +  EXPECT_TRUE(ShouldRunTestOnShard(1, 0, 2)); +  EXPECT_TRUE(ShouldRunTestOnShard(1, 0, 3)); +  EXPECT_TRUE(ShouldRunTestOnShard(1, 0, 4)); +} + +class ShouldShardTest : public testing::Test { + protected: +  virtual void SetUp() { +    index_var_ = GTEST_FLAG_PREFIX_UPPER "INDEX"; +    total_var_ = GTEST_FLAG_PREFIX_UPPER "TOTAL"; +  } + +  virtual void TearDown() { +    SetEnv(index_var_, ""); +    SetEnv(total_var_, ""); +  } + +  const char* index_var_; +  const char* total_var_; +}; + +// Tests that sharding is disabled if neither of the environment variables +// are set. +TEST_F(ShouldShardTest, ReturnsFalseWhenNeitherEnvVarIsSet) { +  SetEnv(index_var_, ""); +  SetEnv(total_var_, ""); + +  EXPECT_FALSE(ShouldShard(total_var_, index_var_, false)); +  EXPECT_FALSE(ShouldShard(total_var_, index_var_, true)); +} + +// Tests that sharding is not enabled if total_shards  == 1. +TEST_F(ShouldShardTest, ReturnsFalseWhenTotalShardIsOne) { +  SetEnv(index_var_, "0"); +  SetEnv(total_var_, "1"); +  EXPECT_FALSE(ShouldShard(total_var_, index_var_, false)); +  EXPECT_FALSE(ShouldShard(total_var_, index_var_, true)); +} + +// Tests that sharding is enabled if total_shards > 1 and +// we are not in a death test subprocess. +TEST_F(ShouldShardTest, WorksWhenShardEnvVarsAreValid) { +  SetEnv(index_var_, "4"); +  SetEnv(total_var_, "22"); +  EXPECT_TRUE(ShouldShard(total_var_, index_var_, false)); +  EXPECT_FALSE(ShouldShard(total_var_, index_var_, true)); + +  SetEnv(index_var_, "8"); +  SetEnv(total_var_, "9"); +  EXPECT_TRUE(ShouldShard(total_var_, index_var_, false)); +  EXPECT_FALSE(ShouldShard(total_var_, index_var_, true)); + +  SetEnv(index_var_, "0"); +  SetEnv(total_var_, "9"); +  EXPECT_TRUE(ShouldShard(total_var_, index_var_, false)); +  EXPECT_FALSE(ShouldShard(total_var_, index_var_, true)); +} + +#ifdef GTEST_HAS_DEATH_TEST + +// Tests that we exit in error if the sharding values are not valid. +TEST_F(ShouldShardTest, AbortsWhenShardingEnvVarsAreInvalid) { +  SetEnv(index_var_, "4"); +  SetEnv(total_var_, "4"); +  EXPECT_DEATH({ShouldShard(total_var_, index_var_, false);}, +               ".*"); + +  SetEnv(index_var_, "4"); +  SetEnv(total_var_, "-2"); +  EXPECT_DEATH({ShouldShard(total_var_, index_var_, false);}, +               ".*"); + +  SetEnv(index_var_, "5"); +  SetEnv(total_var_, ""); +  EXPECT_DEATH({ShouldShard(total_var_, index_var_, false);}, +               ".*"); + +  SetEnv(index_var_, ""); +  SetEnv(total_var_, "5"); +  EXPECT_DEATH({ShouldShard(total_var_, index_var_, false);}, +               ".*"); +} + +#endif  // GTEST_HAS_DEATH_TEST + +// Tests that ShouldRunTestOnShard is a partition when 5 +// shards are used. +TEST(ShouldRunTestOnShardTest, IsPartitionWhenThereAreFiveShards) { +  // Choose an arbitrary number of tests and shards. +  const int num_tests = 17; +  const int num_shards = 5; + +  // Check partitioning: each test should be on exactly 1 shard. +  for (int test_id = 0; test_id < num_tests; test_id++) { +    int prev_selected_shard_index = -1; +    for (int shard_index = 0; shard_index < num_shards; shard_index++) { +      if (ShouldRunTestOnShard(num_shards, shard_index, test_id)) { +        if (prev_selected_shard_index < 0) { +          prev_selected_shard_index = shard_index; +        } else { +          ADD_FAILURE() << "Shard " << prev_selected_shard_index << " and " +            << shard_index << " are both selected to run test " << test_id; +        } +      } +    } +  } + +  // Check balance: This is not required by the sharding protocol, but is a +  // desirable property for performance. +  for (int shard_index = 0; shard_index < num_shards; shard_index++) { +    int num_tests_on_shard = 0; +    for (int test_id = 0; test_id < num_tests; test_id++) { +      num_tests_on_shard += +        ShouldRunTestOnShard(num_shards, shard_index, test_id); +    } +    EXPECT_GE(num_tests_on_shard, num_tests / num_shards); +  } +} +  // For the same reason we are not explicitly testing everything in the  // Test class, there are no separate tests for the following classes  // (except for some trivial cases): | 
