check_test_inclusion.py 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  1. #!/usr/bin/env python
  2. # Copyright 2018 Google
  3. #
  4. # Licensed under the Apache License, Version 2.0 (the "License");
  5. # you may not use this file except in compliance with the License.
  6. # You may obtain a copy of the License at
  7. #
  8. # http://www.apache.org/licenses/LICENSE-2.0
  9. #
  10. # Unless required by applicable law or agreed to in writing, software
  11. # distributed under the License is distributed on an "AS IS" BASIS,
  12. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. # See the License for the specific language governing permissions and
  14. # limitations under the License.
  15. """Verifies that all tests are a part of the project file.
  16. """
  17. from __future__ import print_function
  18. import os
  19. import os.path
  20. import re
  21. import sys
  22. # Tests that are known not to compile in Xcode and can't be added there.
  23. EXCLUDED = frozenset([
  24. ])
  25. def Main():
  26. """Runs the style check."""
  27. tests = FindTestFiles("Firestore/Example/Tests", "Firestore/core/test")
  28. problems = CheckProject(
  29. "Firestore/Example/Firestore.xcodeproj/project.pbxproj", tests)
  30. if problems:
  31. Error("Test files exist that are unreferenced in Xcode project files:")
  32. for problem in problems:
  33. Error(problem)
  34. sys.exit(1)
  35. sys.exit(0)
  36. def FindTestFiles(*test_dirs):
  37. """Searches the given source roots for test files.
  38. Args:
  39. *test_dirs: A list of directories containing test sources.
  40. Returns:
  41. A list of test source filenames.
  42. """
  43. test_file_pattern = re.compile(r"(?:Tests?\.mm?|_test\.(?:cc|mm))$")
  44. result = []
  45. for test_dir in test_dirs:
  46. for root, dirs, files in os.walk(test_dir):
  47. del dirs # unused
  48. for basename in files:
  49. filename = os.path.join(root, basename)
  50. if filename not in EXCLUDED and test_file_pattern.search(basename):
  51. result.append(filename)
  52. return result
  53. def CheckProject(project_file, test_files):
  54. """Checks the given project file for tests in the given test_dirs.
  55. Args:
  56. project_file: The path to an Xcode pbxproj file.
  57. test_files: A list of all tests source files in the project.
  58. Returns:
  59. A sorted list of filenames that aren't referenced in the project_file.
  60. """
  61. # An dict of basename to filename
  62. basenames = {os.path.basename(f): f for f in test_files}
  63. file_list_pattern = re.compile(r"/\* (\S+) in Sources \*/")
  64. with open(project_file, "r") as fd:
  65. for line in fd:
  66. line = line.rstrip()
  67. m = file_list_pattern.search(line)
  68. if m:
  69. basename = m.group(1)
  70. if basename in basenames:
  71. del basenames[basename]
  72. return sorted(basenames.values())
  73. def Error(message, *args):
  74. message %= args
  75. print(message, file=sys.stderr)
  76. if __name__ == "__main__":
  77. Main()