regression.py 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  1. import sys, os, subprocess, re, time
  2. class Result:
  3. def __init__(self, out, log, code):
  4. self.out = out.split('\n')
  5. self.log = log.split('\n')
  6. self.code = code
  7. class Regression:
  8. def __init__(self, loader = None, executable = '', prepare = None, timeout = 0):
  9. self.loader = loader
  10. self.executable = executable
  11. self.prepare = prepare
  12. self.runs = dict()
  13. default_timeout = int(os.getenv('TIMEOUT', '10000'))
  14. if default_timeout > timeout:
  15. self.timeout = default_timeout
  16. else:
  17. self.timeout = timeout
  18. self.keep_log = (os.getenv('KEEP_LOG', '0') == '1')
  19. def add_check(self, name, check, times = 1, ignore_failure=0, args = []):
  20. combined_args = ' '.join(args)
  21. if not combined_args in self.runs:
  22. self.runs[combined_args] = []
  23. self.runs[combined_args].append((name, check, ignore_failure, times))
  24. def run_checks(self):
  25. something_failed = 0
  26. for combined_args in self.runs:
  27. needed_times = 1
  28. for (name, check, ignore_failure, times) in self.runs[combined_args]:
  29. if needed_times < times:
  30. needed_times = times
  31. run_times = 0
  32. outputs = []
  33. timed_out = False
  34. while run_times < needed_times:
  35. args = []
  36. if self.loader:
  37. args.append(self.loader)
  38. if self.executable:
  39. args.append(self.executable)
  40. if combined_args:
  41. args += combined_args.split(' ')
  42. if self.prepare:
  43. self.prepare(args)
  44. time.sleep(0.1)
  45. p = subprocess.Popen(args,
  46. stdout=subprocess.PIPE,
  47. stderr=subprocess.PIPE)
  48. sleep_time = 0
  49. finish = False
  50. while sleep_time < self.timeout:
  51. time.sleep(0.001)
  52. if p.poll() is not None:
  53. finish = True
  54. break
  55. sleep_time += 1
  56. if not finish and p.poll() is None:
  57. timed_out = True
  58. p.kill()
  59. time.sleep(0.1)
  60. out = p.stdout.read().decode('utf-8')
  61. log = p.stderr.read().decode('utf-8')
  62. outputs.append(Result(out, log, p.returncode))
  63. run_times = run_times + 1
  64. keep_log = False
  65. for (name, check, ignore_failure, times) in self.runs[combined_args]:
  66. if run_times == times:
  67. result = check(outputs)
  68. if not timed_out and result:
  69. print('\033[92m[Success ]\033[0m', name)
  70. else:
  71. if ignore_failure:
  72. print('[Fail (Ignored)]', name)
  73. else:
  74. print('\033[93m[Fail ]\033[0m', name)
  75. something_failed = 1
  76. if timed_out : print('Test timed out!')
  77. keep_log = True
  78. if self.keep_log and keep_log:
  79. sargs = [re.sub(r"\W", '_', a).strip('_') for a in args]
  80. filename = 'log-' + '_'.join(sargs) + '_' + time.strftime("%Y%m%d_%H%M%S")
  81. with open(filename, 'w') as f:
  82. f.write(log + out)
  83. print('keep log to %s' % (filename))
  84. if something_failed:
  85. return -1
  86. else:
  87. return 0