File: regress.py.in

package info (click to toggle)
simulavr 1.0.0%2Bgit20160221.e53413b-3
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 6,740 kB
  • sloc: cpp: 35,491; python: 6,995; ansic: 3,567; makefile: 1,075; sh: 653; asm: 414; tcl: 320; javascript: 32
file content (267 lines) | stat: -rw-r--r-- 7,987 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
#! /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.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
#
###############################################################################
#
# $Id: regress.py.in,v 1.1 2004/07/31 00:58:05 rivetwa Exp $
#

# # @configure_input@

from __future__ import print_function
import os, os.path, sys, fnmatch, glob
import subprocess

# 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 '@<something>@'.
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' + os.path.splitext(sys.executable)[1]

# 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
  num_not_supported = 0

  start_time = sum(os.times()[:2])

  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 = getattr(test_module,test_name)(*(target,))
          print('%-30s  ->  ' %(test_name), end=' ')
          test.run()
        except base_test.TestFail as reason:
          print('FAILED: %s' %(reason))
          num_fails += 1
          # Could also do a sys.exit(1) here is user wishes
          result = EXIT_STATUS_FAIL
        except base_test.TestOpcodeNotSupported as reason:
          print(reason)
          num_not_supported += 1
        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 = sum(os.times()[:2]) - 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('  Number of Skipped Tests: %d (opcode not supported by target)' %(num_not_supported))
  print()
  
  return result

def usage():
  print("""
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
  -d, --dev=<dev> : use the given device for simulation, the defaul value is
                    "atmega128"
  -s, --sim=<sim> : path to simulavr executable
      --stall     : stall the regression engine when done
""", file=sys.stderr)
  sys.exit(1)

def run_simulator(prog, dev, port=1212):
  """Attempt to start up a simulator and return pid.
  """

  # Check if prog file exists
  if not os.path.isfile(prog):
    print('%s does not exist' %(prog), file=sys.stderr)
    sys.exit(1)

  out = os.open(regressdir+'/sim.out', os.O_WRONLY | os.O_CREAT | os.O_TRUNC, 0o644)
  err = os.open(regressdir+'/sim.err', os.O_WRONLY | os.O_CREAT | os.O_TRUNC, 0o644)
  p = subprocess.Popen((prog, '-g', '-G', '-d', dev, '-p', str(port)),
                       shell = False,
                       stdout = out,
                       stderr = err)

  return p
  
if __name__ == '__main__':
  import getopt, time, socket, signal

  # Parse command line options
  try:
    opts, args = getopt.getopt(sys.argv[1:], "hd:s:", ["help", "dev=", "sim=", "stall"])
  except getopt.GetoptError:
    # print help information and exit:
    usage()

  device = "atmega128"
  stall = 0

  for o, a in opts:
    if o in ("-h", "--help"):
      usage()
    if o in ("-d", "--dev"):
      device = a
    if o in ("-s", "--sim"):
      sim_path = a
    if o in ("--stall",):
      stall = 1

  if len(args) > 3:
    usage()

  sim_p = run_simulator(sim_path, device)

  # Open a connection to the target
  tries = 5
  while (tries > 0):
    try:
      target = avr_target.AvrTarget(device)
    except socket.error:
      print('Simulator not responding, wait a second and try again', file=sys.stderr)
      tries -= 1
      time.sleep(1)
    else:
      break
  if tries == 0:
    print('Fatal error: simulator did not start', file=sys.stderr)
    sys.exit(1)

  # run the tests
  try:
    status = run_tests(*[target]+args)
  finally:
    # We always want to shut down the simulator
    target.close()

    if stall:
      input('hit enter to quit...')

    # make sure that the simulator has quit
    sim_p.wait()
    
  sys.exit( status )