1 import argparse
2 import csv
3 import datetime
4 import json
5 import os.path
6 import subprocess
7 import sys
8 import time
9 from loguru import logger
10 import psutil
11
12 def set_arg_parser():
13 parser = argparse.ArgumentParser()
14 parser.add_argument("-c", "--case_config", dest="case_config", default="./default_case.json", type=str,
15 help="JSON path to run")
16 return parser.parse_args()
17
18 def get_case_config_info(config_file: str):
19 if not config_file.endswith(".json"):
20 error_msg = f"Invalid JSON campaign: {config_file}"
21 logger.error(error_msg)
22 raise Exception(error_msg)
23 if not os.path.exists(config_file):
24 error_msg = f"Not found this campaign file in system: {config_file}"
25 logger.error(error_msg)
26 raise Exception(error_msg)
27 with open(config_file, 'r') as c_f:
28 campaign_data = json.load(c_f)
29 if campaign_data:
30 return campaign_data
31 else:
32 error_msg = f"Empty campaign file:{config_file}"
33 logger.error(error_msg)
34 raise Exception(error_msg)
35
36 def create_log_folder():
37 ROOT_LOG_FOLDER = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'logs')
38 log_folder_name = "Stability_Test_" + f'{time.strftime("%Y_%m_%d_%H_%M_%S")}'
39 log_folder_path = os.path.join(ROOT_LOG_FOLDER, log_folder_name)
40
41 if not os.path.exists(log_folder_path):
42 os.makedirs(log_folder_path)
43 os.environ['CASE_LOG_FOLDER'] = log_folder_path
44 return log_folder_path
45
46 @logger.catch
47 def write_cycle_result(tc_result, csv_dir, filename):
48 if not csv_dir:
49 error_msg = "csv folder is empty when update result csv"
50 logger.error(error_msg)
51 raise Exception(error_msg)
52 try:
53 csv_path = os.path.join(csv_dir, f"{filename}_result.csv")
54 # logger.info(csv_path)
55 with open(csv_path, 'a+', newline='') as csvfile:
56 ret_writer = csv.writer(csvfile, dialect='excel')
57 ret_writer.writerow(tc_result)
58 except Exception as e:
59 error_msg = f"Write case result csv got exception: {e}"
60 raise Exception(error_msg)
61
62 def kill(proc_pid):
63 process = psutil.Process(proc_pid)
64 for proc in process.children(recursive=True):
65 proc.kill()
66 process.kill()
67
68 if __name__ == '__main__':
69 logger.info('============================================================================================')
70 logger.info('===================== Start SOS and Android VM Stability Test Case =========================')
71 logger.info('============================================================================================')
72
73 args = set_arg_parser()
74 logger.info(f"use config file: {args.case_config}")
75 config = get_case_config_info(args.case_config)
76 log_folder_path = create_log_folder()
77 all_cases = config[0]['testcases']
78
79 for index, case in enumerate(all_cases):
80 if case['case_enabling'] == "enable":
81 case_name = case['case_name'][0].upper()+case['case_name'][1:]
82 debug_mode = case['debug_mode']
83
84 for num in range(case['cycle_number']):
85 cycle_result = {}
86 start_time = datetime.datetime.now().astimezone()
87 case_log_path = os.path.join(log_folder_path+f"/{case_name}", f'Cycle_{num+1}_{time.strftime("%Y_%m_%d_%H_%M_%S")}')
88 if not os.path.exists(case_log_path):
89 os.makedirs(case_log_path)
90 os.environ["CASE_LOG_FOLDER"] = case_log_path
91 cmd =case['case_cmd'] + f' --debug_mode {debug_mode}'
92 logger.info(f'Test Cycle {num+1}: {cmd}')
93 try:
94 process = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
95 process.wait(timeout=15*60) # Force terminate process when time > 10 minutes, this may be blocked
96 returncode = process.returncode
97 except subprocess.TimeoutExpired:
98 returncode = process.returncode
99 logger.warning(f'exec {cmd} TimeoutExpired, return code: {returncode}, now force kill this cycle process')
100 kill(process.pid)
101 cycle_result['result'] = 'Test failed as subprocess exec timeout'
102 if debug_mode=='on' and (returncode==1 or returncode is None):
103 logger.debug(f"debug mode: {debug_mode}, stop test now and keep issue scene")
104 sys.exit(0)
105 result = []
106 csv_header = []
107 csv_header.append('cycle_id')
108 result.append(num+1)
109 try:
110 with open(f'{case_log_path}/cycle_result.json') as json_file:
111 cycle_result = json.load(json_file)
112 except Exception as e:
113 process.terminate()
114 logger.error(e.args)
115 cycle_result['result_file'] = 'No result file generated'
116
117 vm_id=''
118 if 'vm_id' in cycle_result:
119 vm_id = cycle_result['vm_id']
120 for key in cycle_result:
121 if num==0:
122 csv_header.append(key)
123 result.append(cycle_result[key])
124 if num==0:
125 csv_header.append("cycle_duration")
126 csv_header.append("log_path")
127 write_cycle_result(csv_header, log_folder_path, f'{vm_id}_{case_name}')
128 cycle_duration = datetime.datetime.now().astimezone() - start_time
129 result.append(cycle_duration)
130 result.append(case_log_path)
131 logger.info(f'{vm_id} Test Cycle {num+1} Done, Cost: {cycle_duration}')
132
133 write_cycle_result(result, log_folder_path, f'{vm_id}_{case_name}')