class Program(object): def __init__(self): self.bus_client = None self.case_name = "" def _start_bus(self, local=True): ''' _start_bus : start bus server with default config :param local: bool, default is True :return: None ''' if local: return elif self.args.bus_server_port: self.bus_server = BusServer(self.args.bus_server_port) else: self.bus_server = BusServer() self.bus_server.start() time.sleep(0.5) def _start_loader(self, count: int, bus_client: BusClient): ''' _start_loader : start loader (count) :param count: loader count :param bus_client: bus client -> BusClient (connect to bus server) :return: None ''' for x in range(count): loader = Loader(bus_client, self.loader_recorder_lock, self.args) loader.start() def _start_runner(self, count: int, log_dir: str, bus_client: BusClient): ''' _start_runner : start runner (count) :param count: runner count :param log_dir: log :return: ''' for x in range(count): runner = Runner(log_dir, bus_client, self.multi_process_locks, self.args) runner.start() def _start_recorder(self, bus_client: BusClient, count: int = 1, log_dir: str = "", time_str: str = ""): ''' start recorder :param bus_client: :param count: :param log_dir: :param time_str: :return: ''' recorder = Recorder(bus_client, count, self.case_name, time_str, log_dir, self.args.report_template, self.loader_recorder_lock, self.args) recorder.start() def _init_logging_module(self, args): ''' init logging module :param args: :return: ''' logging.basicConfig(level=logging.DEBUG if not args.debug else logging.DEBUG, format='%(asctime)s %(levelname)s %(message)s') pass def _init_system_logger(self, log_dir: str, bus_client: BusClient): ''' init system logger :param log_dir: :param bus_client: :return: ''' log = Logger(self.case_name, self.time_str, log_dir, bus_client, self.args) log.start() def _init_system_lock(self, args): ''' generate some locker :param args: :return: ''' self.loader_recorder_lock = m_lock() self.multi_process_locks = [m_lock() for x in range(4)] if self.bus_client.get_case_count().empty(): self.bus_client.get_case_count().put(0) def _bus_client(self, args): ''' init bus client :param args: :return: ''' if isinstance(args.bus_server, list): self.bus_client = BusClient(args.bus_server[1], args.bus_server[2], args.bus_server[0]) elif args.bus_server_port: self.bus_client = BusClient(None, args.bus_server_port, None) else: self.bus_client = BusClient() self.params_loader = self.bus_client.get_param() def start_main(self): self.params_loader.put(Signal("main", SIGNAL_START)) def stop_main(self): self.params_loader.put(Signal("main", SIGNAL_STOP)) def put_loader_msg(self, args): if args.case: for arg in args.case: self.params_loader.put({"file_name": arg}) def _start_web_server(self, args): plugin_manager.start_web_server(args, self.bus_client) def run(self, args): try: self.args = args self._init_logging_module(args) self.case_name = self.args.name self.time_str = Utils.get_time_str() self.case_log_dir = f"{args.log_dir}/{self.case_name}/{self.time_str}" self.runner_count = args.runner_count if args.runner_count else 1 self.only_bus(args) self._start_bus(local=args.bus_server if args.bus_server else False) self._bus_client(args) self._init_system_lock(args) # this only in server bus if not args.bus_server: self._init_system_logger(args.log_dir, self.bus_client) # only : module if args.only_loader: self._start_loader(1, self.bus_client) elif args.only_runner: self._start_runner(self.runner_count, self.case_log_dir, self.bus_client) elif args.only_recorder: self._start_recorder(self.bus_client, self.runner_count, self.case_log_dir, self.time_str) else: self._start_loader(1, self.bus_client) self._start_runner(self.runner_count, self.case_log_dir, self.bus_client) self._start_recorder(self.bus_client, self.runner_count, self.case_log_dir, self.time_str) self.start_main() self.put_loader_msg(args) self.stop_main() self._start_web_server(args) self.wait_end_signal(args) except KeyboardInterrupt as key_inter: logger.error(key_inter) except FailLoaderException as loader_inter: logger.error(loader_inter) except FailRecorderException as recorder_inter: logger.error(recorder_inter) except FailRunnerException as runner_inter: logger.error(runner_inter) except FailFrameworkException as frame_inter: logger.error(frame_inter) def only_bus(self, args): if args.only_bus: self._start_bus(local=args.bus_server if args.bus_server else False) self._bus_client(args) self._init_system_lock(args) self._init_system_logger(args.log_dir, self.bus_client) self._start_recorder(self.bus_client, self.runner_count, self.case_log_dir, self.time_str) self.wait_end_signal(args) sys.exit(0) else: logger.debug("not only bus mode") def only_loader(self, args): if args.only_loader: pass def wait_end_signal(self, args): try: time.sleep(2) system_signal = self.bus_client.get_system() while True: if not args.console: if not system_signal.empty(): self.signal = system_signal.get() signal = self.signal.signal if isinstance(self.signal, Signal) else None logger.info(f"program signal {SIGNAL_GROUP.get(signal) if signal in [x for x in range(20, 30)] else None}") # check the end signal from recorder to main if signal == SIGNAL_RECORD_END or signal == SIGNAL_STOP: if not args.local_logger: while True: if not system_signal.empty(): signal_logger = system_signal.get() signal_logger = signal_logger.signal if isinstance(signal_logger, Signal) else None logger.info(f"program signal {SIGNAL_GROUP.get(signal_logger) if signal_logger in [x for x in range(20, 30)] else None}") # check the logger signal from logger to main if signal_logger == SIGNAL_LOGGER_END: logger.info("main -- stop") system_signal.put(Signal("main", SIGNAL_RECORD_END)) system_signal.put(Signal("main", SIGNAL_LOGGER_END)) break # if use local logger, just end the main program else: logger.info("main -- stop") system_signal.put(Signal("main", SIGNAL_RECORD_END)) system_signal.put(Signal("main", SIGNAL_LOGGER_END)) break time.sleep(0.1) else: cmd = input(f"haf-{PLATFORM_VERSION}# ") if self._run_cmd(cmd): break if args.only_bus: logger.info("main - wait for other process end !") time.sleep(3) time.sleep(0.1) except KeyboardInterrupt as key_inter: self.params_loader.put(Signal("main", SIGNAL_STOP)) # TODO: Here need CMDER to support cmd command ... def _run_cmd(self, cmd): if cmd == "rerun" or cmd == "r": result = self._rerun() elif cmd == "version" or cmd == "v": result = self._version() elif cmd == "help" or cmd == "h": result = self._help() elif cmd == "name" or cmd == "n": result = self._case_name() elif cmd == "exit" or cmd == "e": result = self._exit() elif cmd == "summary" or cmd == "s": result = self._summary() else: print("unsupported command!") result = self._help() return result def _rerun(self): case_handler = self.bus_client.get_case() while not case_handler.empty(): case_handler.get() self._start_runner(self.args.runner_count if self.args.runner_count else 1, self.case_log_dir, self.bus_client) self._start_loader(1, self.bus_client) self._start_recorder(self.bus_client, self.runner_count, self.case_log_dir, self.time_str) self.start_main() self.put_loader_msg(self.args) self.stop_main() return False def _version(self): print(BANNER_STRS) return False def _help(self): help = f""" haf-{PLATFORM_VERSION}# # rerun / r rerun the input cases # version / v version of haf # help / h help information # name / n case name of this test # summary / s summary of this test # exit / e exit """ print(help) return False def _summary(self): result_main = self.bus_client.get_case_result_main() if not result_main.empty(): results = result_main.get() if isinstance(results, EndResult): self.results = results if hasattr(self, "results") and isinstance(self.results, EndResult): pass else: self.results = EndResult() result_summary = "|{:^8}|{:^8}|{:^8}|{:^8}|{:^8}|{:^25}|{:^25}|".format(self.results.passed, self.results.failed, self.results.skip, \ self.results.error, self.results.all, self.results.begin_time, self.results.end_time) print("--------------------------------------------------------------------------------------------------") print( "|--\33[32mPASS\33[0m--|--\33[31mFAIL\33[0m--|--\33[37mSKIP\33[0m--|--\33[35mERROR\33[0m-|---\33[36mALL\33[0m--|----------\33[36mBegin\33[0m----------|-----------\33[36mEnd\33[0m-----------|") print(result_summary) print("--------------------------------------------------------------------------------------------------") def _case_name(self): print(self.case_name) return False def _exit(self): logger.info("main -- stop, wait for bus end") print(BANNER_STRS_EXIT) return True
class Logger(Process): ''' Logger ''' def __init__(self, case_name: str, time_str: str, log_dir: str, bus_client: BusClient, args: tuple): super().__init__() self.daemon = True self.bus_client = bus_client self.case_name = case_name self.log_dir = log_dir self.loggers = {} self.args = args self.time_str = time_str def reconnect_bus(self): ''' need reconnect bus by self.bus's infos :return: ''' self.bus_client = BusClient(self.bus_client.domain, self.bus_client.port, self.bus_client.auth_key) def run(self): self.reconnect_bus() if hasattr(self.args, "debug") and self.args.debug: logging.basicConfig(level=logging.DEBUG, format='%(asctime)s %(levelname)s %(message)s') else: logging.basicConfig(level=logging.INFO, format='%(asctime)s %(levelname)s %(message)s') log_home = f"{self.log_dir}/{self.case_name}/{self.time_str}" if not os.path.exists(log_home): os.makedirs(log_home) # here delete BusClient(), using input bus_clients # self.bus_client = BusClient() try: log_queue = self.bus_client.get_log() logger_end = self.bus_client.get_logger_end() while True: if not logger_end.empty(): logger_signal = logger_end.get() # check logger end singal to stop logger, from recorder to logger if isinstance( logger_signal, Signal ) and logger_signal.signal == SIGNAL_LOGGER_END: while True: if log_queue.empty(): break log = log_queue.get() self.log_handler(log) self.end_handler() break elif log_queue.empty(): time.sleep(0.001) continue else: log = log_queue.get() self.log_handler(log) except KeyboardInterrupt as key_e: print(BANNER_STRS_EXIT) def split_log(self, log): ''' split origin log msg :param log: :return: ''' try: return log.rsplit("$%", 2) except Exception as ee: return f"log$%error$%{log}" def log_print(self, log): ''' to print the log with format :param log: :return: ''' if self.args.nout: return logger_name = log.get("logger_name") level = log.get("level") msg_origin = log.get("msg") process = log.get("process") if process not in self.loggers: self.loggers[process] = logging.getLogger(logger_name) logger = self.loggers.get(process) if level == "debug": msg = f"<{process}> [{logger_name}] {msg_origin}" if hasattr(self.args, "debug") and self.args.debug: logger.debug(msg) elif level == "info": msg = f"<{process}> [{logger_name}] {msg_origin}" logger.info(msg) elif level == "warning": msg = f"{msg_origin}" logger.warning( f"<{process}> [{logger_name}]\33[33m ####################################### \33[0m" ) logger.warning(f"<{process}> [{logger_name}] \33[33m{msg}\33[0m") logger.warning( f"<{process}> [{logger_name}]\33[33m ####################################### \33[0m" ) elif level == "error": msg = f"{msg_origin}" logger.error( f"<{process}> [{logger_name}]\33[31m >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> \33[0m" ) logger.error(f"<{process}> [{logger_name}]\33[31m | {msg}\33[0m") logger.error( f"<{process}> [{logger_name}]\33[31m <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< \33[0m" ) elif level == "critical": logger.critical(f"\33[5m{log}\33[0m") def log_handler(self, log): ''' handler log here :param log: :return: ''' self.log_print(log) log = log.get("msg") try: temp1, temp2, msg = self.split_log(log) except: temp1 = "error" temp2 = "error" msg = log if "loader" in temp2: self.loader_handler(temp1, msg) elif "runner" in temp2: self.runner_handler(temp1, msg) elif "recorder" in temp2: self.recorder_handler(temp1, msg) elif "system" in temp2: self.system_handler(temp1, temp2, msg) elif "error" in temp2: self.error_handler(temp1, msg) else: self.case_handler(temp1, temp2, msg) def loader_handler(self, temp1, msg): self.write("loader", temp1, msg) def runner_handler(self, temp1, msg): self.write("runner", temp1, msg) def case_handler(self, temp1, temp2, msg): self.write(temp1, temp2, msg) def recorder_handler(self, temp1, msg): self.write("recorder", temp1, msg) def system_handler(self, temp1, temp2, msg): self.write("system", f"{temp1}.{temp2}", msg) def error_handler(self, temp1, msg): self.write("error", temp1, msg) def write(self, dir, filename, msg): ''' write log to filename's file :param dir: :param filename: :param msg: :return: ''' msg = f"{self.now}{msg}\n" dir = f"{self.log_dir}/{self.case_name}/{self.time_str}/{dir}" if not os.path.exists(dir): os.makedirs(dir) full_name = f"{dir}/{filename}.log" try: with open(full_name, 'a+') as f: f.write(msg) f.close() except Exception as e: with open(full_name, 'a+', encoding='utf-8') as f: f.write(msg) f.close() @property def now(self): ''' get datetime now to str :return: time now str ''' current_time = time.time() local_time = time.localtime(current_time) time_temp = time.strftime("%Y-%m-%d %H:%M:%S", local_time) secs = (current_time - int(current_time)) * 1000 timenow = "%s %03d" % (time_temp, secs) return timenow def end_handler(self): ''' when logger end, send signal logger end to main :return: ''' logger_handler = self.bus_client.get_system() logger_handler.put(Signal(self.pid, SIGNAL_LOGGER_END))