]>
git.ipfire.org Git - thirdparty/hostap.git/blob - tests/hwsim/run-tests.py
4 # Copyright (c) 2013, Jouni Malinen <j@w1.fi>
6 # This software may be distributed under the terms of the BSD license.
7 # See README for more details.
13 from datetime
import datetime
18 logger
= logging
.getLogger()
20 sys
.path
.append('../../wpaspy')
22 from wpasupplicant
import WpaSupplicant
23 from hostapd
import HostapdGlobal
25 def reset_devs(dev
, apdev
):
26 hapd
= HostapdGlobal()
31 logger
.info("Failed to reset device " + d
.ifname
)
34 hapd
.remove(ap
['ifname'])
36 def report(conn
, build
, commit
, run
, test
, result
, diff
):
42 sql
= "INSERT INTO results(test,result,run,time,duration,build,commitid) VALUES(?, ?, ?, ?, ?, ?, ?)"
43 params
= (test
, result
, run
, time
.time(), diff
.total_seconds(), build
, commit
)
45 conn
.execute(sql
, params
)
48 print "sqlite: " + str(e
)
49 print "sql: %r" % (params
, )
51 class DataCollector(object):
52 def __init__(self
, logdir
, testname
, tracing
, dmesg
):
54 self
._testname
= testname
55 self
._tracing
= tracing
59 output
= os
.path
.join(self
._logdir
, '%s.dat' % (self
._testname
, ))
60 self
._trace
_cmd
= subprocess
.Popen(['sudo', 'trace-cmd', 'record', '-o', output
, '-e', 'mac80211', '-e', 'cfg80211', 'sh', '-c', 'echo STARTED ; read l'],
61 stdin
=subprocess
.PIPE
,
62 stdout
=subprocess
.PIPE
,
63 stderr
=open('/dev/null', 'w'),
65 l
= self
._trace
_cmd
.stdout
.read(7)
66 while not 'STARTED' in l
:
67 l
+= self
._trace
_cmd
.stdout
.read(1)
68 def __exit__(self
, type, value
, traceback
):
70 self
._trace
_cmd
.stdin
.write('DONE\n')
71 self
._trace
_cmd
.wait()
73 output
= os
.path
.join(self
._logdir
, '%s.dmesg' % (self
._testname
, ))
74 subprocess
.call(['sudo', 'dmesg', '-c'], stdout
=open(output
, 'w'))
79 for t
in os
.listdir("."):
80 m
= re
.match(r
'(test_.*)\.py$', t
)
82 logger
.debug("Import test cases from " + t
)
83 mod
= __import__(m
.group(1))
84 test_modules
.append(mod
.__name
__.replace('test_', '', 1))
86 if s
.startswith("test_"):
87 func
= mod
.__dict
__.get(s
)
89 test_names
= list(set([t
.__name
__.replace('test_', '', 1) for t
in tests
]))
94 parser
= argparse
.ArgumentParser(description
='hwsim test runner')
95 parser
.add_argument('--logdir', metavar
='<directory>', default
='logs',
96 help='log output directory for all other options, ' +
97 'must be given if other log options are used')
98 group
= parser
.add_mutually_exclusive_group()
99 group
.add_argument('-d', const
=logging
.DEBUG
, action
='store_const',
100 dest
='loglevel', default
=logging
.INFO
,
101 help="verbose debug output")
102 group
.add_argument('-q', const
=logging
.WARNING
, action
='store_const',
103 dest
='loglevel', help="be quiet")
104 group
.add_argument('-l', action
='store_true', dest
='logfile',
105 help='store debug log to a file (in log directory)')
107 parser
.add_argument('-e', metavar
="<filename>", dest
='errorfile',
108 nargs
='?', const
="failed",
109 help='error filename (in log directory)')
110 parser
.add_argument('-r', metavar
="<filename>", dest
='resultsfile',
111 nargs
='?', const
="results.txt",
112 help='results filename (in log directory)')
114 parser
.add_argument('-S', metavar
='<sqlite3 db>', dest
='database',
115 help='database to write results to')
116 parser
.add_argument('--commit', metavar
='<commit id>',
117 help='commit ID, only for database')
118 parser
.add_argument('-b', metavar
='<build>', dest
='build', help='build ID')
119 parser
.add_argument('-L', action
='store_true', dest
='update_tests_db',
120 help='List tests (and update descriptions in DB)')
121 parser
.add_argument('-T', action
='store_true', dest
='tracing',
122 help='collect tracing per test case (in log directory)')
123 parser
.add_argument('-D', action
='store_true', dest
='dmesg',
124 help='collect dmesg per test case (in log directory)')
125 parser
.add_argument('-f', dest
='testmodules', metavar
='<test module>',
126 help='execute only tests from these test modules',
127 type=str, choices
=[[]] + test_modules
, nargs
='+')
128 parser
.add_argument('tests', metavar
='<test>', nargs
='*', type=str,
129 help='tests to run (only valid without -f)',
130 choices
=[[]] + test_names
)
132 args
= parser
.parse_args()
134 if args
.tests
and args
.testmodules
:
135 print 'Invalid arguments - both test module and tests given'
138 if (args
.logfile
or args
.errorfile
or
139 args
.resultsfile
or args
.tracing
):
141 print 'Need --logdir for the given options'
145 logger
.setLevel(logging
.DEBUG
)
146 file_name
= os
.path
.join(args
.logdir
, 'run-tests.log')
147 log_handler
= logging
.FileHandler(file_name
)
148 fmt
= "%(asctime)s %(levelname)s %(message)s"
149 log_formatter
= logging
.Formatter(fmt
)
150 log_handler
.setFormatter(log_formatter
)
151 logger
.addHandler(log_handler
)
154 logging
.basicConfig(level
=args
.loglevel
)
157 if args
.loglevel
== logging
.WARNING
:
160 error_file
= args
.errorfile
and os
.path
.join(args
.logdir
, args
.errorfile
)
161 results_file
= args
.resultsfile
and os
.path
.join(args
.logdir
, args
.resultsfile
)
165 conn
= sqlite3
.connect(args
.database
)
170 run
= int(time
.time())
172 if args
.update_tests_db
:
174 name
= t
.__name
__.replace('test_', '', 1)
175 print name
+ " - " + t
.__doc
__
177 sql
= 'INSERT OR REPLACE INTO tests(test,description) VALUES (?, ?)'
178 params
= (name
, t
.__doc
__)
180 conn
.execute(sql
, params
)
182 print "sqlite: " + str(e
)
183 print "sql: %r" % (params
,)
190 dev0
= WpaSupplicant('wlan0', '/tmp/wpas-wlan0')
191 dev1
= WpaSupplicant('wlan1', '/tmp/wpas-wlan1')
192 dev2
= WpaSupplicant('wlan2', '/tmp/wpas-wlan2')
193 dev
= [ dev0
, dev1
, dev2
]
195 apdev
.append({"ifname": 'wlan3', "bssid": "02:00:00:00:03:00"})
196 apdev
.append({"ifname": 'wlan4', "bssid": "02:00:00:00:04:00"})
200 logger
.info(d
.ifname
+ ": No response from wpa_supplicant")
202 logger
.info("DEV: " + d
.ifname
+ ": " + d
.p2p_dev_addr())
204 logger
.info("APDEV: " + ap
['ifname'])
210 # make sure nothing is left over from previous runs
211 # (if there were any other manual runs or we crashed)
212 reset_devs(dev
, apdev
)
215 subprocess
.call(['sudo', 'dmesg', '-c'], stdout
=open('/dev/null', 'w'))
218 name
= t
.__name
__.replace('test_', '', 1)
220 if not name
in args
.tests
:
223 if not t
.__module
__.replace('test_', '', 1) in args
.testmodules
:
227 log_handler
.stream
.close()
228 logger
.removeHandler(log_handler
)
229 file_name
= os
.path
.join(args
.logdir
, name
+ '.log')
230 log_handler
= logging
.FileHandler(file_name
)
231 log_handler
.setFormatter(log_formatter
)
232 logger
.addHandler(log_handler
)
234 with
DataCollector(args
.logdir
, name
, args
.tracing
, args
.dmesg
):
235 logger
.info("START " + name
)
237 print "START " + name
240 logger
.info("Test: " + t
.__doc
__)
241 start
= datetime
.now()
244 d
.request("NOTE TEST-START " + name
)
246 logger
.info("Failed to issue TEST-START before " + name
+ " for " + d
.ifname
)
248 print "FAIL " + name
+ " - could not start test"
254 if t
.func_code
.co_argcount
> 1:
266 report(conn
, args
.build
, args
.commit
, run
, name
, result
, diff
)
267 result
= result
+ " " + name
+ " "
268 result
= result
+ str(diff
.total_seconds()) + " " + str(end
)
270 if log_to_file
or print_res
:
274 f
= open(results_file
, 'a')
275 f
.write(result
+ "\n")
282 report(conn
, args
.build
, args
.commit
, run
, name
, "FAIL", diff
)
283 result
= "FAIL " + name
+ " " + str(diff
.total_seconds()) + " " + str(end
)
289 f
= open(results_file
, 'a')
290 f
.write(result
+ "\n")
294 d
.request("NOTE TEST-STOP " + name
)
296 logger
.info("Failed to issue TEST-STOP after " + name
+ " for " + d
.ifname
)
298 reset_devs(dev
, apdev
)
300 for i
in range(0, 3):
303 srcname
= os
.path
.join(args
.logdir
, 'log' + str(i
))
304 dstname
= os
.path
.join(args
.logdir
, name
+ '.log' + str(i
))
306 while os
.path
.exists(dstname
):
307 dstname
= os
.path
.join(args
.logdir
, name
+ '.log' + str(i
) + '-' + str(num
))
309 os
.rename(srcname
, dstname
)
310 dev
[i
].request("RELOG")
311 subprocess
.call(['sudo', 'chown', '-f', getpass
.getuser(),
314 logger
.info("Failed to rename log files")
318 log_handler
.stream
.close()
319 logger
.removeHandler(log_handler
)
320 file_name
= os
.path
.join(args
.logdir
, 'run-tests.log')
321 log_handler
= logging
.FileHandler(file_name
)
322 log_handler
.setFormatter(log_formatter
)
323 logger
.addHandler(log_handler
)
329 logger
.info("passed " + str(len(passed
)) + " test case(s)")
330 logger
.info("skipped " + str(len(skipped
)) + " test case(s)")
331 logger
.info("failed tests: " + str(failed
))
333 f
= open(error_file
, 'w')
334 f
.write(str(failed
) + '\n')
337 logger
.info("passed all " + str(len(passed
)) + " test case(s)")
339 logger
.info("skipped " + str(len(skipped
)) + " test case(s)")
341 print "passed all " + str(len(passed
)) + " test case(s)"
343 print "skipped " + str(len(skipped
)) + " test case(s)"
345 if __name__
== "__main__":