PageRenderTime 52ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 0ms

/tests/run_tests.py

http://github.com/bengardner/uncrustify
Python | 281 lines | 264 code | 3 blank | 14 comment | 9 complexity | 5a3be2d56fe2ca593bac820f9b6825fb MD5 | raw file
Possible License(s): GPL-2.0
  1. #!/usr/bin/env python
  2. #
  3. # Scans the .test files on the command line and parses each, running
  4. # the tests listed. Results are printed out.
  5. #
  6. # This could all be done with bash, but I wanted to use python. =)
  7. # Anyway, this was all done while waiting in the Denver airport.
  8. # * @author Guy Maurel since version 0.62 for uncrustify4Qt
  9. # * October 2015
  10. #
  11. import argparse
  12. import sys
  13. import os
  14. import string
  15. import filecmp
  16. # OK, so I just had way too much fun with the colors..
  17. # windows doesn't support ansi sequences (unless using ConEmu and enabled)
  18. disablecolors = os.name == "nt" and os.environ.get('CONEMUANSI', '') != 'ON'
  19. if disablecolors:
  20. NORMAL = ""
  21. BOLD = ""
  22. UNDERSCORE = ""
  23. REVERSE = ""
  24. else:
  25. NORMAL = "\033[0m"
  26. BOLD = "\033[1m"
  27. UNDERSCORE = "\033[1m"
  28. REVERSE = "\033[7m"
  29. FG_BLACK = "\033[30m"
  30. FG_RED = "\033[31m"
  31. FG_GREEN = "\033[32m"
  32. FG_YELLOW = "\033[33m"
  33. FG_BLUE = "\033[34m"
  34. FG_MAGNETA = "\033[35m"
  35. FG_CYAN = "\033[36m"
  36. FG_WHITE = "\033[37m"
  37. FGB_BLACK = "\033[90m"
  38. FGB_RED = "\033[91m"
  39. FGB_GREEN = "\033[92m"
  40. FGB_YELLOW = "\033[93m"
  41. FGB_BLUE = "\033[94m"
  42. FGB_MAGNETA = "\033[95m"
  43. FGB_CYAN = "\033[96m"
  44. FGB_WHITE = "\033[97m"
  45. BG_BLACK = "\033[40m"
  46. BG_RED = "\033[41m"
  47. BG_GREEN = "\033[42m"
  48. BG_YELLOW = "\033[43m"
  49. BG_BLUE = "\033[44m"
  50. BG_MAGNETA = "\033[45m"
  51. BG_CYAN = "\033[46m"
  52. BG_WHITE = "\033[47m"
  53. BGB_BLACK = "\033[100m"
  54. BGB_RED = "\033[101m"
  55. BGB_GREEN = "\033[102m"
  56. BGB_YELLOW = "\033[103m"
  57. BGB_BLUE = "\033[104m"
  58. BGB_MAGNETA = "\033[105m"
  59. BGB_CYAN = "\033[106m"
  60. BGB_WHITE = "\033[107m"
  61. # after all that, I chose c
  62. if disablecolors:
  63. FAIL_COLOR = ""
  64. PASS_COLOR = ""
  65. MISMATCH_COLOR = ""
  66. UNSTABLE_COLOR = ""
  67. SKIP_COLOR = ""
  68. else:
  69. FAIL_COLOR = UNDERSCORE
  70. PASS_COLOR = FG_GREEN
  71. MISMATCH_COLOR = FG_RED #REVERSE
  72. UNSTABLE_COLOR = FGB_CYAN
  73. SKIP_COLOR = FGB_YELLOW
  74. def run_tests(args, test_name, config_name, input_name, lang):
  75. # print("Test: ", test_name)
  76. # print("Config:", config_name)
  77. # print("Input: ", input_name)
  78. # print('Output:', expected_name)
  79. if not os.path.isabs(config_name):
  80. config_name = os.path.join('config', config_name)
  81. if test_name[-1] == '!':
  82. test_name = test_name[:-1]
  83. rerun_config = "%s.rerun%s" % os.path.splitext(config_name)
  84. else:
  85. rerun_config = config_name
  86. expected_name = os.path.join(os.path.dirname(input_name), test_name + '-' + os.path.basename(input_name))
  87. resultname = os.path.join(args.results, expected_name)
  88. outputname = os.path.join('output', expected_name)
  89. try:
  90. os.makedirs(os.path.dirname(resultname))
  91. except:
  92. pass
  93. cmd = '"%s" -q -c %s -f input/%s %s -o %s %s' % (args.exe, config_name, input_name, lang, resultname, "-LA 2>" + resultname + ".log -p " + resultname + ".unc" if args.g else "-L1,2")
  94. if args.c:
  95. print("RUN: " + cmd)
  96. a = os.system(cmd)
  97. if a != 0:
  98. print(FAIL_COLOR + "FAILED: " + NORMAL + test_name)
  99. return -1
  100. try:
  101. if not filecmp.cmp(resultname, outputname):
  102. print(MISMATCH_COLOR + "MISMATCH: " + NORMAL + test_name)
  103. if args.d:
  104. cmd = "git diff --no-index %s %s" % (outputname, resultname)
  105. sys.stdout.flush()
  106. os.system(cmd)
  107. return -1
  108. except:
  109. print(MISMATCH_COLOR + "MISSING: " + NORMAL + test_name)
  110. return -1
  111. # The file in results matches the file in output.
  112. # Re-run with the output file as the input to check stability.
  113. cmd = '"%s" -q -c %s -f %s %s -o %s' % (args.exe, rerun_config, outputname, lang, resultname)
  114. if args.c:
  115. print("RUN: " + cmd)
  116. a = os.system(cmd)
  117. if a != 0:
  118. print(FAIL_COLOR + "FAILED2: " + NORMAL + test_name)
  119. return -1
  120. try:
  121. if not filecmp.cmp(resultname, outputname):
  122. print(UNSTABLE_COLOR + "UNSTABLE: " + NORMAL + test_name)
  123. if args.d:
  124. cmd = "git diff --no-index %s %s" % (outputname, resultname)
  125. sys.stdout.flush()
  126. os.system(cmd)
  127. return -2
  128. except:
  129. # impossible
  130. print(UNSTABLE_COLOR + "MISSING: " + NORMAL + test_name)
  131. return -1
  132. if args.p:
  133. print(PASS_COLOR + "PASSED: " + NORMAL + test_name)
  134. return 0
  135. def process_test_file(args, filename):
  136. fd = open(filename, "r")
  137. if fd == None:
  138. print("Unable to open " + filename)
  139. return None
  140. print("Processing " + filename)
  141. pass_count = 0
  142. fail_count = 0
  143. unst_count = 0
  144. for line in fd:
  145. line = line.strip()
  146. parts = line.split()
  147. if (len(parts) < 3) or (parts[0][0] == '#'):
  148. continue
  149. if args.r != None:
  150. test_name = parts[0]
  151. # remove special suffixes (eg. '!')
  152. if not test_name[-1].isdigit():
  153. test_name = test_name[:-1]
  154. test_nb = int(test_name)
  155. # parse range list (eg. 10001-10010,10030-10050,10063)
  156. range_filter = args.r
  157. filtered = True
  158. for value in range_filter.split(","):
  159. t = value.split("-")
  160. a = b = int(t[0])
  161. if len(t) > 1:
  162. b = int(t[1])
  163. if test_nb >= a and test_nb <= b:
  164. filtered = False
  165. break
  166. if filtered:
  167. if args.p:
  168. print(SKIP_COLOR + "SKIPPED: " + NORMAL + parts[0])
  169. continue
  170. lang = ""
  171. if len(parts) > 3:
  172. lang = "-l " + parts[3]
  173. rt = run_tests(args, parts[0], parts[1], parts[2], lang)
  174. if rt < 0:
  175. if rt == -1:
  176. fail_count += 1
  177. else:
  178. unst_count += 1
  179. else:
  180. pass_count += 1
  181. return [pass_count, fail_count, unst_count]
  182. #
  183. # entry point
  184. #
  185. def main(argv):
  186. all_tests = "c-sharp c cpp d java pawn objective-c vala ecma".split()
  187. parser = argparse.ArgumentParser(description='Run uncrustify tests')
  188. parser.add_argument('-c', help='show commands', action='store_true')
  189. parser.add_argument('-d', help='show diff on failure', action='store_true')
  190. parser.add_argument('-p', help='show passed/skipped tests', action='store_true')
  191. parser.add_argument('-g', help='generate debug files (.log, .unc)', action='store_true')
  192. parser.add_argument('-r', help='specify test filter range list', type=str, default=None)
  193. parser.add_argument('--results', help='specify results folder', type=str, default='results')
  194. parser.add_argument('--exe', help='uncrustify executable to test',
  195. type=str)
  196. parser.add_argument('tests', metavar='TEST', help='test(s) to run (default all)',
  197. type=str, default=all_tests, nargs='*')
  198. args = parser.parse_args()
  199. # Save current working directory from which the script is called to be able to resolve relative --exe paths
  200. cwd = os.getcwd()
  201. os.chdir(os.path.dirname(os.path.realpath(__file__)))
  202. if not args.exe:
  203. if os.name == "nt":
  204. bin_path = '../win32/{0}/uncrustify.exe'
  205. if args.g:
  206. bin_path = bin_path.format('Debug')
  207. else:
  208. bin_path = bin_path.format('Release')
  209. else:
  210. bin_path = '../src/uncrustify'
  211. args.exe = os.path.abspath(bin_path)
  212. else:
  213. if not os.path.isabs(args.exe):
  214. args.exe = os.path.normpath(os.path.join(cwd, args.exe))
  215. if not os.path.exists(args.exe):
  216. print(FAIL_COLOR + "FAILED: " + NORMAL + "Cannot find uncrustify executable")
  217. return -1
  218. # do a sanity check on the executable
  219. cmd = '"%s" > %s' % (args.exe, "usage.txt")
  220. if args.c:
  221. print("RUN: " + cmd)
  222. a = os.system(cmd)
  223. if a != 0:
  224. print(FAIL_COLOR + "FAILED: " + NORMAL + "Sanity check")
  225. return -1
  226. #print args
  227. print("Tests: " + str(args.tests))
  228. pass_count = 0
  229. fail_count = 0
  230. unst_count = 0
  231. for item in args.tests:
  232. if not item.endswith('.test'):
  233. item += '.test'
  234. passfail = process_test_file(args, item)
  235. if passfail != None:
  236. pass_count += passfail[0]
  237. fail_count += passfail[1]
  238. unst_count += passfail[2]
  239. print("Passed %d / %d tests" % (pass_count, pass_count + fail_count))
  240. if fail_count > 0:
  241. print(BOLD + "Failed %d test(s)" % (fail_count) + NORMAL)
  242. sys.exit(1)
  243. else:
  244. txt = BOLD + "All tests passed" + NORMAL
  245. if unst_count > 0:
  246. txt += ", but some files were unstable"
  247. print(txt)
  248. sys.exit(0)
  249. if __name__ == '__main__':
  250. sys.exit(main(sys.argv))