testRandomOrder.py 2.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677
  1. #!/usr/bin/env python3
  2. # Copyright Catch2 Authors
  3. # Distributed under the Boost Software License, Version 1.0.
  4. # (See accompanying file LICENSE_1_0.txt or copy at
  5. # https://www.boost.org/LICENSE_1_0.txt)
  6. # SPDX-License-Identifier: BSL-1.0
  7. """
  8. This test script verifies that the random ordering of tests inside
  9. Catch2 is invariant in regards to subsetting. This is done by running
  10. the binary 3 times, once with all tests selected, and twice with smaller
  11. subsets of tests selected, and verifying that the selected tests are in
  12. the same relative order.
  13. """
  14. import subprocess
  15. import sys
  16. import random
  17. import xml.etree.ElementTree as ET
  18. def none_to_empty_str(e):
  19. if e is None:
  20. return ""
  21. assert type(e) is str
  22. return e
  23. def list_tests(self_test_exe, tags, rng_seed):
  24. cmd = [self_test_exe, '--reporter', 'xml', '--list-tests', '--order', 'rand',
  25. '--rng-seed', str(rng_seed)]
  26. tags_arg = ','.join('[{}]~[.]'.format(t) for t in tags)
  27. if tags_arg:
  28. cmd.append(tags_arg)
  29. process = subprocess.Popen(
  30. cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
  31. stdout, stderr = process.communicate()
  32. if stderr:
  33. raise RuntimeError("Unexpected error output:\n" + process.stderr)
  34. root = ET.fromstring(stdout)
  35. result = [(none_to_empty_str(tc.find('Name').text),
  36. none_to_empty_str(tc.find('Tags').text),
  37. none_to_empty_str(tc.find('ClassName').text)) for tc in root.findall('./TestCase')]
  38. if len(result) < 2:
  39. raise RuntimeError("Unexpectedly few tests listed (got {})".format(
  40. len(result)))
  41. return result
  42. def check_is_sublist_of(shorter, longer):
  43. assert len(shorter) < len(longer)
  44. assert len(set(longer)) == len(longer)
  45. indexes_in_longer = {s: i for i, s in enumerate(longer)}
  46. for s1, s2 in zip(shorter, shorter[1:]):
  47. assert indexes_in_longer[s1] < indexes_in_longer[s2], (
  48. '{} comes before {} in longer list.\n'
  49. 'Longer: {}\nShorter: {}'.format(s2, s1, longer, shorter))
  50. def main():
  51. self_test_exe, = sys.argv[1:]
  52. # We want a random seed for the test, but want to avoid 0,
  53. # because it has special meaning
  54. seed = random.randint(1, 2 ** 32 - 1)
  55. list_one_tag = list_tests(self_test_exe, ['generators'], seed)
  56. list_two_tags = list_tests(self_test_exe, ['generators', 'matchers'], seed)
  57. list_all = list_tests(self_test_exe, [], seed)
  58. # First, verify that restricting to a subset yields the same order
  59. check_is_sublist_of(list_two_tags, list_all)
  60. check_is_sublist_of(list_one_tag, list_two_tags)
  61. if __name__ == '__main__':
  62. sys.exit(main())