]> git.ipfire.org Git - thirdparty/hostap.git/blame - tests/hwsim/run-tests.py
tests: Use python3 compatible "except" statement
[thirdparty/hostap.git] / tests / hwsim / run-tests.py
CommitLineData
040dc68e 1#!/usr/bin/env python2
05955587 2#
8107d333 3# Test case executor
51c5aeb4 4# Copyright (c) 2013-2015, Jouni Malinen <j@w1.fi>
05955587
JM
5#
6# This software may be distributed under the terms of the BSD license.
7# See README for more details.
8
9import os
10import re
11import sys
12import time
1fc114a1 13from datetime import datetime
0b1faa8b 14import argparse
435e37df 15import subprocess
1942b681 16import termios
05955587
JM
17
18import logging
c9aa4308 19logger = logging.getLogger()
05955587 20
a302ee34
JM
21try:
22 import sqlite3
23 sqlite3_imported = True
24except ImportError:
25 sqlite3_imported = False
26
d2002f83
JB
27scriptsdir = os.path.dirname(os.path.realpath(sys.modules[__name__].__file__))
28sys.path.append(os.path.join(scriptsdir, '..', '..', 'wpaspy'))
b3e2ce3b 29
05955587 30from wpasupplicant import WpaSupplicant
b8cd4c54 31from hostapd import HostapdGlobal
5061a301 32from check_kernel import check_kernel
848bb8de 33from wlantest import Wlantest
51c5aeb4 34from utils import HwsimSkip
b8cd4c54 35
1942b681
JM
36def set_term_echo(fd, enabled):
37 [iflag, oflag, cflag, lflag, ispeed, ospeed, cc] = termios.tcgetattr(fd)
38 if enabled:
39 lflag |= termios.ECHO
40 else:
41 lflag &= ~termios.ECHO
42 termios.tcsetattr(fd, termios.TCSANOW,
43 [iflag, oflag, cflag, lflag, ispeed, ospeed, cc])
44
ae3ad328 45def reset_devs(dev, apdev):
66f0bdb4 46 ok = True
62d58f7a 47 for d in dev:
789959c4
JM
48 try:
49 d.reset()
bab493b9 50 except Exception as e:
789959c4 51 logger.info("Failed to reset device " + d.ifname)
1fc114a1 52 print str(e)
66f0bdb4 53 ok = False
9489637b 54
a66d2248 55 wpas = None
9489637b 56 try:
bb5d761c 57 wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5', monitor=False)
eb92d389
JM
58 ifaces = wpas.global_request("INTERFACES").splitlines()
59 for iface in ifaces:
60 if iface.startswith("wlan"):
61 wpas.interface_remove(iface)
bab493b9 62 except Exception as e:
9489637b 63 pass
a66d2248
JM
64 if wpas:
65 wpas.close_ctrl()
9489637b 66
66f0bdb4
JM
67 try:
68 hapd = HostapdGlobal()
f8949f5f 69 hapd.flush()
1edc3190
JM
70 hapd.remove('wlan3-6')
71 hapd.remove('wlan3-5')
72 hapd.remove('wlan3-4')
66f0bdb4
JM
73 hapd.remove('wlan3-3')
74 hapd.remove('wlan3-2')
75 for ap in apdev:
76 hapd.remove(ap['ifname'])
bab493b9 77 except Exception as e:
66f0bdb4
JM
78 logger.info("Failed to remove hostapd interface")
79 print str(e)
80 ok = False
81 return ok
05955587 82
1d646f5e
JM
83def add_log_file(conn, test, run, type, path):
84 if not os.path.exists(path):
85 return
86 contents = None
87 with open(path, 'r') as f:
88 contents = f.read()
89 if contents is None:
90 return
91 sql = "INSERT INTO logs(test,run,type,contents) VALUES(?, ?, ?, ?)"
a302ee34 92 params = (test, run, type, sqlite3.Binary(contents))
1d646f5e
JM
93 try:
94 conn.execute(sql, params)
95 conn.commit()
bab493b9 96 except Exception as e:
1d646f5e
JM
97 print "sqlite: " + str(e)
98 print "sql: %r" % (params, )
99
9363f5e0
JM
100def report(conn, prefill, build, commit, run, test, result, duration, logdir,
101 sql_commit=True):
b74b7e87
JM
102 if conn:
103 if not build:
104 build = ''
105 if not commit:
106 commit = ''
a5d7da3f
JB
107 if prefill:
108 conn.execute('DELETE FROM results WHERE test=? AND run=? AND result=?', (test, run, 'NOTRUN'))
781b65cf 109 sql = "INSERT INTO results(test,result,run,time,duration,build,commitid) VALUES(?, ?, ?, ?, ?, ?, ?)"
a5d7da3f 110 params = (test, result, run, time.time(), duration, build, commit)
b74b7e87 111 try:
781b65cf 112 conn.execute(sql, params)
9363f5e0
JM
113 if sql_commit:
114 conn.commit()
bab493b9 115 except Exception as e:
b74b7e87 116 print "sqlite: " + str(e)
781b65cf 117 print "sql: %r" % (params, )
b74b7e87 118
1d646f5e
JM
119 if result == "FAIL":
120 for log in [ "log", "log0", "log1", "log2", "log3", "log5",
121 "hostapd", "dmesg", "hwsim0", "hwsim0.pcapng" ]:
122 add_log_file(conn, test, run, log,
123 logdir + "/" + test + "." + log)
124
0d5a5404 125class DataCollector(object):
2494bcef 126 def __init__(self, logdir, testname, args):
0d5a5404 127 self._logdir = logdir
435e37df 128 self._testname = testname
2494bcef
VV
129 self._tracing = args.tracing
130 self._dmesg = args.dmesg
131 self._dbus = args.dbus
435e37df 132 def __enter__(self):
0d5a5404 133 if self._tracing:
2ca47da4 134 output = os.path.abspath(os.path.join(self._logdir, '%s.dat' % (self._testname, )))
c4668009 135 self._trace_cmd = subprocess.Popen(['trace-cmd', 'record', '-o', output, '-e', 'mac80211', '-e', 'cfg80211', '-e', 'printk', 'sh', '-c', 'echo STARTED ; read l'],
0d5a5404
JB
136 stdin=subprocess.PIPE,
137 stdout=subprocess.PIPE,
138 stderr=open('/dev/null', 'w'),
139 cwd=self._logdir)
140 l = self._trace_cmd.stdout.read(7)
b5008c2c 141 while self._trace_cmd.poll() is None and not 'STARTED' in l:
0d5a5404 142 l += self._trace_cmd.stdout.read(1)
b5008c2c
EA
143 res = self._trace_cmd.returncode
144 if res:
145 print "Failed calling trace-cmd: returned exit status %d" % res
146 sys.exit(1)
2494bcef
VV
147 if self._dbus:
148 output = os.path.abspath(os.path.join(self._logdir, '%s.dbus' % (self._testname, )))
149 self._dbus_cmd = subprocess.Popen(['dbus-monitor', '--system'],
150 stdout=open(output, 'w'),
151 stderr=open('/dev/null', 'w'),
152 cwd=self._logdir)
153 res = self._dbus_cmd.returncode
154 if res:
155 print "Failed calling dbus-monitor: returned exit status %d" % res
156 sys.exit(1)
435e37df 157 def __exit__(self, type, value, traceback):
0d5a5404
JB
158 if self._tracing:
159 self._trace_cmd.stdin.write('DONE\n')
160 self._trace_cmd.wait()
161 if self._dmesg:
162 output = os.path.join(self._logdir, '%s.dmesg' % (self._testname, ))
cfb5576d
JM
163 num = 0
164 while os.path.exists(output):
165 output = os.path.join(self._logdir, '%s.dmesg-%d' % (self._testname, num))
166 num += 1
c4668009 167 subprocess.call(['dmesg', '-c'], stdout=open(output, 'w'))
435e37df 168
57661377
JM
169def rename_log(logdir, basename, testname, dev):
170 try:
171 import getpass
172 srcname = os.path.join(logdir, basename)
173 dstname = os.path.join(logdir, testname + '.' + basename)
174 num = 0
175 while os.path.exists(dstname):
176 dstname = os.path.join(logdir,
177 testname + '.' + basename + '-' + str(num))
178 num = num + 1
179 os.rename(srcname, dstname)
66f0bdb4
JM
180 if dev:
181 dev.relog()
c4668009 182 subprocess.call(['chown', '-f', getpass.getuser(), srcname])
bab493b9 183 except Exception as e:
57661377
JM
184 logger.info("Failed to rename log files")
185 logger.info(e)
186
05955587 187def main():
0b1faa8b
JB
188 tests = []
189 test_modules = []
d2002f83 190 files = os.listdir(scriptsdir)
cb8cb33e 191 for t in files:
0b1faa8b
JB
192 m = re.match(r'(test_.*)\.py$', t)
193 if m:
194 logger.debug("Import test cases from " + t)
195 mod = __import__(m.group(1))
e9552262 196 test_modules.append(mod.__name__.replace('test_', '', 1))
6ac593ec
JM
197 for key,val in mod.__dict__.iteritems():
198 if key.startswith("test_"):
199 tests.append(val)
4cd8343f 200 test_names = list(set([t.__name__.replace('test_', '', 1) for t in tests]))
0b1faa8b 201
b74b7e87 202 run = None
0b1faa8b
JB
203
204 parser = argparse.ArgumentParser(description='hwsim test runner')
b72c3002 205 parser.add_argument('--logdir', metavar='<directory>',
0141fa52
JB
206 help='log output directory for all other options, ' +
207 'must be given if other log options are used')
0b1faa8b
JB
208 group = parser.add_mutually_exclusive_group()
209 group.add_argument('-d', const=logging.DEBUG, action='store_const',
210 dest='loglevel', default=logging.INFO,
211 help="verbose debug output")
212 group.add_argument('-q', const=logging.WARNING, action='store_const',
213 dest='loglevel', help="be quiet")
0b1faa8b 214
0b1faa8b
JB
215 parser.add_argument('-S', metavar='<sqlite3 db>', dest='database',
216 help='database to write results to')
a5d7da3f
JB
217 parser.add_argument('--prefill-tests', action='store_true', dest='prefill',
218 help='prefill test database with NOTRUN before all tests')
aee9446d
JB
219 parser.add_argument('--commit', metavar='<commit id>',
220 help='commit ID, only for database')
0b1faa8b
JB
221 parser.add_argument('-b', metavar='<build>', dest='build', help='build ID')
222 parser.add_argument('-L', action='store_true', dest='update_tests_db',
223 help='List tests (and update descriptions in DB)')
0141fa52
JB
224 parser.add_argument('-T', action='store_true', dest='tracing',
225 help='collect tracing per test case (in log directory)')
0d5a5404
JB
226 parser.add_argument('-D', action='store_true', dest='dmesg',
227 help='collect dmesg per test case (in log directory)')
2494bcef
VV
228 parser.add_argument('--dbus', action='store_true', dest='dbus',
229 help='collect dbus per test case (in log directory)')
de684a2b
JM
230 parser.add_argument('--shuffle-tests', action='store_true',
231 dest='shuffle_tests',
232 help='Shuffle test cases to randomize order')
09e38c2f 233 parser.add_argument('--split', help='split tests for parallel execution (<server number>/<total servers>)')
b5476d94
JM
234 parser.add_argument('--no-reset', action='store_true', dest='no_reset',
235 help='Do not reset devices at the end of the test')
91f3cf69
JM
236 parser.add_argument('--long', action='store_true',
237 help='Include test cases that take long time')
f72434b4
JB
238 parser.add_argument('-f', dest='testmodules', metavar='<test module>',
239 help='execute only tests from these test modules',
240 type=str, choices=[[]] + test_modules, nargs='+')
3bfa5f10
IP
241 parser.add_argument('-l', metavar='<modules file>', dest='mfile',
242 help='test modules file name')
0d7456e9
JM
243 parser.add_argument('-i', action='store_true', dest='stdin_ctrl',
244 help='stdin-controlled test case execution')
0b1faa8b
JB
245 parser.add_argument('tests', metavar='<test>', nargs='*', type=str,
246 help='tests to run (only valid without -f)',
247 choices=[[]] + test_names)
248
249 args = parser.parse_args()
250
3bfa5f10
IP
251 if (args.tests and args.testmodules) or (args.tests and args.mfile) or (args.testmodules and args.mfile):
252 print 'Invalid arguments - only one of (test, test modules, modules file) can be given.'
0b1faa8b
JB
253 sys.exit(2)
254
0b1faa8b 255 if args.database:
a302ee34
JM
256 if not sqlite3_imported:
257 print "No sqlite3 module found"
258 sys.exit(2)
0b1faa8b 259 conn = sqlite3.connect(args.database)
63f83fac
JB
260 conn.execute('CREATE TABLE IF NOT EXISTS results (test,result,run,time,duration,build,commitid)')
261 conn.execute('CREATE TABLE IF NOT EXISTS tests (test,description)')
1d646f5e 262 conn.execute('CREATE TABLE IF NOT EXISTS logs (test,run,type,contents)')
0b1faa8b
JB
263 else:
264 conn = None
7585f349 265
b74b7e87 266 if conn:
6a5b4b1a 267 run = int(time.time())
b74b7e87 268
5e3c0b02
JM
269 # read the modules from the modules file
270 if args.mfile:
0663ae22
JM
271 args.testmodules = []
272 with open(args.mfile) as f:
273 for line in f.readlines():
274 line = line.strip()
275 if not line or line.startswith('#'):
276 continue
277 args.testmodules.append(line)
5e3c0b02
JM
278
279 tests_to_run = []
499c5e9d
JM
280 if args.tests:
281 for selected in args.tests:
282 for t in tests:
283 name = t.__name__.replace('test_', '', 1)
284 if name == selected:
285 tests_to_run.append(t)
286 else:
287 for t in tests:
288 name = t.__name__.replace('test_', '', 1)
289 if args.testmodules:
290 if not t.__module__.replace('test_', '', 1) in args.testmodules:
291 continue
292 tests_to_run.append(t)
5e3c0b02 293
0b1faa8b 294 if args.update_tests_db:
5e3c0b02 295 for t in tests_to_run:
4cd8343f 296 name = t.__name__.replace('test_', '', 1)
aa5fcc55
JM
297 if t.__doc__ is None:
298 print name + " - MISSING DESCRIPTION"
299 else:
300 print name + " - " + t.__doc__
f3be6eea 301 if conn:
781b65cf 302 sql = 'INSERT OR REPLACE INTO tests(test,description) VALUES (?, ?)'
4cd8343f 303 params = (name, t.__doc__)
f3be6eea 304 try:
781b65cf 305 conn.execute(sql, params)
bab493b9 306 except Exception as e:
f3be6eea 307 print "sqlite: " + str(e)
781b65cf 308 print "sql: %r" % (params,)
f3be6eea
JM
309 if conn:
310 conn.commit()
311 conn.close()
9b00f24a
JM
312 sys.exit(0)
313
cb8cb33e
JM
314 if not args.logdir:
315 if os.path.exists('logs/current'):
316 args.logdir = 'logs/current'
317 else:
318 args.logdir = 'logs'
319
320 # Write debug level log to a file and configurable verbosity to stdout
321 logger.setLevel(logging.DEBUG)
322
323 stdout_handler = logging.StreamHandler()
324 stdout_handler.setLevel(args.loglevel)
325 logger.addHandler(stdout_handler)
326
327 file_name = os.path.join(args.logdir, 'run-tests.log')
328 log_handler = logging.FileHandler(file_name)
329 log_handler.setLevel(logging.DEBUG)
330 fmt = "%(asctime)s %(levelname)s %(message)s"
331 log_formatter = logging.Formatter(fmt)
332 log_handler.setFormatter(log_formatter)
333 logger.addHandler(log_handler)
05955587 334
0fa28afe
JM
335 dev0 = WpaSupplicant('wlan0', '/tmp/wpas-wlan0')
336 dev1 = WpaSupplicant('wlan1', '/tmp/wpas-wlan1')
337 dev2 = WpaSupplicant('wlan2', '/tmp/wpas-wlan2')
0b20f514 338 dev = [ dev0, dev1, dev2 ]
ae3ad328 339 apdev = [ ]
ae3ad328 340 apdev.append({"ifname": 'wlan3', "bssid": "02:00:00:00:03:00"})
0b20f514 341 apdev.append({"ifname": 'wlan4', "bssid": "02:00:00:00:04:00"})
05955587
JM
342
343 for d in dev:
344 if not d.ping():
3ed2814a 345 logger.info(d.ifname + ": No response from wpa_supplicant")
05955587 346 return
3ed2814a 347 logger.info("DEV: " + d.ifname + ": " + d.p2p_dev_addr())
ae3ad328 348 for ap in apdev:
3ed2814a 349 logger.info("APDEV: " + ap['ifname'])
05955587 350
05955587 351 passed = []
0d84c400 352 skipped = []
05955587
JM
353 failed = []
354
8f946511
JB
355 # make sure nothing is left over from previous runs
356 # (if there were any other manual runs or we crashed)
66f0bdb4
JM
357 if not reset_devs(dev, apdev):
358 if conn:
359 conn.close()
360 conn = None
361 sys.exit(1)
8f946511 362
0d5a5404 363 if args.dmesg:
c4668009 364 subprocess.call(['dmesg', '-c'], stdout=open('/dev/null', 'w'))
0d5a5404 365
a5d7da3f
JB
366 if conn and args.prefill:
367 for t in tests_to_run:
368 name = t.__name__.replace('test_', '', 1)
1d646f5e 369 report(conn, False, args.build, args.commit, run, name, 'NOTRUN', 0,
9363f5e0
JM
370 args.logdir, sql_commit=False)
371 conn.commit()
a5d7da3f 372
09e38c2f
JM
373 if args.split:
374 vals = args.split.split('/')
375 split_server = int(vals[0])
376 split_total = int(vals[1])
377 logger.info("Parallel execution - %d/%d" % (split_server, split_total))
378 split_server -= 1
379 tests_to_run.sort(key=lambda t: t.__name__)
380 tests_to_run = [x for i,x in enumerate(tests_to_run) if i % split_total == split_server]
381
de684a2b
JM
382 if args.shuffle_tests:
383 from random import shuffle
384 shuffle(tests_to_run)
385
b1448311 386 count = 0
0d7456e9
JM
387 if args.stdin_ctrl:
388 print "READY"
389 sys.stdout.flush()
f6d1c5d9 390 num_tests = 0
0d7456e9 391 else:
f6d1c5d9 392 num_tests = len(tests_to_run)
1942b681
JM
393 if args.stdin_ctrl:
394 set_term_echo(sys.stdin.fileno(), False)
c55799e5
JM
395
396 check_country_00 = True
397 for d in dev:
398 if d.get_driver_status_field("country") != "00":
399 check_country_00 = False
400
0d7456e9
JM
401 while True:
402 if args.stdin_ctrl:
403 test = sys.stdin.readline()
404 if not test:
405 break
406 test = test.splitlines()[0]
407 if test == '':
408 break
409 t = None
410 for tt in tests:
411 name = tt.__name__.replace('test_', '', 1)
412 if name == test:
413 t = tt
414 break
415 if not t:
416 print "NOT-FOUND"
417 sys.stdout.flush()
418 continue
419 else:
f6d1c5d9 420 if len(tests_to_run) == 0:
0d7456e9 421 break
f6d1c5d9 422 t = tests_to_run.pop(0)
0d7456e9 423
c55799e5
JM
424 if dev[0].get_driver_status_field("country") == "98":
425 # Work around cfg80211 regulatory issues in clearing intersected
426 # country code 98. Need to make station disconnect without any
427 # other wiphy being active in the system.
428 logger.info("country=98 workaround - try to clear state")
429 id = dev[1].add_network()
430 dev[1].set_network(id, "mode", "2")
431 dev[1].set_network_quoted(id, "ssid", "country98")
432 dev[1].set_network(id, "key_mgmt", "NONE")
433 dev[1].set_network(id, "frequency", "2412")
434 dev[1].set_network(id, "scan_freq", "2412")
435 dev[1].select_network(id)
436 ev = dev[1].wait_event(["CTRL-EVENT-CONNECTED"])
437 if ev:
438 dev[0].connect("country98", key_mgmt="NONE", scan_freq="2412")
439 dev[1].request("DISCONNECT")
440 dev[0].wait_disconnected()
441 dev[0].request("DISCONNECT")
442 dev[0].request("ABORT_SCAN")
443 time.sleep(1)
444 dev[0].reset()
445 dev[1].reset()
446 dev[0].dump_monitor()
447 dev[1].dump_monitor()
448
a5d7da3f 449 name = t.__name__.replace('test_', '', 1)
f2a438f5 450 open('/dev/kmsg', 'w').write('running hwsim test case %s\n' % name)
c9aa4308
JM
451 if log_handler:
452 log_handler.stream.close()
453 logger.removeHandler(log_handler)
454 file_name = os.path.join(args.logdir, name + '.log')
455 log_handler = logging.FileHandler(file_name)
8f47f31d 456 log_handler.setLevel(logging.DEBUG)
c9aa4308
JM
457 log_handler.setFormatter(log_formatter)
458 logger.addHandler(log_handler)
459
66f0bdb4 460 reset_ok = True
2494bcef 461 with DataCollector(args.logdir, name, args):
b1448311 462 count = count + 1
f6d1c5d9 463 msg = "START {} {}/{}".format(name, count, num_tests)
b1448311 464 logger.info(msg)
8f47f31d 465 if args.loglevel == logging.WARNING:
b1448311 466 print msg
f9174c3b 467 sys.stdout.flush()
435e37df
JB
468 if t.__doc__:
469 logger.info("Test: " + t.__doc__)
470 start = datetime.now()
8171d704 471 open('/dev/kmsg', 'w').write('TEST-START %s @%.6f\n' % (name, time.time()))
435e37df
JB
472 for d in dev:
473 try:
521b7e79
JM
474 d.dump_monitor()
475 if not d.ping():
476 raise Exception("PING failed for {}".format(d.ifname))
477 if not d.global_ping():
478 raise Exception("Global PING failed for {}".format(d.ifname))
4cd8343f 479 d.request("NOTE TEST-START " + name)
bab493b9 480 except Exception as e:
4cd8343f 481 logger.info("Failed to issue TEST-START before " + name + " for " + d.ifname)
435e37df 482 logger.info(e)
4cd8343f 483 print "FAIL " + name + " - could not start test"
435e37df
JB
484 if conn:
485 conn.close()
486 conn = None
1942b681
JM
487 if args.stdin_ctrl:
488 set_term_echo(sys.stdin.fileno(), True)
435e37df 489 sys.exit(1)
4896ddae 490 try:
90073916
JM
491 if t.func_code.co_argcount > 2:
492 params = {}
493 params['logdir'] = args.logdir
91f3cf69 494 params['long'] = args.long
81e787b7 495 t(dev, apdev, params)
90073916 496 elif t.func_code.co_argcount > 1:
81e787b7 497 t(dev, apdev)
435e37df 498 else:
81e787b7
JM
499 t(dev)
500 result = "PASS"
c55799e5
JM
501 if check_country_00:
502 for d in dev:
503 country = d.get_driver_status_field("country")
504 if country != "00":
505 d.dump_monitor()
506 logger.info("Country code not reset back to 00: is " + country)
507 print "Country code not reset back to 00: is " + country
508 result = "FAIL"
509
510 # Try to wait for cfg80211 regulatory state to
511 # clear.
512 d.cmd_execute(['iw', 'reg', 'set', '00'])
513 for i in range(5):
514 time.sleep(1)
515 country = d.get_driver_status_field("country")
516 if country == "00":
517 break
518 if country == "00":
519 print "Country code cleared back to 00"
520 logger.info("Country code cleared back to 00")
521 else:
522 print "Country code remains set - expect following test cases to fail"
523 logger.info("Country code remains set - expect following test cases to fail")
524 break
bab493b9 525 except HwsimSkip as e:
51c5aeb4
JM
526 logger.info("Skip test case: %s" % e)
527 result = "SKIP"
bab493b9 528 except NameError as e:
1a4f18d8
JB
529 import traceback
530 logger.info(e)
531 traceback.print_exc()
532 result = "FAIL"
bab493b9 533 except Exception as e:
2147b3a7 534 import traceback
51c5aeb4 535 logger.info(e)
2147b3a7 536 traceback.print_exc()
51c5aeb4
JM
537 if args.loglevel == logging.WARNING:
538 print "Exception: " + str(e)
539 result = "FAIL"
8171d704 540 open('/dev/kmsg', 'w').write('TEST-STOP %s @%.6f\n' % (name, time.time()))
435e37df
JB
541 for d in dev:
542 try:
521b7e79 543 d.dump_monitor()
4cd8343f 544 d.request("NOTE TEST-STOP " + name)
bab493b9 545 except Exception as e:
f5f59e4f 546 logger.info("Failed to issue TEST-STOP after {} for {}".format(name, d.ifname))
435e37df 547 logger.info(e)
66f0bdb4 548 result = "FAIL"
78a37200
JM
549 if args.no_reset:
550 print "Leaving devices in current state"
551 else:
552 reset_ok = reset_devs(dev, apdev)
a66d2248 553 wpas = None
9489637b 554 try:
a66d2248 555 wpas = WpaSupplicant(global_iface="/tmp/wpas-wlan5")
9489637b
JM
556 rename_log(args.logdir, 'log5', name, wpas)
557 if not args.no_reset:
558 wpas.remove_ifname()
bab493b9 559 except Exception as e:
9489637b 560 pass
a66d2248
JM
561 if wpas:
562 wpas.close_ctrl()
05955587 563
353e5067 564 for i in range(0, 3):
57661377 565 rename_log(args.logdir, 'log' + str(i), name, dev[i])
66f0bdb4
JM
566 try:
567 hapd = HostapdGlobal()
bab493b9 568 except Exception as e:
66f0bdb4
JM
569 print "Failed to connect to hostapd interface"
570 print str(e)
571 reset_ok = False
572 result = "FAIL"
573 hapd = None
57661377 574 rename_log(args.logdir, 'hostapd', name, hapd)
1f9427c9
JM
575 if hapd:
576 del hapd
577 hapd = None
75428961 578
8efc83d4
JA
579 # Use None here since this instance of Wlantest() will never be
580 # used for remote host hwsim tests on real hardware.
581 Wlantest.setup(None)
848bb8de
JM
582 wt = Wlantest()
583 rename_log(args.logdir, 'hwsim0.pcapng', name, wt)
584 rename_log(args.logdir, 'hwsim0', name, wt)
41a256ec
AN
585 if os.path.exists(os.path.join(args.logdir, 'fst-wpa_supplicant')):
586 rename_log(args.logdir, 'fst-wpa_supplicant', name, None)
587 if os.path.exists(os.path.join(args.logdir, 'fst-hostapd')):
588 rename_log(args.logdir, 'fst-hostapd', name, None)
d760db19
MH
589 if os.path.exists(os.path.join(args.logdir, 'wmediumd.log')):
590 rename_log(args.logdir, 'wmediumd.log', name, None)
848bb8de 591
4a1b8901
JB
592 end = datetime.now()
593 diff = end - start
5061a301
JB
594
595 if result == 'PASS' and args.dmesg:
596 if not check_kernel(os.path.join(args.logdir, name + '.dmesg')):
bcbd7415 597 logger.info("Kernel issue found in dmesg - mark test failed")
5061a301
JB
598 result = 'FAIL'
599
600 if result == 'PASS':
601 passed.append(name)
602 elif result == 'SKIP':
603 skipped.append(name)
604 else:
605 failed.append(name)
606
1d646f5e
JM
607 report(conn, args.prefill, args.build, args.commit, run, name, result,
608 diff.total_seconds(), args.logdir)
f5f59e4f 609 result = "{} {} {} {}".format(result, name, diff.total_seconds(), end)
4a1b8901 610 logger.info(result)
8f47f31d 611 if args.loglevel == logging.WARNING:
4a1b8901
JB
612 print result
613 sys.stdout.flush()
614
66f0bdb4
JM
615 if not reset_ok:
616 print "Terminating early due to device reset failure"
617 break
1942b681
JM
618 if args.stdin_ctrl:
619 set_term_echo(sys.stdin.fileno(), True)
66f0bdb4 620
c9aa4308
JM
621 if log_handler:
622 log_handler.stream.close()
623 logger.removeHandler(log_handler)
624 file_name = os.path.join(args.logdir, 'run-tests.log')
625 log_handler = logging.FileHandler(file_name)
8f47f31d 626 log_handler.setLevel(logging.DEBUG)
c9aa4308
JM
627 log_handler.setFormatter(log_formatter)
628 logger.addHandler(log_handler)
629
b74b7e87
JM
630 if conn:
631 conn.close()
632
05955587 633 if len(failed):
f5f59e4f
JM
634 logger.info("passed {} test case(s)".format(len(passed)))
635 logger.info("skipped {} test case(s)".format(len(skipped)))
a572f0b9 636 logger.info("failed tests: " + ' '.join(failed))
8f47f31d 637 if args.loglevel == logging.WARNING:
a572f0b9 638 print "failed tests: " + ' '.join(failed)
05955587 639 sys.exit(1)
f5f59e4f 640 logger.info("passed all {} test case(s)".format(len(passed)))
0d84c400 641 if len(skipped):
f5f59e4f 642 logger.info("skipped {} test case(s)".format(len(skipped)))
8f47f31d 643 if args.loglevel == logging.WARNING:
f5f59e4f 644 print "passed all {} test case(s)".format(len(passed))
0d84c400 645 if len(skipped):
f5f59e4f 646 print "skipped {} test case(s)".format(len(skipped))
05955587
JM
647
648if __name__ == "__main__":
649 main()