Module tester
[hide private]
[frames] | no frames]

Source Code for Module tester

  1  #!/usr/bin/python 
  2   
  3  """ 
  4  Testing infrastructure - generates and executes tests 
  5   
  6  Computer Systems Architecture Course 
  7  Assignment 1 
  8  March 2016 
  9  """ 
 10  import getopt 
 11  import os 
 12  import pickle 
 13  import random 
 14  import subprocess 
 15  import sys 
 16  from threading import Timer 
 17   
 18  from supervisor import Supervisor 
 19  from test import TestCase, TestParams 
 20   
 21  # Tester messages 
 22  START_TEST_MSG       = "**************** Start %10s *****************"      # pylint: disable=bad-whitespace 
 23  END_TEST_MSG         = "***************** End %10s ******************"      # pylint: disable=bad-whitespace 
 24  TEST_ERRORS_MSG      = "Errors in iteration %d of %d:"                      # pylint: disable=bad-whitespace 
 25  TEST_FINISHED_MSG    = "%-10s finished.................%d%% completed"      # pylint: disable=bad-whitespace 
 26  TIMEOUT_MSG          = "%-10s timeout..................%d%% completed"      # pylint: disable=bad-whitespace 
27 28 -class Tester(object):
29 """ 30 Runs the test. 31 """
32 - def __init__(self, output_filename):
33 """ 34 Constructor. 35 @type output_filename: String 36 @param output_filename: the file in which the tester logs results 37 """ 38 self.output_filename = output_filename 39 40 self.passed_tests = 0 41 42 self.rand_gen = random.Random() 43 self.rand_gen.seed(0)
44
45 - def run_test(self, testcase, num_iterations=1):
46 """ 47 Performs a testcase generated from a given file or randomly. 48 To better check for synchronization errors the testcase is run several 49 times, as given by the 'num_iterations' parameter. 50 @type testcase: TestCase 51 @param testcase: the testcase to run 52 @type num_iterations: Integer 53 @param num_iterations: number of time to run the test 54 """ 55 print START_TEST_MSG % testcase.name 56 57 self.passed_tests = 0 58 59 testcase.num_iterations = num_iterations 60 for i in range(num_iterations): 61 print TEST_ERRORS_MSG % (i + 1, num_iterations) 62 testcase.crt_iteration = i + 1 63 if self.start_test(testcase) == 0: 64 self.passed_tests += 1 65 print "No errors" 66 67 print END_TEST_MSG % testcase.name 68 69 out_file = open(self.output_filename, "a") 70 71 msg = TEST_FINISHED_MSG % (testcase.name, 100.0 * self.passed_tests / num_iterations) 72 73 out_file.write(msg + "\n") 74 out_file.close()
75 76 @staticmethod
77 - def timer_fn(iteration, num_iterations):
78 """ 79 Timer function, it's executed in case of timeout when running a testcase 80 @type iteration: integer 81 @param iteration: the current iteration of the given testcase 82 @type num_iterations: integer 83 @param num_iterations: the total number of iterations for the given testcase 84 """ 85 print >> sys.stderr, "timeout" 86 87 os.abort()
88
89 - def start_test(self, test):
90 """ 91 Starts a child process that will run the test case. 92 93 @type test: TestCase 94 @param test: an object containing all the information necessary for 95 running the test case 96 """ 97 path = os.path.dirname(sys.argv[0]) 98 path = "." if path == "" else path 99 command = "python %s/tester.py" % path 100 test = pickle.dumps(test) 101 process = subprocess.Popen(command, stdin=subprocess.PIPE, shell=True) 102 process.communicate(test) 103 104 return process.returncode
105
106 107 -def usage(argv):
108 print "Usage: python %s [OPTIONS]"%argv[0] 109 print "options:" 110 print "\t-t, --test\tspecial test to run" 111 print "\t-f, --testfile\ttest file, if not specified run a pickled test from stdin" 112 print "\t-o, --out\t\toutput file" 113 print "\t-i, --iterations\t\tthe number of times the test is run (iterations), defaults to 2" 114 print "\t-h, --help\t\tprint this help screen"
115
116 117 -def main():
118 try: 119 opts, _ = getopt.getopt(sys.argv[1:], "h:t:f:o:i:", 120 ["help", "--test", "testfile=", "out=", "iterations="]) 121 122 except getopt.GetoptError, err: 123 print str(err) 124 usage(sys.argv) 125 sys.exit(2) 126 127 test_name = None 128 test_file = "" 129 iterations = 2 130 output_file = "tester.out" 131 132 for opt, arg in opts: 133 if opt in ("-h", "--help"): 134 usage(sys.argv) 135 sys.exit(0) 136 elif opt in ("-t", "--test"): 137 test_name = arg 138 elif opt in ("-f", "--testfile"): 139 test_file = arg 140 elif opt in ("-o", "--out"): 141 output_file = arg 142 elif opt in ("-i", "--iterations"): 143 try: 144 iterations = int(arg) 145 except TypeError, err: 146 print str(err) 147 sys.exit(2) 148 else: 149 assert False, "unhandled option" 150 151 if test_name == "test0": 152 tester = Tester(output_file) 153 test = TestCase.create_simple_test_case() 154 tester.run_test(test, iterations) 155 elif test_name == "test9": 156 tester = Tester(output_file) 157 test = TestCase.create_sharing1_test_case() 158 tester.run_test(test, iterations) 159 elif test_name == "test10": 160 tester = Tester(output_file) 161 test = TestCase.create_sharing2_test_case() 162 tester.run_test(test, iterations) 163 elif test_file: 164 tester = Tester(output_file) 165 test_params = TestParams.load_test(test_file) 166 test = TestCase.create_test_case(test_params, tester.rand_gen) 167 tester.run_test(test, iterations) 168 169 else: # I'm the child process :D 170 test = pickle.loads("".join(sys.stdin.readlines())) 171 172 watchdog = Timer(interval=test.timeout, 173 function=Tester.timer_fn, 174 args=(test.crt_iteration, test.num_iterations)) 175 176 watchdog.start() 177 178 supervisor = Supervisor(test) 179 supervisor.register_banned_thread(watchdog) 180 supervisor.register_banned_thread() 181 return_code = supervisor.run_testcase() 182 183 watchdog.cancel() 184 185 sys.stdout.flush() 186 sys.stderr.flush() 187 sys.exit(return_code)
188 189 190 if __name__ == "__main__": 191 main() 192