summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorzhangchengwei <[email protected]>2022-09-05 16:36:28 +0800
committerzhangchengwei <[email protected]>2022-09-05 16:36:28 +0800
commitf6e94ebdd782e6e59d6270ea468fa100ac212a99 (patch)
tree2a6204ae9d8cab4c604a20c902f26d660ae002a3
parent67b76148cfc5867b129163e9a24b1e27d1bfc8cc (diff)
增加airtest接口逻辑
-rw-r--r--control/airtest_client_upper/airtest_api_test.py68
-rw-r--r--control/airtest_client_upper/airtest_client_api.bat6
-rw-r--r--control/airtest_client_upper/airtest_client_api.py182
-rw-r--r--control/airtest_server_api.py207
-rw-r--r--control/business.py68
-rw-r--r--control/control.py3
-rw-r--r--control/control_config.ini30
-rw-r--r--control/gunicorn_config.py52
-rw-r--r--control/tsg_log.py3
9 files changed, 598 insertions, 21 deletions
diff --git a/control/airtest_client_upper/airtest_api_test.py b/control/airtest_client_upper/airtest_api_test.py
new file mode 100644
index 0000000..3193789
--- /dev/null
+++ b/control/airtest_client_upper/airtest_api_test.py
@@ -0,0 +1,68 @@
+import requests
+import json
+import os
+
+
+#测试提交任务总代理接口
+def task():
+ url = r"http://192.168.42.7:5000/task"
+ req_header = {"Content-Type": "application/json"}
+ data_info = {
+ "app_name": "python",
+ "app_operation": "./airtest_test/test1/test.py",
+ "test_device_id": "testapp",
+ "packet_name": "",
+ "upper_device_ip": "192.168.64.27",
+ "upper_device_id": "111111", # 预留参数
+ }
+ data_info = json.dumps(data_info)
+ print(data_info)
+ r = requests.request("post", headers=req_header, url=url, data=data_info)
+ r_s = json.loads(r.text)
+ print(r_s)
+
+
+#测试airtest任务中client端代理接口
+def airtest_case():
+ url = r"http://127.0.0.1:5001/airtest_case"
+ url = r"http://192.168.64.27:5001/airtest_case"
+ req_header = {"Content-Type": "application/json"}
+ data_info = {
+ "app_name": "python",
+ "app_operation": "/airtest_test/test1/test.py",
+ "test_device_id": "testapp",
+ "packet_name": ""
+ }
+ data_info = json.dumps(data_info)
+ print(data_info)
+ #data_info = '{"app_name": "python", "app_operation": "./airtest_test/test1/test.py", "test_device_id": "testapp", "packet_name": ""}'
+ r = requests.request("post", headers=req_header, url=url, data=data_info)
+ print(r.text)
+
+#服务的airtest获取packek_name文件接口
+def upload_s_packet():
+ url = r"http://192.168.42.7:5000/upload"
+ file_abs_path = "D:/zcw/py-auto/airtest_test/test1/api_test/2022082213343303200118349977-allow-only-IpAndApplication-sendMessage-airTest.pcap"
+ file_name = os.path.basename(file_abs_path)
+ file_data = {"file": (file_name, open(file_abs_path, "rb"))}
+ #req_header = {"Content-Type": "multipart/form-data"}
+ r = requests.request("POST", url=url, files=file_data)
+ print(r.text)
+
+
+#airtest_client端上位机上传数据包
+def upload_packet(file_abs_path = "D:/zcw/py-auto/airtest_test/test1/api_test/2022082213343303200118349977-allow-only-IpAndApplication-sendMessage-airTest.pcap"):
+ #url = r"http://127.0.0.1:5001/upload_to_server"
+ url = r"http://192.168.50.19:5001/upload_to_server"
+ file_name = os.path.basename(file_abs_path)
+ file_data = {"file": (None, file_abs_path, "string")}
+ print(file_data)
+ r = requests.request("POST", url=url, files=file_data)
+ print(r.text)
+
+
+if __name__ == '__main__':
+ #task()
+ #airtest_case()
+ #upload_s_packet()
+ upload_packet() \ No newline at end of file
diff --git a/control/airtest_client_upper/airtest_client_api.bat b/control/airtest_client_upper/airtest_client_api.bat
new file mode 100644
index 0000000..350058f
--- /dev/null
+++ b/control/airtest_client_upper/airtest_client_api.bat
@@ -0,0 +1,6 @@
+@echo off
+reg add HKEY_CURRENT_USER\Console /v QuickEdit /t REG_DWORD /d 00000000 /f
+D:
+cd D:\Airtest_client_upper
+python D:\Airtest_client_upper\airtest_client_api.py
+pause \ No newline at end of file
diff --git a/control/airtest_client_upper/airtest_client_api.py b/control/airtest_client_upper/airtest_client_api.py
new file mode 100644
index 0000000..a961425
--- /dev/null
+++ b/control/airtest_client_upper/airtest_client_api.py
@@ -0,0 +1,182 @@
+# coding=utf-8
+from gevent import monkey
+monkey.patch_all()
+import os.path
+import time
+import json
+from flask import Flask, request, make_response, jsonify
+from gevent import pywsgi
+import requests
+import subprocess
+from concurrent.futures import ThreadPoolExecutor
+
+
+#airtest脚本路径
+airtest_client_path = r"D:\App_automation\air_test_auto\control.py"
+airtest_server_ip = "192.168.42.7" #airtest_server服务层代理IP
+airtest_server_port = 5000 #airtest_server服务器代理端口
+
+#airtest_server接口uri
+airtest_server_device_info_url = "/device_info" #airtest_server代理提交设备信息地址
+airtest_server_upload = "/upload"
+
+
+app = Flask(__name__)
+app.config['JSON_AS_ASCII'] = False
+
+def client():
+ print("cient")
+ return "client"
+
[email protected]("/client1")
+def client1():
+ print("cient1")
+ time.sleep(50)
+ return "client1"
+
+
[email protected]("/airtest_case", methods=["POST"]) #上位机c端代理提供s端代理调用的执行任务接口
+def airtest_case():
+ #上位机根据任务信息执行airtest脚本,并将结果返回
+ if request.method == "POST":
+ airtest_case_info = request.json
+ # 上位机实际处理任务函数
+ print(f"airtest_server传过来的参数:{airtest_case_info}")
+ test_device_id = airtest_case_info["test_device_id"]
+ app_name = airtest_case_info["app_name"]
+ app_operation = airtest_case_info["app_operation"]
+ packet_name = airtest_case_info["packet_name"]
+ # -d = test_device_id, -n = app_name, -o = app_operation, -p = packet_name
+ airtest_exec_cmd = " python {} -d {} -n {} -o {} -p {}".format(airtest_client_path, test_device_id, app_name,
+ app_operation, packet_name)
+ print("执行命令:{}".format(airtest_exec_cmd))
+ airtest_case_task = subprocess.Popen(airtest_exec_cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE,
+ shell=True)
+ exec_result = ""
+ while True:
+ exec_result_1 = airtest_case_task.stdout.readline()
+ try:
+ exec_result_1 = exec_result_1.decode("gbk")
+ except:
+ exec_result_1 = exec_result_1.decode("utf-8")
+ exec_result_1 = exec_result_1.encode().decode()
+ exec_result += exec_result_1
+ print(exec_result_1, end="")
+ if exec_result_1 == "":
+ time.sleep(0.5)
+ if exec_result_1 == "":
+ break
+ else:
+ exec_result_1 = ""
+
+ # 配置返回数据
+ return_info = {
+ "code": 200,
+ "success": 0,
+ "msg": ""
+ }
+ status_code = make_response().status_code
+ return_info["code"] = status_code
+ return_info["msg"] = exec_result
+ print(f"测试用例执行结果{exec_result}")
+ if "The test case succeeded" in exec_result:
+ return_info["success"] = 0
+ else:
+ return_info["success"] = 1
+ print(f"airtest脚本执行结果:{return_info}")
+ return jsonify(return_info)
+
[email protected]("/upload_to_server", methods=["POST"]) #airtest_client 上位机代理数据上传接口
+def upload_to_server():
+ if request.method == "POST":
+ print(request.form)
+ file_abs_name = request.form.get("file")
+ #调用airtest_sercer服务器代理上传文件接口
+ url = "http://{}:{}{}".format(airtest_server_ip, airtest_server_port, airtest_server_upload)
+ file_name = os.path.basename(file_abs_name)
+ file_data = {"file": (file_name, open(file_abs_name, "rb"))}
+ n = 0
+ while True:
+ try:
+ r = requests.request("post", url=url, files=file_data)
+ except:
+ n += 1
+ print("调用fusion上次文件接口失败:{}".format(url))
+ if n == 3:
+ return jsonify({"code": 1, "data": {}, "msg": "上传失败"})
+ continue
+ print(r.text)
+ return jsonify({"code": 0, "data": {}, "msg": "上传成功"})
+
+
+
[email protected]("/upload_c_packet") #airtest_client层,接收上层代理下发的获取捕包文件接口,暂时不使用此方式
+def upload_packet():
+ #上传捕包文件脚本
+ if request.method == "GET":
+ packet_name = request.args.get("packet_name")
+ # 处理捕包文件脚本
+ print(f"airtest_client上位机层收到获取捕包数据文件通知:{packet_name}")
+ return "上位机处理捕包上传文件"
+
+# 获得device信息,并提交给server端接口
+def call_server_device_info_api():
+ #获取本机和连接的测试设备数据
+ global airtest_server_ip, airtest_server_port, airtest_server_device_info_url
+ device_info = {
+ "upper_device_name": "host1",
+ "upper_device_ip": "192.168.50.5",
+ "test_device_info": [
+ {
+ "test_device_type": "mobile",
+ "test_device_name": "huiwei",
+ "test_device_ip": "192.168.50.3",
+ },
+ {
+ "test_device_type": "simulator",
+ "test_device_name": "leidian",
+ "test_device_ip": "192.168.50.20",
+ }
+ ]}
+ device_info = json.dumps(device_info)
+ #调用提交给server接口
+ req_header = {"Content-Type": "application/json"}
+ print(device_info)
+ url = "http://{}:{}{}".format(airtest_server_ip, airtest_server_port, airtest_server_device_info_url)
+ r_call_server_deviceinfo_api = requests.request("post", url=url, headers=req_header, data=device_info)
+ print(r_call_server_deviceinfo_api.text)
+
+#定时收集上位机ip信息,连接的设备信息(模拟器ip、真机ip、使用情况信息),并上传给server端
+def submit_device_info():
+ n = 0
+ while True:
+ #将本机信息提交到server的deviceinfo接口
+ call_server_device_info_api()
+ print(f"搜集上位机和设备的信息:{n}")
+ time.sleep(100)
+ n += 1
+
+def airtest_client_api_agent():
+ app.debug = True
+ #app.run(host="0.0.0.0", port=5001)
+ server = pywsgi.WSGIServer(("0.0.0.0", 5001), app)
+ server.serve_forever()
+
+def current_thread():
+ current_task = ThreadPoolExecutor(max_workers=2)
+ current_task.submit(airtest_client_api_agent)
+ current_task.submit(submit_device_info)
+
+if __name__ == '__main__':
+ print(11111111111)
+ #current_thread()
+
+ # app.debug = True
+ # app.run(host="0.0.0.0", port=5001)
+
+ server = pywsgi.WSGIServer(("0.0.0.0", 5001), app)
+ server.serve_forever()
+
+
+ print(22) \ No newline at end of file
diff --git a/control/airtest_server_api.py b/control/airtest_server_api.py
new file mode 100644
index 0000000..c3503cd
--- /dev/null
+++ b/control/airtest_server_api.py
@@ -0,0 +1,207 @@
+#!/usr/bin/python3
+# -*- coding: utf-8 -*-
+import shutil
+import sys
+import os
+sys.path.append(r"/opt/test")
+import json
+from flask import Flask, request, make_response, jsonify
+from werkzeug.utils import secure_filename
+from gevent import pywsgi
+from gevent import monkey
+import requests
+import copy
+import random
+import time
+import traceback
+import configparser
+from business import config_abs_path, tsglogger_fun
+from automation.control.tsg_log import TsgLogger
+
+# 将python标准的io方法,都替换成gevent中同名的方法,遇到io阻塞gevent自动进行协程切换
+#monkey.patch_all()
+
+
+airtest_client_port = 5001 #airtest_client上位机层代理端口
+airtest_client_upload_c_packet_url = "/upload_c_packet" #airtest_client上位机层代理提交数据包接口
+airtest_client_airtest_case_url = "/airtest_case" #airtest_client上位机层代理调用任务接口
+
+
+#获得脚本文件所在的根路径
+abs_script_path = __file__
+work_path = os.path.split(abs_script_path)[0]
+
+app = Flask(__name__)
+
+
+def airtestlogger_fun(instructNo):
+ config_parse = configparser.ConfigParser()
+ config_parse.read(config_abs_path)
+ root_path = config_parse.get("path_info", "root_path")
+ log_file_name0 = config_parse.get("log_info", "airtest_file_name")
+ log_file_name = root_path + log_file_name0
+ log_file_level = config_parse.get("log_info", "log_file_level")
+ log_confole_level = config_parse.get("log_info", "log_console_level")
+
+ tsglogger = TsgLogger(log_file_name, file_level=log_file_level, console_level=log_confole_level, instructNo=instructNo).getLogger()
+ return tsglogger
+
+
+
+def server():
+ airtest_logger = airtestlogger_fun("0000000000")
+ airtest_logger.info("server:{}".format(time.time()))
+ print("server")
+ return "server"
+
[email protected]("/device_info", methods=["POST"]) #服务端获取设备信息接口
+def device_info(): #获取设备信息,包括上位机IP、连接设备类型信息(模拟器IP、真机ip)
+ if request.method == "POST":
+ device_info = request.json
+ # 获得设备信息
+ print("-----{}".format(random.randint(1, 8)))
+ print("得到上位机和其测试设备信息{}".format(device_info))
+ # 将设备信息维护一个字典
+ return "设备信息"
+
+
[email protected]("/task", methods=["POST"]) #提交任务总代理接口
+def task(): #获取任务,并派给执行函数
+ task_dict = request.json
+ #创建log日志数据文件
+ if task_dict["packet_name"]:
+ task_id = task_dict["packet_name"].split("-")[0]
+ else:
+ task_id = "0000000000"
+ airtest_logger = airtestlogger_fun(task_id)
+
+ # 获取任务,从传来的数据中获取url和data数据
+ #print(f"robotframework传来的参数:{task_dict}")
+ airtest_logger.info(f"robotframework传来的参数:{task_dict}")
+ airtest_logger.info("临时记录时间{}".format(time.time()))
+ global airtest_client_port, airtest_client_airtest_case_url
+ upper_device_ip = task_dict["upper_device_ip"]
+
+ # if upper_device_ip == "192.168.50.19":
+ # upper_device_ip = "192.168.64.27"
+ # upper_device_ip = "192.168.50.19"
+
+ url = "http://{}:{}{}".format(upper_device_ip, airtest_client_port, airtest_client_airtest_case_url) #airtest_client的调用任务的url
+ airtest_client_data = copy.deepcopy(task_dict)
+ airtest_client_data.pop("upper_device_ip")
+ airtest_client_data.pop("upper_device_id")
+ #转化成json格式
+ data = json.dumps(airtest_client_data)
+ #print(f"传给airtest_client端的参数:{data}")
+ airtest_logger.info(f"传给airtest_client端接口{url}的参数:{data}")
+ # 根据设备使用情况,下发到对应设备接口执行
+ result = exec_airtet_case(url, data, airtest_logger)
+ # 获取最终执行结果
+ return result
+
[email protected]("/upload_s_packet") #server获取数据包接口,呈上,供给control调用。暂不使用,捕包文件直接调用上次接口即可。
+def upload_s_packet():
+ #server获取数据包接口
+ if request.method == "GET":
+ packet_name = request.args.get("packet_name")
+ upper_device_ip = request.args.get("upper_device_ip")
+ # 实际处理上传的捕包数据
+ print(f"control层请求需要回传的数据包名称参数:{packet_name},获取数据脚本的上位机ip:{upper_device_ip}")
+ global airtest_client_port, airtest_client_upload_c_packet_url
+ # 调用airtest_clent层上位机的提供捕包文件的接口
+ url = "http://{}:{}{}".format(upper_device_ip, airtest_client_port, airtest_client_upload_c_packet_url)
+ params_dict = {"packet_name": packet_name}
+ r = requests.request("get", url=url, params=params_dict)
+ print(r.text)
+ return r.text
+
[email protected]("/upload", methods=["POST"]) #server层代理实际上传文件接口
+def upload():
+ if request.method == "POST":
+ f = request.files
+ print(f)
+ f = f["file"]
+ f_name = secure_filename(f.filename)
+ print("上传文件名称:{}".format(f_name))
+ packet_dir_name = os.path.join(os.path.dirname(work_path), "airtest_packet")
+ if not os.path.exists(packet_dir_name):
+ os.mkdir(packet_dir_name)
+ packet_file_name = os.path.join(packet_dir_name, secure_filename(f_name))
+ f.save(packet_file_name)
+ f_id = f_name.split("-")[0]
+ airtest_logger = airtestlogger_fun(f_id)
+ print("文件保存的绝对路径:{}".format(packet_file_name))
+ airtest_logger.info("捕包数据文件保存的绝对路径:{}".format(packet_file_name))
+ print("文件所属任务id:{}".format(f_id))
+ #调用fusion中agent的上次文件接口,将数据查到fusion中。
+ config = configparser.ConfigParser()
+ config.read(config_abs_path)
+ fusion_host = config.get("interface_info", "fusion_host")
+ upload_url = "{}/callback/uploadlocal/{}".format(fusion_host, f_id)
+ file_data = {"file": (None, packet_file_name, "String")}
+ n = 0
+ while True:
+ try:
+ r = requests.request("post", url=upload_url, files=file_data)
+ except:
+ n += 1
+ print("调用fusion上次文件接口失败:{}".format(upload_url))
+ if n == 3:
+ airtest_logger.error("调用fusion上次文件接口失败:{}".format(upload_url))
+ return "调用fusion上次文件接口失败:{}".format(upload_url)
+ continue
+ break
+ print(r.text)
+ airtest_logger.info("上传数据文件返回的结果".format(r.text))
+
+ #情况5天前的文件
+ now_time = time.time()
+ delete_time = now_time - 3600*24*5
+ clear_dir_list = os.listdir(packet_dir_name)
+ if len(clear_dir_list) > 0:
+ for path in clear_dir_list:
+ abs_path = os.path.join(packet_dir_name, path)
+ abs_path_ctime = os.path.getctime(abs_path)
+ if abs_path_ctime <= delete_time:
+ try:
+ shutil.rmtree(abs_path)
+ except:
+ os.remove(abs_path)
+
+ return "{}".format(make_response().status_code)
+
+#调用执行airtest执行接口,执行任务
+def exec_airtet_case(url, data, airtest_logger):
+ #调用执行结果执行任务,并获取结果
+ req_header = {"Content-Type": "application/json"}
+ print("下发任务给airtest_client_上位机接口地址:{},数据:{}".format(url, data))
+ n = 0
+ while True:
+ try:
+ r = requests.request("post", url=url, headers=req_header, data=data)
+ except Exception as e:
+ print(e)
+ traceback.print_exc()
+ n += 1
+ print(f"连接失败次数:{n}, 连接地址:{url}")
+ if n == 3:
+ print(f"连接失败,连接地址{url}")
+ airtest_logger.error(f"连接失败,连接地址{url}")
+ return f"连接失败,连接地址{url}"
+ continue
+ break
+ result = r.text
+ #print("上位机接口:{},执行用例数据{},执行结果{}".format(url, data, result))
+ airtest_logger.info("上位机接口:{},执行用例数据{},执行结果{}".format(url, data, result))
+ return result
+
+
+
+if __name__ == '__main__':
+
+ app.debug = True
+ app.run(host="0.0.0.0", port=5000)
+
+ # server = pywsgi.WSGIServer(("0.0.0.0", 5000), app)
+ # server.serve_forever()
diff --git a/control/business.py b/control/business.py
index 0a6ad26..1b1f357 100644
--- a/control/business.py
+++ b/control/business.py
@@ -13,6 +13,7 @@ import sys
import subprocess
import requests
import copy
+import traceback
from scapy.all import AsyncSniffer, wrpcap, sniff
from threading import Thread, RLock
from concurrent.futures import ThreadPoolExecutor, as_completed, wait, ALL_COMPLETED
@@ -166,6 +167,13 @@ def clear_historical_reort(instructNo_setup_json_abs_path, tsglogger):
:param instructNo_setup_json_abs_path: #/opt/test/automation/tasks/2022052717210703000103027569/setup_2022052717210703000103027569.json
:return:
"""
+ try: #测试使用的
+ a = 1
+ b = 1
+ c = a + b
+ except Exception as e:
+ tsglogger.error("异常:{}".format((traceback.format_exc())))
+
tsglogger.info("开始函数:{}".format(clear_historical_reort.__name__))
#print("清楚历史数据...:{}".format(instructNo_setup_json_abs_path))
tsglogger.info("清楚历史数据...:{}".format(instructNo_setup_json_abs_path))
@@ -191,6 +199,7 @@ def clear_historical_reort(instructNo_setup_json_abs_path, tsglogger):
dir_ctime = os.path.getctime(dir_abs_path)
except Exception as e:
tsglogger.error(e)
+ tsglogger.error("异常:{}".format((traceback.format_exc())))
continue
#print(dir_abs_path)
#tsglogger.info(dir_abs_path)
@@ -202,6 +211,7 @@ def clear_historical_reort(instructNo_setup_json_abs_path, tsglogger):
os.remove(dir_abs_path)
except Exception as e:
tsglogger.error(e)
+ tsglogger.error("异常:{}".format((traceback.format_exc())))
#删除agent server上的report历史文件:
agent_server_host = Linux(ip="192.168.42.4", username="root", password="Xxg-LAB<>90", tsglogger=tsglogger)
agent_server_host.connect()
@@ -235,7 +245,8 @@ def get_setup_abs_path(instructNo, tsglogger):
setup_json_name1 = i
except Exception as e:
tsglogger.error("没有setup文件")
- tsglogger.exception(e)
+ tsglogger.error(e)
+ tsglogger.error("异常:{}".format((traceback.format_exc())))
else:
instructNo_setup_json_abs_path = root_path + "/automation/tasks/" + instructNo + "/" + setup_json_name1
tsglogger.debug("返回参数,instructNo_setup_json_abs_path:".format(instructNo_setup_json_abs_path)) #通过instrucNo重组setup绝对路径,后面会使用
@@ -359,7 +370,7 @@ def execute_combine_capture_packet(robot_command, tsglogger):
#ip = "192.168.42.97"
#eth = "eth0"
- ip = "192.168"
+ #ip = "192.168.64.27"
tsglogger.debug(f"捕包网卡信息:{eth}")
tsglogger.debug(f"捕包的ip信息:{ip}")
#tsglogger.error("测试信息。。。")
@@ -536,6 +547,7 @@ def get_case_name_from_output_xml(dryrun_output_list,instructNo_setup_json_abs_p
output_tree = ET.ElementTree(file=dryrun_output_name_abs_path)
except Exception as e:
tsglogger.error("没有dryrun命令生成的output.xml文件")
+ tsglogger.error("异常:{}".format((traceback.format_exc())))
#tsglogger.execption(e)
#suit相关信息的列表
suite_info_list = []
@@ -641,7 +653,8 @@ def callback_callback_dryrun_report(generate_case_json, instructNo, tsglogger):
r_callback_casereport_text = json.loads(r_callback_casereport.text, encoding="utf-8")
except Exception as e:
tsglogger.error("从dryrun生成的caselist到fusion接口数据,提交失败")
- tsglogger.exception(e)
+ tsglogger.error(e)
+ tsglogger.error("异常:{}".format((traceback.format_exc())))
n += 1
time.sleep(0.5)
continue
@@ -697,6 +710,7 @@ def callback_rest_result_report(instructNo, tsglogger):
n += 1
tsglogger.error(e)
tsglogger.info(e)
+ tsglogger.error("异常:{}".format((traceback.format_exc())))
continue
else:
tsglogger.info(f"提交case返回的响应信息:{r_callback_casereport_text}")
@@ -757,6 +771,7 @@ def callbaock_upload_result_file(file_path, instructNo, tsglogger):
n += 1
tsglogger.error("调用总结果{}的绝对路径接口失败".format(data))
tsglogger.error(e)
+ tsglogger.error("异常:{}".format((traceback.format_exc())))
continue
else:
tsglogger.info(f"响应参数:{r_callback_upload_file_test}")
@@ -1023,8 +1038,8 @@ def combine_execute_testcase_commond(execute_case_and_client_list, dryrun_comman
:return:caselist、运行robot命令、client信息的对应列表
"""
"""
- cd /home/hbn/gap_tsg_api0907/ && python -m robot.run -d newsreport/220313 --output test.xml --log test.html --report test.html --dry --pythonpath . --test allow-fqdn-suffix gap_tsg_api/case/policies/security/http.robot
- cd /home/hbn/gap_tsg_api0907/ && python -m robot.run -v defaultIp:1.1.1.1 -d newsreport/220313 --output test.xml --log test.html --report test.html --pythonpath . --test allow-fqdn-suffix gap_tsg_api/case/policies/security/http.robot
+ cd /home/hbn/gap_tsg_api0907/gap_tsg_api/ && python -m robot.run -d newsreport/220313 --output test.xml --log test.html --report test.html --dry --pythonpath . --test allow-fqdn-suffix case/policies/security/http.robot
+ cd /home/hbn/gap_tsg_api0907/gap_tsg_api/ && python -m robot.run -v defaultIp:1.1.1.1 -d newsreport/220313 --output test.xml --log test.html --report test.html --pythonpath . --test allow-fqdn-suffix case/policies/security/http.robot
"""
"""通过linux命令,执行robot的dryrun命令,并生成dryrun文件"""
tsglogger.info(f"开始函数:{combine_execute_testcase_commond.__name__}")
@@ -1041,7 +1056,8 @@ def combine_execute_testcase_commond(execute_case_and_client_list, dryrun_comman
if cases[0] == case: #只为了执行第一个元素
for i in range(len(case)):
case_name = case[i][0].split("/")
- case_name:list = case_name[case_name.index("gap_tsg_api"):]
+ case_name:list = case_name[case_name.index("case"):]
+ #case_name:list = case_name[case_name.index("gap_tsg_api"):]
case_name0 = "/".join(case_name[:-1])
case_name0 = " " + case_name[-1] + " " + case_name0 + ".robot"
case_name1 = dryrun_command + " --test " + case_name0
@@ -1098,6 +1114,7 @@ def get_mobile_info_dict():
global config_abs_path
control_config.read(config_abs_path)
eth_info = control_config.get("mobile_info", "mobile_info_dict")
+ eth_info = eth_info.lower() #全部转换为小写
mobile_info_dict = json.loads(eth_info)
return mobile_info_dict
@@ -1155,13 +1172,17 @@ def capture_packet_and_execute_robot(robot_command, client_info, f_dict, common_
mobile_case_rlock.acquire()
tsglogger.info("手机客户度信息" + client_info["incomingMobileClientInfo"]["clientModule"])
case_old_id = mobile_case_id_list.index(robot_command) #只是使用索引号做为遍历的起点,没有其它的作用
- mobile_info_allow_case_list = mobile_info_dict[client_info["incomingMobileClientInfo"]["clientModule"]]
-
+ try:
+ mobile_info_allow_case_list = mobile_info_dict[(client_info["incomingMobileClientInfo"]["clientModule"]).lower()]
+ except:
+ tsglogger.error("异常:{}".format((traceback.format_exc())))
+ tsglogger.error("在{} 中没有 {}".format(mobile_info_dict, (client_info["incomingMobileClientInfo"]["clientModule"]).lower()))
+ exit(1)
for case_id in range(case_old_id, len(mobile_case_list)): #负载均衡可以手机设备可以执行的用例 mobile_case_list 这个列表才是实际取case的
robot_command_0 = mobile_case_list[case_id]
signal = 0
for mobile_info_allow_case in mobile_info_allow_case_list:
- if mobile_info_allow_case in robot_command_0:
+ if mobile_info_allow_case in robot_command_0.lower():
signal = 1
mobile_case_list[case_id] = mobile_case_list[case_old_id]
mobile_case_list[case_old_id] = robot_command_0
@@ -1191,7 +1212,7 @@ def capture_packet_and_execute_robot(robot_command, client_info, f_dict, common_
for key, values in mobile_info_dict.items(): #筛选出case命令中可以执行使用的手机设备
signal_1 = 0
for value in values:
- if value in robot_command:
+ if value in robot_command.lower():
client_info_0 = key
client_info_0_list.append(client_info_0)
signal_1 = 1
@@ -1220,20 +1241,35 @@ def capture_packet_and_execute_robot(robot_command, client_info, f_dict, common_
common_var_str = ""
for var in common_configration_variable_list:
common_var_str += " -v " + str(var[0]) + ":" + str(var[1]) + " "
+ #将common_var_str中添加packet_name变量,供给airtest使用,捕包时,传数据包名字。不捕包时,传空值。
+ if str(pactureParm) == "1": #捕包参数时,传packet_name变量值非空
+ packet_name = "{}-{}".format(instructNo, robot_command.split()[-2])
+ common_var_str = "{} -v packet_name:{} ".format(common_var_str, packet_name)
+ else:
+ common_var_str = "{} -v packet_name:{} ".format(common_var_str, "")
+
#重组需要执行的robot_command命令
robot_command = re.sub("-v.*--pythonpath", "-v \"" + list(client_info.keys())[0] + ":" + str(list(client_info.values())[0]) + "\" {} --pythonpath ".format(common_var_str), robot_command)
- if str(pactureParm) == "1": #判断是否捕包
+ if (str(pactureParm) == "1") and ("incomingMobileClientInfo" not in robot_command): #判断是否捕包,且phone用例不捕包
dpkt = execute_combine_capture_packet(robot_command, tsglogger)
- execute_commond_of_robot(robot_command, f_dict, tsglogger)
- if str(pactureParm) == "1":
+ execute_result = execute_commond_of_robot(robot_command, f_dict, tsglogger)
+ tsglogger.debug("执行测试case的返回结果:{}".format(execute_result))
+ tsglogger.debug("执行测试case的的status:{}".format(execute_result["status"]))
+ if (str(pactureParm) == "1") and ("incomingMobileClientInfo" not in robot_command): #判断是否捕包,且phone用例不捕包
dpkt[0].kill() #dpk = [dpkt, [source_file_info]]
+ time.sleep(0.5)
tsglogger.info(f"线程:{threading.current_thread().name}:完成捕包")
#回传捕包数据文件
- tsglogger.info(f"线程:{threading.current_thread().name}:开始回传捕包数据文件")
- callbaock_upload_result_file(dpkt[1], instructNo, tsglogger)
- tsglogger.info(f"线程:{threading.current_thread().name}:完成回传捕包数据文件")
+ if execute_result["status"] == 1: #{"case":case_name, "status":1} 1为执行失败,需要回传捕包数据
+ tsglogger.info(f"线程:{threading.current_thread().name}:开始回传捕包数据文件")
+ tsglogger.info("测试失败的用例,需要回传的捕包文件:{}".format(dpkt[1][0]))
+ callbaock_upload_result_file(dpkt[1], instructNo, tsglogger)
+ tsglogger.info(f"线程:{threading.current_thread().name}:完成回传捕包数据文件")
+ else: #{"case":case_name, "status":0} 删除捕包文件
+ tsglogger.info("测试通过的用例,需要删除的捕包文件:{}".format(dpkt[1][0]))
+ os.remove(dpkt[1][0])
client_info_dict[threading_name][1] = 1 #将设备资源重新设置为可以状态
tsglogger.info(f"结束函数:{capture_packet_and_execute_robot.__name__}")
diff --git a/control/control.py b/control/control.py
index 3a45d12..1881fd8 100644
--- a/control/control.py
+++ b/control/control.py
@@ -105,7 +105,8 @@ def executeAutomation(instructNo, runMode, onlyDryrun, kill):
else: #不检验版本信息
tsglogger.info("无需校验版本信息!")
# 获取执行列表中生成dryrun文件命令,重新组合dryrun命令
- dryrun_command_front_past = "cd /opt/test/automation/scripts/ && python3 -m robot.run -d newsreport/220313 --output test.xml --log test.html --report test.html --dry --pythonpath . "
+ dryrun_command_front_past = "cd /opt/test/automation/scripts/gap_tsg_api/ && python3 -m robot.run -d newsreport/220313 --output test.xml --log test.html --report test.html --dry --pythonpath . "
+ #dryrun_command_front_past = "cd /opt/test/automation/scripts/ && python3 -m robot.run -d newsreport/220313 --output test.xml --log test.html --report test.html --dry --pythonpath . "
for i in range(len(f_dict["commandList"])):
f_dict["commandList"][i] = dryrun_command_front_past + f_dict["commandList"][i]
dryrun_command_list = f_dict["commandList"]
diff --git a/control/control_config.ini b/control/control_config.ini
index 4dc04f2..dc19be2 100644
--- a/control/control_config.ini
+++ b/control/control_config.ini
@@ -11,6 +11,7 @@ incoming_common_variable = /opt/test/automation/scripts/gap_tsg_api/variable
[log_info]
log_file_name = /automation/tsgauto_log/tsgauto.log
+airtest_file_name = /automation/tsgauto_log/airtest_case.log
log_file_level = DEBUG
log_console_level = INFO
@@ -19,16 +20,37 @@ log_console_level = INFO
capture_eth = ens16
[mobile_info]
-mobile_info_dict = {
+#itest使用的测试环境
+mobile_info_dict1 = {
"vivoV2031A":["facebook", "freegate", "gmail", "instagram", "instagram", "psiphon3", "qq", "skype", "tachyon",
- "taobao", "telegram", "tor", "twitter", "wechat", "whatsapp", "wireguard", "youtube"],
+ "taobao", "telegram", "tor", "twitter", "wechat", "whatsapp", "wireguard", "youtube", "baidu"],
"iphone12":["facebook", "gmail", "instagram", "instagram", "psiphon3", "qq", "skype", "tachyon",
- "taobao", "telegram", "tor", "twitter", "wechat", "whatsapp", "wireguard", "youtube"],
+ "taobao", "telegram", "tor", "twitter", "wechat", "whatsapp", "wireguard", "youtube", "baidu"],
"xiaomi":["freegate", "psiphon3", "tachyon", "tor"],
"iphoneXR":["freegate", "psiphon3", "tachyon", "youtube"]
}
+#airtest使用的测试环境
+mobile_info_dict = {
+ "thunder": ["wechat", "facebook", "Instagram", "gmail", "twitter", "youtube", "qq", "taobao", "bilibili", "V4C", "UGVPN", "TorVPN"],
+ "free": ["telegram","skype", "whatsapp", "V4C", "UGVPN", "VPNlat", "anonytun_vpn", "urbanVPN", "TurboVPN_mm", "FlashVPN", "ProtonVPN", "Freegate", "TachyonVPN", "visitWebsite", "TorVPN"],
+ "mumu": ["baidu","psiphon3"],
+ "honor": ["telegram", "wechat", "facebook", "Instagram", "gmail", "skype", "youtube", "baidu", "qq", "taobao", "bilibili", "psiphon3", "Freegate", "TachyonVPN", "UGVPN", "anonytun_vpn", "TurboVPN_mm", "FlashVPN"],
+ "vivoV2031A": ["telegram", "wechat", "facebook", "Instagram", "gmail", "skype", "twitter", "youtube", "baidu", "qq", "taobao", "bilibili", "psiphon3", "Freegate", "TachyonVPN", "TorVPN", "TorBrowser", "V4C", "UGVPN", "VPNlat", "anonytun_vpn", "urbanVPN", "TurboVPN_mm", "FlashVPN", "ProtonVPN"],
+ "xiaomi": ["telegram", "wechat", "facebook", "gmail", "skype", "twitter", "baidu", "qq", "taobao", "bilibili", "psiphon3", "UGVPN", "anonytun_vpn", "FlashVPN", "TurboVPN_mm"],
+ "yijia": ["telegram", "wechat", "facebook", "Instagram", "gmail", "skype", "twitter", "youtube", "baidu", "qq", "taobao", "bilibili", "psiphon3", "Freegate", "TachyonVPN", "TorVPN", "TorBrowser", "V4C", "UGVPN", "VPNlat", "anonytun_vpn", "urbanVPN", "TurboVPN_mm", "FlashVPN", "ProtonVPN"]
+ }
+
+mobile_info_dict2 = {
+ "thunder":["wechat", "facebook", "Instagram", "gmail", "twitter", "youtube", "qq", "taobao", "bilibili", "V4C", "UGVPN", "TorVPN"],
+ "free":["telegram","skype", "whatsapp", "V4C", "UGVPN", "VPNlat", "anonytun_vpn", "urbanVPN", "TurboVPN_mm", "FlashVPN", "ProtonVPN", "Freegate", "TachyonVPN",
+ "visitWebsite", "TorVPN"],
+ "mumu":["baidu","psiphon3"],
+ "honor":[],
+ "vivoV2031A":["telegram", "V4C"]
+ }
+
[report_retention_time]
control_layer_retention_time = 3
-agent_server_layer_retention_time = 15
+agent_server_layer_retention_time = 10
agent_server_layer_cache_retention_time = 2 \ No newline at end of file
diff --git a/control/gunicorn_config.py b/control/gunicorn_config.py
new file mode 100644
index 0000000..f136ad6
--- /dev/null
+++ b/control/gunicorn_config.py
@@ -0,0 +1,52 @@
+import os
+import gevent.monkey
+gevent.monkey.patch_all()
+
+import multiprocessing
+
+debug = True
+#gunicorn + gevent部署
+#https://blog.csdn.net/wf1722029940/article/details/120493808
+#https://blog.csdn.net/weixin_46072106/article/details/109708788
+#https://www.cnblogs.com/fengff/p/9225859.html
+#gunicorn -c gunicorn_config.py flask_server:app
+#gunicorn -c gunicorn_config.py airtest_server_api:app
+
+
+#预加载资源
+preload_app = True
+
+#绑定ip
+bind = "0.0.0.0:5000"
+
+#进程数量
+workers = multiprocessing.cpu_count() * 2 + 1
+
+#线程数量
+threads = multiprocessing.cpu_count() * 10
+
+# 等待队列最大长度,超过这个长度的链接将被拒绝连接
+backlog = 2048
+
+# 工作模式--协程
+worker_class = "gevent"
+
+# 最大客户客户端并发数量,对使用线程和协程的worker的工作有影响
+# 服务器配置设置的值 1200:中小型项目 上万并发: 中大型
+# 服务器硬件:宽带+数据库+内存
+# 服务器的架构:集群 主从
+worker_connections = 1200
+
+# 进程名称
+proc_name = 'gunicorn.pid'
+# 进程pid记录文件
+pidfile = 'airserverlog/app_run.log'
+# 日志等级
+loglevel = 'debug'
+# 日志文件名
+logfile = 'airserverlog/debug.log'
+# 访问记录
+accesslog = 'airserverlog/access.log'
+# 访问记录格式
+access_log_format = '%(h)s %(t)s %(U)s %(q)s'
+
diff --git a/control/tsg_log.py b/control/tsg_log.py
index b15e235..f4ab86e 100644
--- a/control/tsg_log.py
+++ b/control/tsg_log.py
@@ -64,6 +64,9 @@ class TsgLogger():
self.logger.setLevel(logging.DEBUG)
self.instrucNO = instructNo
+ if self.logger.handlers:
+ self.logger.handlers.clear()
+
stream_handler = logging.StreamHandler()
stream_handler.setLevel(console_level)