blob: 67993a3c2a3427793cc9feaa406ebc49226467a3 [file] [log] [blame]
b.liue9582032025-04-17 19:18:16 +08001#!/usr/bin/env python3
2#
3# Remote test case executor
4# Copyright (c) 2016, Tieto Corporation
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
13import traceback
14import getopt
15from datetime import datetime
16from random import shuffle
17
18import logging
19logger = logging.getLogger()
20
21scriptsdir = os.path.dirname(os.path.realpath(sys.modules[__name__].__file__))
22sys.path.append(os.path.join(scriptsdir, '..', '..', 'wpaspy'))
23sys.path.append(os.path.join(scriptsdir, '..', 'hwsim'))
24
25import wpaspy
26import config
27from test_devices import show_devices
28from test_devices import check_devices
29from rutils import TestSkip
30from utils import HwsimSkip
31from hwsim_wrapper import run_hwsim_test
32
33def usage():
34 print("USAGE: " + sys.argv[0] + " -t devices")
35 print("USAGE: " + sys.argv[0] + " -t check_devices")
36 print("USAGE: " + sys.argv[0] + " -d <dut_name> -t <all|sanity|tests_to_run> [-r <ref_name>] [-c <cfg_file.py>] [-m <all|monitor_name>] [-h hwsim_tests] [-f hwsim_modules][-R][-T][-P][-S][-v]")
37 print("USAGE: " + sys.argv[0])
38
39def get_devices(devices, duts, refs, monitors):
40 for dut in duts:
41 config.get_device(devices, dut, lock=True)
42 for ref in refs:
43 config.get_device(devices, ref, lock=True)
44 for monitor in monitors:
45 if monitor == "all":
46 continue
47 if monitor in duts:
48 continue
49 if monitor in refs:
50 continue
51 config.get_device(devices, monitor, lock=True)
52
53def put_devices(devices, duts, refs, monitors):
54 for dut in duts:
55 config.put_device(devices, dut)
56 for ref in refs:
57 config.put_device(devices, ref)
58 for monitor in monitors:
59 if monitor == "all":
60 continue
61 if monitor in duts:
62 continue
63 if monitor in refs:
64 continue
65 config.put_device(devices, monitor)
66
67def main():
68 duts = []
69 refs = []
70 monitors = []
71 filter_keys = []
72 requested_tests = ["help"]
73 requested_hwsim_tests = []
74 hwsim_tests = []
75 requested_modules = []
76 modules_tests = []
77 cfg_file = "cfg.py"
78 log_dir = "./logs/"
79 verbose = False
80 trace = False
81 restart = False
82 perf = False
83 shuffle_tests = False
84
85 # parse input parameters
86 try:
87 opts, args = getopt.getopt(sys.argv[1:], "d:f:r:t:l:k:c:m:h:vRPTS",
88 ["dut=", "modules=", "ref=", "tests=",
89 "log-dir=",
90 "cfg=", "key=", "monitor=", "hwsim="])
91 except getopt.GetoptError as err:
92 print(err)
93 usage()
94 sys.exit(2)
95
96 for option, argument in opts:
97 if option == "-v":
98 verbose = True
99 elif option == "-R":
100 restart = True
101 elif option == "-T":
102 trace = True
103 elif option == "-P":
104 perf = True
105 elif option == "-S":
106 shuffle_tests = True
107 elif option in ("-d", "--dut"):
108 duts.append(argument)
109 elif option in ("-r", "--ref"):
110 refs.append(argument)
111 elif option in ("-t", "--tests"):
112 requested_tests = re.split('; | |, ', argument)
113 elif option in ("-l", "--log-dir"):
114 log_dir = argument
115 elif option in ("-k", "--key"):
116 filter_keys.append(argument)
117 elif option in ("-m", "--monitor"):
118 monitors.append(argument)
119 elif option in ("-c", "--cfg"):
120 cfg_file = argument
121 elif option in ("-h", "--hwsim"):
122 requested_hwsim_tests = re.split('; | |, ', argument)
123 elif option in ("-f", "--modules"):
124 requested_modules = re.split('; | |, ', argument)
125 else:
126 assert False, "unhandled option"
127
128 # get env configuration
129 setup_params = config.get_setup_params(cfg_file)
130 devices = config.get_devices(cfg_file)
131
132 # put logs in log_dir
133 symlink = os.path.join(log_dir, "current");
134 if os.path.exists(symlink):
135 os.unlink(symlink)
136 log_dir = os.path.join(log_dir, time.strftime("%Y_%m_%d_%H_%M_%S"))
137 if not os.path.exists(log_dir):
138 os.makedirs(log_dir)
139 os.symlink(os.path.join("../", log_dir), symlink)
140
141 # setup restart/trace/perf request
142 setup_params['local_log_dir'] = log_dir
143 setup_params['restart_device'] = restart
144 setup_params['trace'] = trace
145 setup_params['perf'] = perf
146
147 # configure logger
148 logger.setLevel(logging.DEBUG)
149
150 stdout_handler = logging.StreamHandler()
151 stdout_handler.setLevel(logging.WARNING)
152 if verbose:
153 stdout_handler.setLevel(logging.DEBUG)
154 logger.addHandler(stdout_handler)
155
156 formatter = logging.Formatter('%(asctime)s - %(message)s')
157 file_name = os.path.join(log_dir, 'run-tests.log')
158 log_handler = logging.FileHandler(file_name)
159 log_handler.setLevel(logging.DEBUG)
160 log_handler.setFormatter(formatter)
161 logger.addHandler(log_handler)
162
163 # import available tests
164 tests = []
165 failed = []
166 test_modules = []
167 files = os.listdir(scriptsdir)
168 for t in files:
169 m = re.match(r'(test_.*)\.py$', t)
170 if m:
171 mod = __import__(m.group(1))
172 test_modules.append(mod.__name__.replace('test_', '', 1))
173 for key, val in mod.__dict__.items():
174 if key.startswith("test_"):
175 tests.append(val)
176 test_names = list(set([t.__name__.replace('test_', '', 1) for t in tests]))
177
178 # import test_*
179 files = os.listdir("../hwsim/")
180 for t in files:
181 m = re.match(r'(test_.*)\.py$', t)
182 if m:
183 mod = __import__(m.group(1))
184 test_modules.append(mod.__name__.replace('test_', '', 1))
185 for key, val in mod.__dict__.items():
186 if key.startswith("test_"):
187 hwsim_tests.append(val)
188
189 # setup hwsim tests
190 hwsim_tests_to_run = []
191 if len(requested_hwsim_tests) > 0:
192 # apply filters
193 for filter_key in filter_keys:
194 filtered_tests = []
195 for hwsim_test in hwsim_tests:
196 if re.search(filter_key, hwsim_test.__name__):
197 filtered_tests.append(hwsim_test)
198 hwsim_tests = filtered_tests
199
200 # setup hwsim_test we should run
201 if requested_hwsim_tests[0] == "all":
202 hwsim_tests_to_run = hwsim_tests
203 elif requested_hwsim_tests[0] == "remote":
204 hwsim_tests_to_run = [t for t in hwsim_tests
205 if hasattr(t, "remote_compatible") and
206 t.remote_compatible]
207 else:
208 for test in requested_hwsim_tests:
209 t = None
210 for tt in hwsim_tests:
211 name = tt.__name__.replace('test_', '', 1)
212 if name == test:
213 t = tt
214 break
215 if not t:
216 logger.warning("hwsim test case: " + test + " NOT-FOUND")
217 continue
218 hwsim_tests_to_run.append(t)
219
220 # import test_* from modules
221 files = os.listdir("../hwsim/")
222 for t in files:
223 m = re.match(r'(test_.*)\.py$', t)
224 if m:
225 mod = __import__(m.group(1))
226 if mod.__name__.replace('test_', '', 1) not in requested_modules:
227 continue
228 for key, val in mod.__dict__.items():
229 if key.startswith("test_"):
230 modules_tests.append(val)
231
232 if len(requested_modules) > 0:
233 requested_hwsim_tests = modules_tests
234 hwsim_tests_to_run = modules_tests
235
236 # sort the list
237 test_names.sort()
238 tests.sort(key=lambda t: t.__name__)
239
240 # print help
241 if requested_tests[0] == "help" and len(requested_hwsim_tests) == 0:
242 usage()
243 print("\nAvailable Devices:")
244 for device in devices:
245 print("\t", device['name'])
246 print("\nAvailable tests:")
247 for test in test_names:
248 print("\t", test)
249 print("\nAvailable hwsim tests:")
250 for hwsim_test in hwsim_tests:
251 print("\t", hwsim_test.__name__.replace('test_', '', 1))
252 return
253
254 # show/check devices
255 if requested_tests[0] == "devices":
256 show_devices(devices, setup_params)
257 return
258
259 # apply filters
260 for filter_key in filter_keys:
261 filtered_tests = []
262 for test in tests:
263 if re.search(filter_key, test.__name__):
264 filtered_tests.append(test)
265 tests = filtered_tests
266
267 # setup test we should run
268 tests_to_run = []
269 if requested_tests[0] == "all":
270 tests_to_run = tests
271 if requested_tests[0] == "help":
272 pass
273 elif requested_tests[0] == "sanity":
274 for test in tests:
275 if test.__name__.startswith("test_sanity_"):
276 tests_to_run.append(test)
277 else:
278 for test in requested_tests:
279 t = None
280 for tt in tests:
281 name = tt.__name__.replace('test_', '', 1)
282 if name == test:
283 t = tt
284 break
285 if not t:
286 logger.warning("test case: " + test + " NOT-FOUND")
287 continue
288 tests_to_run.append(t)
289
290 if shuffle_tests:
291 shuffle(tests_to_run)
292 shuffle(hwsim_tests_to_run)
293
294 # lock devices
295 try:
296 get_devices(devices, duts, refs, monitors)
297 except Exception as e:
298 logger.warning("get devices failed: " + str(e))
299 logger.info(traceback.format_exc())
300 put_devices(devices, duts, refs, monitors)
301 return
302 except:
303 logger.warning("get devices failed")
304 logger.info(traceback.format_exc())
305 put_devices(devices, duts, refs, monitors)
306 return
307
308 # now run test cases
309 for dut in duts:
310 if len(requested_hwsim_tests) > 0:
311 logger.warning("DUT (apdev): " + str(dut))
312 else:
313 logger.warning("DUT: " + str(dut))
314 for ref in refs:
315 if len(requested_hwsim_tests) > 0:
316 logger.warning("REF (dev): " + str(ref))
317 else:
318 logger.warning("REF: " + str(ref))
319 for monitor in monitors:
320 logger.warning("MON: " + str(monitor))
321
322 # run check_devices at beginning
323 logger.warning("RUN check_devices")
324 try:
325 check_devices(devices, setup_params, refs, duts, monitors)
326 except Exception as e:
327 logger.warning("FAILED: " + str(e))
328 logger.info(traceback.format_exc())
329 put_devices(devices, duts, refs, monitors)
330 return
331 except:
332 logger.warning("FAILED")
333 logger.info(traceback.format_exc())
334 put_devices(devices, duts, refs, monitors)
335 return
336 logger.warning("PASS")
337
338 test_no = 1
339 for test in tests_to_run:
340 try:
341 start = datetime.now()
342 setup_params['tc_name'] = test.__name__.replace('test_', '', 1)
343 logger.warning("START - " + setup_params['tc_name'] + " (" + str(test_no) + "/" + str(len(tests_to_run)) + ")")
344 if test.__doc__:
345 logger.info("Test: " + test.__doc__)
346
347 # run tc
348 res = test(devices, setup_params, refs, duts, monitors)
349
350 end = datetime.now()
351 logger.warning("PASS (" + res + ") - " + str((end - start).total_seconds()) + "s")
352 except KeyboardInterrupt:
353 put_devices(devices, duts, refs, monitors)
354 raise
355 except TestSkip as e:
356 end = datetime.now()
357 logger.warning("SKIP (" + str(e) + ") - " + str((end - start).total_seconds()) + "s")
358 except Exception as e:
359 end = datetime.now()
360 logger.warning("FAILED (" + str(e) + ") - " + str((end - start).total_seconds()) + "s")
361 logger.info(traceback.format_exc())
362 failed.append(test.__name__.replace('test_', '', 1))
363 except:
364 end = datetime.now()
365 logger.warning("FAILED - " + str((end - start).total_seconds()) + "s")
366 logger.info(traceback.format_exc())
367 failed.append(test.__name__.replace('test_', '', 1))
368 test_no += 1
369
370 test_no = 1
371 for hwsim_test in hwsim_tests_to_run:
372 try:
373 start = datetime.now()
374 setup_params['tc_name'] = hwsim_test.__name__.replace('test_', '', 1)
375 logger.warning("START - " + setup_params['tc_name'] + " (" + str(test_no) + "/" + str(len(hwsim_tests_to_run)) + ")")
376 res = run_hwsim_test(devices, setup_params, refs, duts, monitors, hwsim_test)
377 end = datetime.now()
378 logger.warning("PASS (" + res + ") - " + str((end - start).total_seconds()) + "s")
379 except KeyboardInterrupt:
380 put_devices(devices, duts, refs, monitors)
381 raise
382 except HwsimSkip as e:
383 end = datetime.now()
384 logger.warning("SKIP (" + str(e) + ") - " + str((end - start).total_seconds()) + "s")
385 failed.append(hwsim_test.__name__.replace('test_', '', 1))
386 except Exception as e:
387 end = datetime.now()
388 logger.warning("FAILED (" + str(e) + ") - " + str((end - start).total_seconds()) + "s")
389 logger.info(traceback.format_exc())
390 failed.append(hwsim_test.__name__.replace('test_', '', 1))
391 except:
392 end = datetime.now()
393 logger.warning("FAILED - " + str((end - start).total_seconds()) + "s")
394 logger.info(traceback.format_exc())
395 failed.append(hwsim_test.__name__.replace('test_', '', 1))
396 test_no += 1
397
398 # unlock devices
399 put_devices(devices, duts, refs, monitors)
400
401 if len(failed) > 0:
402 logger.warning("Failed test cases:")
403 for test in failed:
404 logger.warning("\t" + test)
405
406
407if __name__ == "__main__":
408 main()