blob: 9a96aac8575288e69b456f8db7bcc849540cf818 [file] [log] [blame]
Chase Qi09edc7f2016-08-18 13:18:50 +08001#!/usr/bin/env python
2import argparse
3import csv
Milosz Wasilewski2fea70e2016-11-11 12:16:09 +00004import cmd
Chase Qi09edc7f2016-08-18 13:18:50 +08005import json
6import logging
7import os
Chase Qi09edc7f2016-08-18 13:18:50 +08008import re
9import shutil
Milosz Wasilewski970431b2016-11-25 14:10:08 +000010import subprocess
Chase Qi09edc7f2016-08-18 13:18:50 +080011import sys
12import time
Chase Qi09edc7f2016-08-18 13:18:50 +080013from uuid import uuid4
14
15
Chase Qifaf7d282016-08-29 19:34:01 +080016try:
17 import pexpect
18 import yaml
19except ImportError as e:
20 print(e)
21 print('Please run the below command to install modules required')
22 print('pip install -r ${REPO_PATH}/automated/utils/requirements.txt')
23 sys.exit(1)
24
25
Chase Qi09edc7f2016-08-18 13:18:50 +080026class TestPlan(object):
27 """
28 Analysis args specified, then generate test plan.
29 """
30
31 def __init__(self, args):
32 self.output = args.output
33 self.test_def = args.test_def
34 self.test_plan = args.test_plan
35 self.timeout = args.timeout
36 self.skip_install = args.skip_install
37 self.logger = logging.getLogger('RUNNER.TestPlan')
38
Milosz Wasilewski2fea70e2016-11-11 12:16:09 +000039 def test_list(self, kind="automated"):
Chase Qi09edc7f2016-08-18 13:18:50 +080040 if self.test_def:
41 if not os.path.exists(self.test_def):
42 self.logger.error(' %s NOT found, exiting...' % self.test_def)
43 sys.exit(1)
44
45 test_list = [{'path': self.test_def}]
46 test_list[0]['uuid'] = str(uuid4())
47 test_list[0]['timeout'] = self.timeout
48 test_list[0]['skip_install'] = self.skip_install
49 elif self.test_plan:
50 if not os.path.exists(self.test_plan):
51 self.logger.error(' %s NOT found, exiting...' % self.test_plan)
52 sys.exit(1)
53
54 with open(self.test_plan, 'r') as f:
55 test_plan = yaml.safe_load(f)
56 try:
Milosz Wasilewski2fea70e2016-11-11 12:16:09 +000057 test_list = []
58 for requirement in test_plan['requirements']:
59 if 'tests' in requirement.keys():
60 if requirement['tests'] and \
61 kind in requirement['tests'].keys() and \
62 requirement['tests'][kind]:
63 for test in requirement['tests'][kind]:
64 test_list.append(test)
Chase Qi09edc7f2016-08-18 13:18:50 +080065 for test in test_list:
66 test['uuid'] = str(uuid4())
67 except KeyError as e:
68 self.logger.error("%s is missing from test plan" % str(e))
69 sys.exit(1)
70 else:
71 self.logger.error('Plese specify a test or test plan.')
72 sys.exit(1)
73
74 return test_list
75
76
77class TestSetup(object):
78 """
79 Create directories required, then copy files needed to these directories.
80 """
81
82 def __init__(self, test, args):
83 self.output = os.path.realpath(args.output)
84 self.test_name = os.path.splitext(test['path'].split('/')[-1])[0]
Milosz Wasilewski2fea70e2016-11-11 12:16:09 +000085 self.repo_test_path = test['path']
Chase Qi09edc7f2016-08-18 13:18:50 +080086 self.uuid = test['uuid']
87 self.test_uuid = self.test_name + '_' + self.uuid
88 self.test_path = os.path.join(self.output, self.test_uuid)
89 self.logger = logging.getLogger('RUNNER.TestSetup')
Milosz Wasilewski2fea70e2016-11-11 12:16:09 +000090 self.test_kind = args.kind
Milosz Wasilewski970431b2016-11-25 14:10:08 +000091 self.test_version = test.get('version', None)
Chase Qi09edc7f2016-08-18 13:18:50 +080092
93 def validate_env(self):
94 # Inspect if environment set properly.
95 try:
96 self.repo_path = os.environ['REPO_PATH']
97 except KeyError:
98 self.logger.error('KeyError: REPO_PATH')
99 self.logger.error("Please run '. ./bin/setenv.sh' to setup test environment")
100 sys.exit(1)
101
102 def create_dir(self):
103 if not os.path.exists(self.output):
104 os.makedirs(self.output)
105 self.logger.info('Output directory created: %s' % self.output)
106
107 def copy_test_repo(self):
108 self.validate_env()
109 shutil.rmtree(self.test_path, ignore_errors=True)
Chase Qi33eb7652016-12-02 10:43:46 +0800110 if self.repo_path in self.test_path:
111 self.logger.error("Cannot copy repository into itself. Please choose output directory outside repository path")
112 sys.exit(1)
113 shutil.copytree(self.repo_path, self.test_path, symlinks=True)
114 self.logger.info('Test repo copied to: %s' % self.test_path)
Chase Qi09edc7f2016-08-18 13:18:50 +0800115
Milosz Wasilewski970431b2016-11-25 14:10:08 +0000116 def checkout_version(self):
117 if self.test_version:
118 path = os.getcwd()
119 os.chdir(self.test_path)
120 subprocess.call("git checkout %s" % self.test_version, shell=True)
121 os.chdir(path)
122
Chase Qi09edc7f2016-08-18 13:18:50 +0800123 def create_uuid_file(self):
124 with open('%s/uuid' % self.test_path, 'w') as f:
125 f.write(self.uuid)
126
127
128class TestDefinition(object):
129 """
130 Convert test definition to testdef.yaml, testdef_metadata and run.sh.
131 """
132
133 def __init__(self, test, args):
Milosz Wasilewski2fea70e2016-11-11 12:16:09 +0000134 self.test = test
135 self.args = args
Chase Qi09edc7f2016-08-18 13:18:50 +0800136 self.output = os.path.realpath(args.output)
137 self.test_def = test['path']
138 self.test_name = os.path.splitext(self.test_def.split('/')[-1])[0]
139 self.test_uuid = self.test_name + '_' + test['uuid']
140 self.test_path = os.path.join(self.output, self.test_uuid)
141 self.logger = logging.getLogger('RUNNER.TestDef')
142 self.skip_install = args.skip_install
Milosz Wasilewski2fea70e2016-11-11 12:16:09 +0000143 self.is_manual = False
Chase Qi09edc7f2016-08-18 13:18:50 +0800144 if 'skip_install' in test:
145 self.skip_install = test['skip_install']
146 self.custom_params = None
147 if 'parameters' in test:
148 self.custom_params = test['parameters']
149 if 'params' in test:
150 self.custom_params = test['params']
Milosz Wasilewski2fea70e2016-11-11 12:16:09 +0000151 self.exists = False
152 if os.path.isfile(self.test_def):
153 self.exists = True
154 with open(self.test_def, 'r') as f:
155 self.testdef = yaml.safe_load(f)
156 if self.testdef['metadata']['format'].startswith("Manual Test Definition"):
157 self.is_manual = True
Chase Qi09edc7f2016-08-18 13:18:50 +0800158
159 def definition(self):
160 with open('%s/testdef.yaml' % self.test_path, 'w') as f:
161 f.write(yaml.dump(self.testdef, encoding='utf-8', allow_unicode=True))
162
163 def metadata(self):
164 with open('%s/testdef_metadata' % self.test_path, 'w') as f:
165 f.write(yaml.dump(self.testdef['metadata'], encoding='utf-8', allow_unicode=True))
166
167 def run(self):
Milosz Wasilewski2fea70e2016-11-11 12:16:09 +0000168 if not self.is_manual:
169 with open('%s/run.sh' % self.test_path, 'a') as f:
170 f.write('#!/bin/sh\n')
Chase Qi09edc7f2016-08-18 13:18:50 +0800171
Milosz Wasilewski2fea70e2016-11-11 12:16:09 +0000172 self.parameters = self.handle_parameters()
173 if self.parameters:
174 for line in self.parameters:
175 f.write(line)
Chase Qi09edc7f2016-08-18 13:18:50 +0800176
Milosz Wasilewski2fea70e2016-11-11 12:16:09 +0000177 f.write('set -e\n')
178 f.write('export TESTRUN_ID=%s\n' % self.testdef['metadata']['name'])
179 f.write('cd %s\n' % self.test_path)
180 f.write('UUID=`cat uuid`\n')
181 f.write('echo "<STARTRUN $TESTRUN_ID $UUID>"\n')
182 steps = self.testdef['run'].get('steps', [])
183 if steps:
184 for cmd in steps:
185 if '--cmd' in cmd or '--shell' in cmd:
186 cmd = re.sub(r'\$(\d+)\b', r'\\$\1', cmd)
187 f.write('%s\n' % cmd)
188 f.write('echo "<ENDRUN $TESTRUN_ID $UUID>"\n')
Chase Qi09edc7f2016-08-18 13:18:50 +0800189
Milosz Wasilewski2fea70e2016-11-11 12:16:09 +0000190 os.chmod('%s/run.sh' % self.test_path, 0755)
191
192 def get_test_run(self):
193 if self.is_manual:
194 return ManualTestRun(self.test, self.args)
195 return AutomatedTestRun(self.test, self.args)
Chase Qi09edc7f2016-08-18 13:18:50 +0800196
197 def handle_parameters(self):
198 ret_val = ['###default parameters from test definition###\n']
199
200 if 'params' in self.testdef:
201 for def_param_name, def_param_value in list(self.testdef['params'].items()):
202 # ?'yaml_line'
203 if def_param_name is 'yaml_line':
204 continue
205 ret_val.append('%s=\'%s\'\n' % (def_param_name, def_param_value))
206 elif 'parameters' in self.testdef:
207 for def_param_name, def_param_value in list(self.testdef['parameters'].items()):
208 if def_param_name is 'yaml_line':
209 continue
210 ret_val.append('%s=\'%s\'\n' % (def_param_name, def_param_value))
211 else:
212 return None
213
214 ret_val.append('######\n')
215
216 ret_val.append('###custom parameters from test plan###\n')
217 if self.custom_params:
218 for param_name, param_value in list(self.custom_params.items()):
219 if param_name is 'yaml_line':
220 continue
221 ret_val.append('%s=\'%s\'\n' % (param_name, param_value))
222
223 if self.skip_install:
224 ret_val.append('SKIP_INSTALL="True"\n')
225 ret_val.append('######\n')
226
227 return ret_val
228
229
230class TestRun(object):
231 def __init__(self, test, args):
232 self.output = os.path.realpath(args.output)
233 self.test_name = os.path.splitext(test['path'].split('/')[-1])[0]
234 self.test_uuid = self.test_name + '_' + test['uuid']
235 self.test_path = os.path.join(self.output, self.test_uuid)
Milosz Wasilewski2fea70e2016-11-11 12:16:09 +0000236 self.logger = logging.getLogger('RUNNER.TestRun')
Chase Qi09edc7f2016-08-18 13:18:50 +0800237 self.test_timeout = args.timeout
238 if 'timeout' in test:
239 self.test_timeout = test['timeout']
Milosz Wasilewski2fea70e2016-11-11 12:16:09 +0000240
241 def run(self):
242 raise NotImplementedError
243
244 def check_result(self):
245 raise NotImplementedError
246
247
248class AutomatedTestRun(TestRun):
249 def run(self):
Chase Qi09edc7f2016-08-18 13:18:50 +0800250 self.logger.info('Executing %s/run.sh' % self.test_path)
251 shell_cmd = '%s/run.sh 2>&1 | tee %s/stdout.log' % (self.test_path, self.test_path)
252 self.child = pexpect.spawn('/bin/sh', ['-c', shell_cmd])
253
Milosz Wasilewski2fea70e2016-11-11 12:16:09 +0000254 def check_result(self):
Chase Qi09edc7f2016-08-18 13:18:50 +0800255 if self.test_timeout:
256 self.logger.info('Test timeout: %s' % self.test_timeout)
257 test_end = time.time() + self.test_timeout
258
259 while self.child.isalive():
260 if self.test_timeout and time.time() > test_end:
261 self.logger.warning('%s test timed out, killing test process...' % self.test_uuid)
262 self.child.terminate(force=True)
263 break
264 try:
265 self.child.expect('\r\n')
266 print(self.child.before)
267 except pexpect.TIMEOUT:
268 continue
269 except pexpect.EOF:
270 self.logger.info('%s test finished.\n' % self.test_uuid)
271 break
272
273
Milosz Wasilewski2fea70e2016-11-11 12:16:09 +0000274class ManualTestShell(cmd.Cmd):
275 def __init__(self, test_dict, result_path):
276 cmd.Cmd.__init__(self)
277 self.test_dict = test_dict
278 self.result_path = result_path
279 self.current_step_index = 0
280 self.steps = self.test_dict['run']['steps']
281 self.expected = self.test_dict['run']['expected']
282 self.prompt = "%s > " % self.test_dict['metadata']['name']
283 self.result = None
284 self.intro = """
285 Welcome to manual test executor. Type 'help' for available commands.
286 This shell is meant to be executed on your computer, not on the system
287 under test. Please execute the steps from the test case, compare to
288 expected result and record the test result as 'pass' or 'fail'. If there
289 is an issue that prevents from executing the step, please record the result
290 as 'skip'.
291 """
292
293 def do_quit(self, line):
294 """
295 Exit test execution
296 """
297 if self.result is not None:
298 return True
299 if line.find("-f") >= 0:
300 self._record_result("skip")
301 return True
302 print "Test result not recorded. Use -f to force. Forced quit records result as 'skip'"
303
304 do_EOF = do_quit
305
306 def do_description(self, line):
307 """
308 Prints current test overall description
309 """
310 print self.test_dict['metadata']['description']
311
312 def do_steps(self, line):
313 """
314 Prints all steps of the current test case
315 """
316 for index, step in enumerate(self.steps):
317 print "%s. %s" % (index, step)
318
319 def do_expected(self, line):
320 """
321 Prints all expected results of the current test case
322 """
323 for index, expected in enumerate(self.expected):
324 print "%s. %s" % (index, expected)
325
326 def do_current(self, line):
327 """
328 Prints current test step
329 """
330 self._print_step()
331
332 do_start = do_current
333
334 def do_next(self, line):
335 """
336 Prints next test step
337 """
338 if len(self.steps) > self.current_step_index + 1:
339 self.current_step_index += 1
340 self._print_step()
341
342 def _print_step(self):
343 print "%s. %s" % (self.current_step_index, self.steps[self.current_step_index])
344
345 def _record_result(self, result):
346 print "Recording %s in %s/stdout.log" % (result, self.result_path)
347 with open("%s/stdout.log" % self.result_path, "a") as f:
348 f.write("<LAVA_SIGNAL_TESTCASE TEST_CASE_ID=%s RESULT=%s>" %
349 (self.test_dict['metadata']['name'], result))
350
351 def do_pass(self, line):
352 """
353 Records PASS as test result
354 """
355 self.result = "pass"
356 self._record_result(self.result)
357 return True
358
359 def do_fail(self, line):
360 """
361 Records FAIL as test result
362 """
363 self.result = "fail"
364 self._record_result(self.result)
365 return True
366
367 def do_skip(self, line):
368 """
369 Records SKIP as test result
370 """
371 self.result = "skip"
372 self._record_result(self.result)
373 return True
374
375
376class ManualTestRun(TestRun, cmd.Cmd):
377 def run(self):
378 print self.test_name
379 with open('%s/testdef.yaml' % self.test_path, 'r') as f:
380 self.testdef = yaml.safe_load(f)
381
382 ManualTestShell(self.testdef, self.test_path).cmdloop()
383
384 def check_result(self):
385 pass
386
387
Chase Qi09edc7f2016-08-18 13:18:50 +0800388class ResultParser(object):
389 def __init__(self, test, args):
390 self.output = os.path.realpath(args.output)
391 self.test_name = os.path.splitext(test['path'].split('/')[-1])[0]
392 self.test_uuid = self.test_name + '_' + test['uuid']
393 self.result_path = os.path.join(self.output, self.test_uuid)
394 self.metrics = []
395 self.results = {}
396 self.results['test'] = self.test_name
397 self.results['id'] = self.test_uuid
398 self.logger = logging.getLogger('RUNNER.ResultParser')
Milosz Wasilewskia76e8dd2016-11-25 14:13:25 +0000399 self.results['params'] = {}
400 with open(os.path.join(self.result_path, "testdef.yaml"), "r") as f:
401 self.testdef = yaml.safe_load(f)
Chase Qi0d75a6b2016-11-29 23:43:54 +0800402 self.results['name'] = ""
403 if 'metadata' in self.testdef.keys() and \
404 'name' in self.testdef['metadata'].keys():
405 self.results['name'] = self.testdef['metadata']['name']
Milosz Wasilewskia76e8dd2016-11-25 14:13:25 +0000406 if 'params' in self.testdef.keys():
407 self.results['params'] = self.testdef['params']
Chase Qiae88be32016-11-23 20:32:21 +0800408 if 'parameters' in test.keys():
Milosz Wasilewskia76e8dd2016-11-25 14:13:25 +0000409 self.results['params'].update(test['parameters'])
Chase Qiae88be32016-11-23 20:32:21 +0800410 if 'params' in test.keys():
Milosz Wasilewskia76e8dd2016-11-25 14:13:25 +0000411 self.results['params'].update(test['params'])
Milosz Wasilewski970431b2016-11-25 14:10:08 +0000412 if 'version' in test.keys():
413 self.results['version'] = test['version']
414 else:
415 path = os.getcwd()
416 os.chdir(self.result_path)
417 test_version = subprocess.check_output("git rev-parse HEAD", shell=True)
418 self.results['version'] = test_version.rstrip()
419 os.chdir(path)
Chase Qi09edc7f2016-08-18 13:18:50 +0800420
421 def run(self):
422 self.parse_stdout()
423 self.dict_to_json()
424 self.dict_to_csv()
425 self.logger.info('Result files saved to: %s' % self.result_path)
426 print('--- Printing result.csv ---')
427 with open('%s/result.csv' % self.result_path) as f:
428 print(f.read())
429
430 def parse_stdout(self):
431 with open('%s/stdout.log' % self.result_path, 'r') as f:
Milosz Wasilewski5a4dd442016-12-07 15:01:57 +0000432 test_case_re = re.compile("TEST_CASE_ID=(.*)")
433 result_re = re.compile("RESULT=(.*)")
434 measurement_re = re.compile("MEASUREMENT=(.*)")
435 units_re = re.compile("UNITS=(.*)")
Chase Qi09edc7f2016-08-18 13:18:50 +0800436 for line in f:
437 if re.match(r'\<(|LAVA_SIGNAL_TESTCASE )TEST_CASE_ID=.*', line):
438 line = line.strip('\n').strip('<>').split(' ')
439 data = {'test_case_id': '',
440 'result': '',
441 'measurement': '',
442 'units': ''}
443
444 for string in line:
Milosz Wasilewskiff695622016-12-05 16:00:06 +0000445 test_case_match = test_case_re.match(string)
446 result_match = result_re.match(string)
447 measurement_match = measurement_re.match(string)
448 units_match = units_re.match(string)
449 if test_case_match:
Milosz Wasilewski5a4dd442016-12-07 15:01:57 +0000450 data['test_case_id'] = test_case_match.group(1)
Milosz Wasilewskiff695622016-12-05 16:00:06 +0000451 if result_match:
Milosz Wasilewski5a4dd442016-12-07 15:01:57 +0000452 data['result'] = result_match.group(1)
Milosz Wasilewskiff695622016-12-05 16:00:06 +0000453 if measurement_match:
Milosz Wasilewski5a4dd442016-12-07 15:01:57 +0000454 data['measurement'] = measurement_match.group(1)
Milosz Wasilewskiff695622016-12-05 16:00:06 +0000455 if units_match:
Milosz Wasilewski5a4dd442016-12-07 15:01:57 +0000456 data['units'] = units_match.group(1)
Chase Qi09edc7f2016-08-18 13:18:50 +0800457
458 self.metrics.append(data.copy())
459
460 self.results['metrics'] = self.metrics
461
462 def dict_to_json(self):
Chase Qi87f4f402016-11-07 15:32:01 +0800463 # Save test results to output/test_id/result.json
Chase Qi09edc7f2016-08-18 13:18:50 +0800464 with open('%s/result.json' % self.result_path, 'w') as f:
Chase Qi87f4f402016-11-07 15:32:01 +0800465 json.dump([self.results], f, indent=4)
466
467 # Collect test results of all tests in output/result.json
468 feeds = []
469 if os.path.isfile('%s/result.json' % self.output):
470 with open('%s/result.json' % self.output, 'r') as f:
471 feeds = json.load(f)
472
473 feeds.append(self.results)
474 with open('%s/result.json' % self.output, 'w') as f:
475 json.dump(feeds, f, indent=4)
Chase Qi09edc7f2016-08-18 13:18:50 +0800476
477 def dict_to_csv(self):
Chase Qica15cf52016-11-10 17:00:22 +0800478 # Convert dict self.results['params'] to a string.
479 test_params = ''
480 if self.results['params']:
481 params_dict = self.results['params']
482 test_params = ';'.join(['%s=%s' % (k, v) for k, v in params_dict.iteritems()])
Chase Qi09edc7f2016-08-18 13:18:50 +0800483
Chase Qica15cf52016-11-10 17:00:22 +0800484 for metric in self.results['metrics']:
Chase Qi0d75a6b2016-11-29 23:43:54 +0800485 metric['name'] = self.results['name']
Chase Qica15cf52016-11-10 17:00:22 +0800486 metric['test_params'] = test_params
487
488 # Save test results to output/test_id/result.csv
Chase Qi0d75a6b2016-11-29 23:43:54 +0800489 fieldnames = ['name', 'test_case_id', 'result', 'measurement', 'units', 'test_params']
Chase Qica15cf52016-11-10 17:00:22 +0800490 with open('%s/result.csv' % self.result_path, 'w') as f:
491 writer = csv.DictWriter(f, fieldnames=fieldnames)
Chase Qi09edc7f2016-08-18 13:18:50 +0800492 writer.writeheader()
493 for metric in self.results['metrics']:
494 writer.writerow(metric)
495
Chase Qi87f4f402016-11-07 15:32:01 +0800496 # Collect test results of all tests in output/result.csv
497 if not os.path.isfile('%s/result.csv' % self.output):
498 with open('%s/result.csv' % self.output, 'w') as f:
Chase Qi87f4f402016-11-07 15:32:01 +0800499 writer = csv.DictWriter(f, fieldnames=fieldnames)
500 writer.writeheader()
501
Chase Qi09edc7f2016-08-18 13:18:50 +0800502 with open('%s/result.csv' % self.output, 'a') as f:
503 writer = csv.DictWriter(f, fieldnames=fieldnames)
Chase Qi09edc7f2016-08-18 13:18:50 +0800504 for metric in self.results['metrics']:
Chase Qi09edc7f2016-08-18 13:18:50 +0800505 writer.writerow(metric)
506
507
508def get_args():
509 parser = argparse.ArgumentParser()
510 parser.add_argument('-o', '--output', default='/root/output', dest='output',
511 help='''
512 specify a directory to store test and result files.
513 Default: /root/output
514 ''')
515 parser.add_argument('-p', '--test_plan', default=None, dest='test_plan',
516 help='''
517 specify an test plan file which has tests and related
518 params listed in yaml format.
519 ''')
520 parser.add_argument('-d', '--test_def', default=None, dest='test_def',
521 help='''
522 base on test definition repo location, specify relative
523 path to the test definition to run.
524 Format example: "ubuntu/smoke-tests-basic.yaml"
525 ''')
Milosz Wasilewski2fea70e2016-11-11 12:16:09 +0000526 parser.add_argument('-k', '--kind', default="automated", dest='kind',
527 choices=['automated', 'manual'],
528 help='''
529 Selects type of tests to be executed from the test plan.
530 Possible options: automated, manual
531 '''),
Chase Qi09edc7f2016-08-18 13:18:50 +0800532 parser.add_argument('-t', '--timeout', type=int, default=None,
533 dest='timeout', help='Specify test timeout')
534 parser.add_argument('-s', '--skip_install', dest='skip_install',
535 default=False, action='store_true',
536 help='skip install section defined in test definition.')
537 args = parser.parse_args()
538 return args
539
540
541def main():
542 # Setup logger.
543 logger = logging.getLogger('RUNNER')
544 logger.setLevel(logging.DEBUG)
545 ch = logging.StreamHandler()
546 ch.setLevel(logging.DEBUG)
547 formatter = logging.Formatter('%(asctime)s - %(name)s: %(levelname)s: %(message)s')
548 ch.setFormatter(formatter)
549 logger.addHandler(ch)
550
Milosz Wasilewski2fea70e2016-11-11 12:16:09 +0000551 args = get_args()
552 if args.kind != "manual":
553 if os.geteuid() != 0:
554 logger.error("Sorry, you need to run this as root")
555 sys.exit(1)
Chase Qi09edc7f2016-08-18 13:18:50 +0800556
557 # Generate test plan.
Chase Qi09edc7f2016-08-18 13:18:50 +0800558 test_plan = TestPlan(args)
Milosz Wasilewski2fea70e2016-11-11 12:16:09 +0000559 test_list = test_plan.test_list(args.kind)
Chase Qi09edc7f2016-08-18 13:18:50 +0800560 logger.info('Tests to run:')
561 for test in test_list:
562 print(test)
563
564 # Run tests.
565 for test in test_list:
566 # Create directories and copy files needed.
567 setup = TestSetup(test, args)
568 setup.create_dir()
569 setup.copy_test_repo()
Milosz Wasilewski970431b2016-11-25 14:10:08 +0000570 setup.checkout_version()
Chase Qi09edc7f2016-08-18 13:18:50 +0800571 setup.create_uuid_file()
572
573 # Convert test definition.
574 test_def = TestDefinition(test, args)
Milosz Wasilewski2fea70e2016-11-11 12:16:09 +0000575 if test_def.exists:
576 test_def.definition()
577 test_def.metadata()
578 test_def.run()
Chase Qi09edc7f2016-08-18 13:18:50 +0800579
Milosz Wasilewski2fea70e2016-11-11 12:16:09 +0000580 # Run test.
581 test_run = test_def.get_test_run()
582 test_run.run()
583 test_run.check_result()
Chase Qi09edc7f2016-08-18 13:18:50 +0800584
Milosz Wasilewski2fea70e2016-11-11 12:16:09 +0000585 # Parse test output, save results in json and csv format.
586 result_parser = ResultParser(test, args)
587 result_parser.run()
588 else:
589 logger.warning("Requested test definition %s doesn't exist" % test['path'])
Chase Qi09edc7f2016-08-18 13:18:50 +0800590
591if __name__ == "__main__":
592 main()