#! /usr/bin/env python ############################################################################### # # simulavr - A simulator for the Atmel AVR family of microcontrollers. # Copyright (C) 2001, 2002 Theodore A. Roth # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # ############################################################################### # # $Id: regress.py.in,v 1.9 2003/03/25 20:09:37 troth Exp $ # # # @configure_input@ import os, sys, fnmatch, glob # Check the python version _v = sys.version_info _ver = (int(_v[0]) << 16) + (int(_v[1]) << 8) + int(_v[2]) if _ver < 0x020101: sys.write('You need python >= 2.1.1 to run this program.\n') sys.write('Your python version is:\n%s\n' %(sys.version)) sys.exit(1) # This should let you run the regress.py.in script directly for testing. # Remember that configure will replace '@@'. if '@srcdir@' == '@'+'srcdir'+'@': srcdir = '.' else: srcdir = '@srcdir@' regressdir = os.getcwd() # Change dir to srcdir so that building in other dir works os.chdir(srcdir) # default path to simulator sim_path = regressdir+'/../src/simulavr' # Add modules dir to module search path sys.path.append('modules') import avr_target, base_test """Main regression test driver program. Test cases are organised into three levels: directories -> modules -> classes. Directories are the most generic and classes are the most specific. This program will search the current directory for subdirectories with names matching 'test_*'. Each matching subdirectory will be searched for python modules with names matching test_*.py. Each module will be loaded and the attributes searched for classes with names beginning with 'test_'. Each class will perform a single test and if the test fails, an exception derived from base_test.TestFail is raised to indicate that the test has failed. There can be many matches are each level. """ EXIT_STATUS_PASS = 0 EXIT_STATUS_FAIL = 1 def run_tests(target, tdir=None, tmodule=None, tname=None): result = EXIT_STATUS_PASS num_tests = 0 num_passes = 0 num_fails = 0 start_time = os.times()[4] if tdir is None: test_dirs = glob.glob('test_*') else: if tdir[:5] != 'test_': tdir = 'test_'+tdir test_dirs = [tdir] for test_dir in test_dirs: if tmodule is None: try: test_modules = os.listdir(test_dir) except OSError: # problem getting dir listing, go to next dir continue else: if tmodule[:5] != 'test_': tmodule = 'test_'+tmodule if tmodule[-3:] != '.py': tmodule += '.py' test_modules = [tmodule] print '='*8 + ' running tests in %s directory' % (test_dir) # add tests dir to module search patch sys.path.append(test_dir) # Loop through all files in test dir for file in test_modules: # skip files which are not test modules (test modules are 'test_*.py') if not fnmatch.fnmatch(file, 'test_*.py'): continue # get test module name by stripping off .py from file name test_module_name = file[:-3] print '-'*4 + ' loading tests from %s module' %(test_module_name) test_module = __import__(test_module_name) if tname is None: test_names = dir(test_module) else: if tname[:5] != 'test_': tname = 'test_'+tname test_names = [tname] # Loop through all attributes of test_module for test_name in test_names: # If attribute is not a test case, skip it. if test_name[:5] != 'test_': continue try: # Create an instance of the test case object and run it test = apply( getattr(test_module,test_name), (target,) ) print '%-30s -> ' %(test_name), test.run() except base_test.TestFail, reason: print 'FAILED: %s' %(reason) num_fails += 1 # Could also do a sys.exit(1) here is user wishes result = EXIT_STATUS_FAIL else: num_passes += 1 print 'passed' num_tests += 1 # reset the target after each test target.reset() test_names = None test_modules = None # remove test_dir from the module search path sys.path.remove(test_dir) elapsed = os.times()[4] - start_time print print 'Ran %d tests in %.3f seconds [%0.3f tests/second].' % \ (num_tests, elapsed, num_tests/elapsed) print ' Number of Passing Tests: %d' %(num_passes) print ' Number of Failing Tests: %d' %(num_fails) print return result def usage(): print >> sys.stderr, """ Usage: regress.py [options] [[test_]dir] [[test_]module[.py]] [[test_]case] The 'test_' prefix on all args is optional. The '.py' extension on the test_module arg is also optional. Options: -h, --help : print this message and exit -s, --sim= : path to simulavr executable --stall : stall the regression engine when done """ sys.exit(1) def run_simulator(prog, port=1212, dev="at90s8515"): """Attempt to start up a simulator and return pid. """ # Check if prog file exists if not os.path.isfile(prog): print >> sys.stderr, '%s does not exist' %(prog) sys.exit(1) pid = os.fork() if pid == 0: # child process sys.stdout.close() sys.stderr.close() out = os.open(regressdir+'/sim.out', os.O_WRONLY | os.O_CREAT | os.O_TRUNC, 0644) os.dup2(out, 1) os.close(out) err = os.open(regressdir+'/sim.err', os.O_WRONLY | os.O_CREAT | os.O_TRUNC, 0644) os.dup2(err, 2) os.close(err) os.execlp( prog, prog, '-g', '-G', '-d', dev, '-p', str(port) ) assert 0, 'error starting program' # should never get here. return pid if __name__ == '__main__': import getopt, time, socket, signal # Parse command line options try: opts, args = getopt.getopt(sys.argv[1:], "hs:", ["help", "sim=", "stall"]) except getopt.GetoptError: # print help information and exit: usage() stall = 0 for o, a in opts: if o in ("-h", "--help"): usage() if o in ("-s", "--sim"): sim_path = a if o in ("--stall",): stall = 1 if len(args) > 3: usage() sim_pid = run_simulator(sim_path) # Open a connection to the target tries = 5 while (tries > 0): try: target = avr_target.AvrTarget() except socket.error: print >> sys.stderr, 'Simulator not responding, wait a second and try again' tries -= 1 time.sleep(1) else: break if tries == 0: print >> sys.stderr, 'Fatal error: simulator did not start' sys.exit(1) # run the tests try: status = apply(run_tests, [target]+args) finally: # We always want to shut down the simulator target.close() if stall: raw_input('hit enter to quit...') # make sure that the simulator has quit os.kill(sim_pid, signal.SIGINT) os.waitpid(sim_pid, os.WNOHANG) sys.exit( status )