media/webrtc/trunk/testing/gtest/test/gtest_shuffle_test.py

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/media/webrtc/trunk/testing/gtest/test/gtest_shuffle_test.py	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,326 @@
     1.4 +#!/usr/bin/env python
     1.5 +#
     1.6 +# Copyright 2009 Google Inc. All Rights Reserved.
     1.7 +#
     1.8 +# Redistribution and use in source and binary forms, with or without
     1.9 +# modification, are permitted provided that the following conditions are
    1.10 +# met:
    1.11 +#
    1.12 +#     * Redistributions of source code must retain the above copyright
    1.13 +# notice, this list of conditions and the following disclaimer.
    1.14 +#     * Redistributions in binary form must reproduce the above
    1.15 +# copyright notice, this list of conditions and the following disclaimer
    1.16 +# in the documentation and/or other materials provided with the
    1.17 +# distribution.
    1.18 +#     * Neither the name of Google Inc. nor the names of its
    1.19 +# contributors may be used to endorse or promote products derived from
    1.20 +# this software without specific prior written permission.
    1.21 +#
    1.22 +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
    1.23 +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
    1.24 +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
    1.25 +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
    1.26 +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
    1.27 +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
    1.28 +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
    1.29 +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
    1.30 +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
    1.31 +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
    1.32 +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    1.33 +
    1.34 +"""Verifies that test shuffling works."""
    1.35 +
    1.36 +__author__ = 'wan@google.com (Zhanyong Wan)'
    1.37 +
    1.38 +import os
    1.39 +import gtest_test_utils
    1.40 +
    1.41 +# Command to run the gtest_shuffle_test_ program.
    1.42 +COMMAND = gtest_test_utils.GetTestExecutablePath('gtest_shuffle_test_')
    1.43 +
    1.44 +# The environment variables for test sharding.
    1.45 +TOTAL_SHARDS_ENV_VAR = 'GTEST_TOTAL_SHARDS'
    1.46 +SHARD_INDEX_ENV_VAR = 'GTEST_SHARD_INDEX'
    1.47 +
    1.48 +TEST_FILTER = 'A*.A:A*.B:C*'
    1.49 +
    1.50 +ALL_TESTS = []
    1.51 +ACTIVE_TESTS = []
    1.52 +FILTERED_TESTS = []
    1.53 +SHARDED_TESTS = []
    1.54 +
    1.55 +SHUFFLED_ALL_TESTS = []
    1.56 +SHUFFLED_ACTIVE_TESTS = []
    1.57 +SHUFFLED_FILTERED_TESTS = []
    1.58 +SHUFFLED_SHARDED_TESTS = []
    1.59 +
    1.60 +
    1.61 +def AlsoRunDisabledTestsFlag():
    1.62 +  return '--gtest_also_run_disabled_tests'
    1.63 +
    1.64 +
    1.65 +def FilterFlag(test_filter):
    1.66 +  return '--gtest_filter=%s' % (test_filter,)
    1.67 +
    1.68 +
    1.69 +def RepeatFlag(n):
    1.70 +  return '--gtest_repeat=%s' % (n,)
    1.71 +
    1.72 +
    1.73 +def ShuffleFlag():
    1.74 +  return '--gtest_shuffle'
    1.75 +
    1.76 +
    1.77 +def RandomSeedFlag(n):
    1.78 +  return '--gtest_random_seed=%s' % (n,)
    1.79 +
    1.80 +
    1.81 +def RunAndReturnOutput(extra_env, args):
    1.82 +  """Runs the test program and returns its output."""
    1.83 +
    1.84 +  environ_copy = os.environ.copy()
    1.85 +  environ_copy.update(extra_env)
    1.86 +
    1.87 +  return gtest_test_utils.Subprocess([COMMAND] + args, env=environ_copy,
    1.88 +                                     capture_stderr=False).output
    1.89 +
    1.90 +
    1.91 +def GetTestsForAllIterations(extra_env, args):
    1.92 +  """Runs the test program and returns a list of test lists.
    1.93 +
    1.94 +  Args:
    1.95 +    extra_env: a map from environment variables to their values
    1.96 +    args: command line flags to pass to gtest_shuffle_test_
    1.97 +
    1.98 +  Returns:
    1.99 +    A list where the i-th element is the list of tests run in the i-th
   1.100 +    test iteration.
   1.101 +  """
   1.102 +
   1.103 +  test_iterations = []
   1.104 +  for line in RunAndReturnOutput(extra_env, args).split('\n'):
   1.105 +    if line.startswith('----'):
   1.106 +      tests = []
   1.107 +      test_iterations.append(tests)
   1.108 +    elif line.strip():
   1.109 +      tests.append(line.strip())  # 'TestCaseName.TestName'
   1.110 +
   1.111 +  return test_iterations
   1.112 +
   1.113 +
   1.114 +def GetTestCases(tests):
   1.115 +  """Returns a list of test cases in the given full test names.
   1.116 +
   1.117 +  Args:
   1.118 +    tests: a list of full test names
   1.119 +
   1.120 +  Returns:
   1.121 +    A list of test cases from 'tests', in their original order.
   1.122 +    Consecutive duplicates are removed.
   1.123 +  """
   1.124 +
   1.125 +  test_cases = []
   1.126 +  for test in tests:
   1.127 +    test_case = test.split('.')[0]
   1.128 +    if not test_case in test_cases:
   1.129 +      test_cases.append(test_case)
   1.130 +
   1.131 +  return test_cases
   1.132 +
   1.133 +
   1.134 +def CalculateTestLists():
   1.135 +  """Calculates the list of tests run under different flags."""
   1.136 +
   1.137 +  if not ALL_TESTS:
   1.138 +    ALL_TESTS.extend(
   1.139 +        GetTestsForAllIterations({}, [AlsoRunDisabledTestsFlag()])[0])
   1.140 +
   1.141 +  if not ACTIVE_TESTS:
   1.142 +    ACTIVE_TESTS.extend(GetTestsForAllIterations({}, [])[0])
   1.143 +
   1.144 +  if not FILTERED_TESTS:
   1.145 +    FILTERED_TESTS.extend(
   1.146 +        GetTestsForAllIterations({}, [FilterFlag(TEST_FILTER)])[0])
   1.147 +
   1.148 +  if not SHARDED_TESTS:
   1.149 +    SHARDED_TESTS.extend(
   1.150 +        GetTestsForAllIterations({TOTAL_SHARDS_ENV_VAR: '3',
   1.151 +                                  SHARD_INDEX_ENV_VAR: '1'},
   1.152 +                                 [])[0])
   1.153 +
   1.154 +  if not SHUFFLED_ALL_TESTS:
   1.155 +    SHUFFLED_ALL_TESTS.extend(GetTestsForAllIterations(
   1.156 +        {}, [AlsoRunDisabledTestsFlag(), ShuffleFlag(), RandomSeedFlag(1)])[0])
   1.157 +
   1.158 +  if not SHUFFLED_ACTIVE_TESTS:
   1.159 +    SHUFFLED_ACTIVE_TESTS.extend(GetTestsForAllIterations(
   1.160 +        {}, [ShuffleFlag(), RandomSeedFlag(1)])[0])
   1.161 +
   1.162 +  if not SHUFFLED_FILTERED_TESTS:
   1.163 +    SHUFFLED_FILTERED_TESTS.extend(GetTestsForAllIterations(
   1.164 +        {}, [ShuffleFlag(), RandomSeedFlag(1), FilterFlag(TEST_FILTER)])[0])
   1.165 +
   1.166 +  if not SHUFFLED_SHARDED_TESTS:
   1.167 +    SHUFFLED_SHARDED_TESTS.extend(
   1.168 +        GetTestsForAllIterations({TOTAL_SHARDS_ENV_VAR: '3',
   1.169 +                                  SHARD_INDEX_ENV_VAR: '1'},
   1.170 +                                 [ShuffleFlag(), RandomSeedFlag(1)])[0])
   1.171 +
   1.172 +
   1.173 +class GTestShuffleUnitTest(gtest_test_utils.TestCase):
   1.174 +  """Tests test shuffling."""
   1.175 +
   1.176 +  def setUp(self):
   1.177 +    CalculateTestLists()
   1.178 +
   1.179 +  def testShufflePreservesNumberOfTests(self):
   1.180 +    self.assertEqual(len(ALL_TESTS), len(SHUFFLED_ALL_TESTS))
   1.181 +    self.assertEqual(len(ACTIVE_TESTS), len(SHUFFLED_ACTIVE_TESTS))
   1.182 +    self.assertEqual(len(FILTERED_TESTS), len(SHUFFLED_FILTERED_TESTS))
   1.183 +    self.assertEqual(len(SHARDED_TESTS), len(SHUFFLED_SHARDED_TESTS))
   1.184 +
   1.185 +  def testShuffleChangesTestOrder(self):
   1.186 +    self.assert_(SHUFFLED_ALL_TESTS != ALL_TESTS, SHUFFLED_ALL_TESTS)
   1.187 +    self.assert_(SHUFFLED_ACTIVE_TESTS != ACTIVE_TESTS, SHUFFLED_ACTIVE_TESTS)
   1.188 +    self.assert_(SHUFFLED_FILTERED_TESTS != FILTERED_TESTS,
   1.189 +                 SHUFFLED_FILTERED_TESTS)
   1.190 +    self.assert_(SHUFFLED_SHARDED_TESTS != SHARDED_TESTS,
   1.191 +                 SHUFFLED_SHARDED_TESTS)
   1.192 +
   1.193 +  def testShuffleChangesTestCaseOrder(self):
   1.194 +    self.assert_(GetTestCases(SHUFFLED_ALL_TESTS) != GetTestCases(ALL_TESTS),
   1.195 +                 GetTestCases(SHUFFLED_ALL_TESTS))
   1.196 +    self.assert_(
   1.197 +        GetTestCases(SHUFFLED_ACTIVE_TESTS) != GetTestCases(ACTIVE_TESTS),
   1.198 +        GetTestCases(SHUFFLED_ACTIVE_TESTS))
   1.199 +    self.assert_(
   1.200 +        GetTestCases(SHUFFLED_FILTERED_TESTS) != GetTestCases(FILTERED_TESTS),
   1.201 +        GetTestCases(SHUFFLED_FILTERED_TESTS))
   1.202 +    self.assert_(
   1.203 +        GetTestCases(SHUFFLED_SHARDED_TESTS) != GetTestCases(SHARDED_TESTS),
   1.204 +        GetTestCases(SHUFFLED_SHARDED_TESTS))
   1.205 +
   1.206 +  def testShuffleDoesNotRepeatTest(self):
   1.207 +    for test in SHUFFLED_ALL_TESTS:
   1.208 +      self.assertEqual(1, SHUFFLED_ALL_TESTS.count(test),
   1.209 +                       '%s appears more than once' % (test,))
   1.210 +    for test in SHUFFLED_ACTIVE_TESTS:
   1.211 +      self.assertEqual(1, SHUFFLED_ACTIVE_TESTS.count(test),
   1.212 +                       '%s appears more than once' % (test,))
   1.213 +    for test in SHUFFLED_FILTERED_TESTS:
   1.214 +      self.assertEqual(1, SHUFFLED_FILTERED_TESTS.count(test),
   1.215 +                       '%s appears more than once' % (test,))
   1.216 +    for test in SHUFFLED_SHARDED_TESTS:
   1.217 +      self.assertEqual(1, SHUFFLED_SHARDED_TESTS.count(test),
   1.218 +                       '%s appears more than once' % (test,))
   1.219 +
   1.220 +  def testShuffleDoesNotCreateNewTest(self):
   1.221 +    for test in SHUFFLED_ALL_TESTS:
   1.222 +      self.assert_(test in ALL_TESTS, '%s is an invalid test' % (test,))
   1.223 +    for test in SHUFFLED_ACTIVE_TESTS:
   1.224 +      self.assert_(test in ACTIVE_TESTS, '%s is an invalid test' % (test,))
   1.225 +    for test in SHUFFLED_FILTERED_TESTS:
   1.226 +      self.assert_(test in FILTERED_TESTS, '%s is an invalid test' % (test,))
   1.227 +    for test in SHUFFLED_SHARDED_TESTS:
   1.228 +      self.assert_(test in SHARDED_TESTS, '%s is an invalid test' % (test,))
   1.229 +
   1.230 +  def testShuffleIncludesAllTests(self):
   1.231 +    for test in ALL_TESTS:
   1.232 +      self.assert_(test in SHUFFLED_ALL_TESTS, '%s is missing' % (test,))
   1.233 +    for test in ACTIVE_TESTS:
   1.234 +      self.assert_(test in SHUFFLED_ACTIVE_TESTS, '%s is missing' % (test,))
   1.235 +    for test in FILTERED_TESTS:
   1.236 +      self.assert_(test in SHUFFLED_FILTERED_TESTS, '%s is missing' % (test,))
   1.237 +    for test in SHARDED_TESTS:
   1.238 +      self.assert_(test in SHUFFLED_SHARDED_TESTS, '%s is missing' % (test,))
   1.239 +
   1.240 +  def testShuffleLeavesDeathTestsAtFront(self):
   1.241 +    non_death_test_found = False
   1.242 +    for test in SHUFFLED_ACTIVE_TESTS:
   1.243 +      if 'DeathTest.' in test:
   1.244 +        self.assert_(not non_death_test_found,
   1.245 +                     '%s appears after a non-death test' % (test,))
   1.246 +      else:
   1.247 +        non_death_test_found = True
   1.248 +
   1.249 +  def _VerifyTestCasesDoNotInterleave(self, tests):
   1.250 +    test_cases = []
   1.251 +    for test in tests:
   1.252 +      [test_case, _] = test.split('.')
   1.253 +      if test_cases and test_cases[-1] != test_case:
   1.254 +        test_cases.append(test_case)
   1.255 +        self.assertEqual(1, test_cases.count(test_case),
   1.256 +                         'Test case %s is not grouped together in %s' %
   1.257 +                         (test_case, tests))
   1.258 +
   1.259 +  def testShuffleDoesNotInterleaveTestCases(self):
   1.260 +    self._VerifyTestCasesDoNotInterleave(SHUFFLED_ALL_TESTS)
   1.261 +    self._VerifyTestCasesDoNotInterleave(SHUFFLED_ACTIVE_TESTS)
   1.262 +    self._VerifyTestCasesDoNotInterleave(SHUFFLED_FILTERED_TESTS)
   1.263 +    self._VerifyTestCasesDoNotInterleave(SHUFFLED_SHARDED_TESTS)
   1.264 +
   1.265 +  def testShuffleRestoresOrderAfterEachIteration(self):
   1.266 +    # Get the test lists in all 3 iterations, using random seed 1, 2,
   1.267 +    # and 3 respectively.  Google Test picks a different seed in each
   1.268 +    # iteration, and this test depends on the current implementation
   1.269 +    # picking successive numbers.  This dependency is not ideal, but
   1.270 +    # makes the test much easier to write.
   1.271 +    [tests_in_iteration1, tests_in_iteration2, tests_in_iteration3] = (
   1.272 +        GetTestsForAllIterations(
   1.273 +            {}, [ShuffleFlag(), RandomSeedFlag(1), RepeatFlag(3)]))
   1.274 +
   1.275 +    # Make sure running the tests with random seed 1 gets the same
   1.276 +    # order as in iteration 1 above.
   1.277 +    [tests_with_seed1] = GetTestsForAllIterations(
   1.278 +        {}, [ShuffleFlag(), RandomSeedFlag(1)])
   1.279 +    self.assertEqual(tests_in_iteration1, tests_with_seed1)
   1.280 +
   1.281 +    # Make sure running the tests with random seed 2 gets the same
   1.282 +    # order as in iteration 2 above.  Success means that Google Test
   1.283 +    # correctly restores the test order before re-shuffling at the
   1.284 +    # beginning of iteration 2.
   1.285 +    [tests_with_seed2] = GetTestsForAllIterations(
   1.286 +        {}, [ShuffleFlag(), RandomSeedFlag(2)])
   1.287 +    self.assertEqual(tests_in_iteration2, tests_with_seed2)
   1.288 +
   1.289 +    # Make sure running the tests with random seed 3 gets the same
   1.290 +    # order as in iteration 3 above.  Success means that Google Test
   1.291 +    # correctly restores the test order before re-shuffling at the
   1.292 +    # beginning of iteration 3.
   1.293 +    [tests_with_seed3] = GetTestsForAllIterations(
   1.294 +        {}, [ShuffleFlag(), RandomSeedFlag(3)])
   1.295 +    self.assertEqual(tests_in_iteration3, tests_with_seed3)
   1.296 +
   1.297 +  def testShuffleGeneratesNewOrderInEachIteration(self):
   1.298 +    [tests_in_iteration1, tests_in_iteration2, tests_in_iteration3] = (
   1.299 +        GetTestsForAllIterations(
   1.300 +            {}, [ShuffleFlag(), RandomSeedFlag(1), RepeatFlag(3)]))
   1.301 +
   1.302 +    self.assert_(tests_in_iteration1 != tests_in_iteration2,
   1.303 +                 tests_in_iteration1)
   1.304 +    self.assert_(tests_in_iteration1 != tests_in_iteration3,
   1.305 +                 tests_in_iteration1)
   1.306 +    self.assert_(tests_in_iteration2 != tests_in_iteration3,
   1.307 +                 tests_in_iteration2)
   1.308 +
   1.309 +  def testShuffleShardedTestsPreservesPartition(self):
   1.310 +    # If we run M tests on N shards, the same M tests should be run in
   1.311 +    # total, regardless of the random seeds used by the shards.
   1.312 +    [tests1] = GetTestsForAllIterations({TOTAL_SHARDS_ENV_VAR: '3',
   1.313 +                                         SHARD_INDEX_ENV_VAR: '0'},
   1.314 +                                        [ShuffleFlag(), RandomSeedFlag(1)])
   1.315 +    [tests2] = GetTestsForAllIterations({TOTAL_SHARDS_ENV_VAR: '3',
   1.316 +                                         SHARD_INDEX_ENV_VAR: '1'},
   1.317 +                                        [ShuffleFlag(), RandomSeedFlag(20)])
   1.318 +    [tests3] = GetTestsForAllIterations({TOTAL_SHARDS_ENV_VAR: '3',
   1.319 +                                         SHARD_INDEX_ENV_VAR: '2'},
   1.320 +                                        [ShuffleFlag(), RandomSeedFlag(25)])
   1.321 +    sorted_sharded_tests = tests1 + tests2 + tests3
   1.322 +    sorted_sharded_tests.sort()
   1.323 +    sorted_active_tests = []
   1.324 +    sorted_active_tests.extend(ACTIVE_TESTS)
   1.325 +    sorted_active_tests.sort()
   1.326 +    self.assertEqual(sorted_active_tests, sorted_sharded_tests)
   1.327 +
   1.328 +if __name__ == '__main__':
   1.329 +  gtest_test_utils.Main()

mercurial