operator.py:
import re
import time
import pexpect
import sys
import os
import subprocess
from libs.printer import print_passed, print_failed, print_info, print_error
from libs.args_parser import get_args
from libs.serial_client import SerialClient
from libs.operation import *
from libs.relays_client import *
def check_AVC():
print_info('Check AVC')
adb = AdbOperator()
sys = SysOperation(timeout=30)
adb.__enter__()
ret = adb.send_cmd_result('dmesg |grep avc')
if 'avc:' in ret:
print_error("Matched avc Log")
adb.send_cmd_and_expect('reboot -f',expect_str='Rebooting')
print_info('time sleep 30s')
time.sleep(30)#等待重启
ret = sys.execute_cmd(f'adb -s {adb.device_id} wait-for-device devices')
if ret == "timeout" :
return -99
return -1
def get_calling_script():
calling_scripts = []
def find_caller(frame):
nonlocal calling_scripts
if frame is None or '__main__' in frame.f_globals:
return
caller_path = frame.f_code.co_filename
calling_scripts.append(caller_path)
find_caller(frame.f_back)
find_caller(sys._getframe())
return calling_scripts[-1] if len(calling_scripts) > 0 else ''
class AdbOperator:
def __init__(self, device=None, passwd=None,timeout=5, print_result=True, exec_dir='/oemdata/bin', device_type='AN758', log_number=0, log_path_array=None):
self.args = get_args()
self.timeout = timeout
self.log_str = ''
self.status = 0
self.print_result = print_result # 是否打印结果(passed/failed)
self.need_password = False
if device == None:
self.device_id = self.args.serial
else:
self.device_id = device
if passwd == None:
self.passwd = self.args.passwd
else:
self.passwd = passwd
self.exec_dir = f"{self.args.exec_dir}"
self.exec_dir = exec_dir
self.version = self.args.version
self.phone = self.args.phone
self.puk = self.args.puk
self.pin = self.args.pin
self.operator_id = self.args.operator
self.platform = self.args.platform
self.device_type = self.args.project
self.script_name = os.path.splitext(os.path.basename(get_calling_script()))[0]
self.start_time = time.strftime("%Y%m%d%H%M%S")
#self.log_number = log_number
self.log_path_array = log_path_array
self.id_name_list = []
def copy_log(self):
# 获取当前脚本所在的目录
script_dir = os.path.dirname(os.path.abspath(__file__))
dest_dir = script_dir + '/../log/' + self.script_name + '_' + self.device_id + '_' + self.start_time
os.makedirs(dest_dir, exist_ok=True)
self.get_root_permission()
self.enter_to_module()
self.send_cmd_and_expect('fibo_trustzone_example -l', expect_str='tz_log', timeout=30)
time.sleep(2)
#os.system(f'echo {self.passwd} | adb -s {self.device_id} pull /data/vendor/telsdk/tel.log {dest_dir}')
os.system(f'echo {self.passwd} | adb -s {self.device_id} pull /tmp/tz_log/ {dest_dir}')
#os.system(f'echo {self.passwd} | adb -s {self.device_id} shell dmesg > {dest_dir}/dmesg.log')
os.system(f'echo {self.passwd} | adb -s {self.device_id} pull /etc/misc/wifi {dest_dir}')
os.system(f'cp {script_dir}/../log/serial_log {dest_dir}')
if self.log_path_array is not None:
for log_path in self.log_path_array:
os.system(f'echo {self.passwd} | adb -s {self.device_id} pull {log_path} {dest_dir}')
# 2023-03-14 add by: shi_dian
# 进入adb shell时,可自动识别是否需要root密码
def enter_to_module(self,passwd=None):
"""进入模组"""
print_info(f'adb -s {self.device_id} wait-for-device shell')
p = pexpect.spawn(
'adb', ['-s', self.device_id, 'wait-for-device', 'shell'],
encoding='utf-8',
timeout=self.timeout,
codec_errors='replace'
)
p.logfile_read = sys.stdout
self.p = p
expect_ret = p.expect(['Enter root Passwd:','Enter user Passwd:' ,pexpect.EOF, pexpect.TIMEOUT], timeout=3)
#exec_result += str(p.before)
#if p.after is not None and type(p.after) is str:
# exec_result += str(p.after)
if expect_ret == 0 or expect_ret == 1:
self.need_password = True
time.sleep(1)
# 需要输入root时,输入root密码
#print_info(f'input root passwd={self.passwd}')
if passwd:
p.sendline(passwd)
else:
p.sendline(self.passwd)
ret = p.expect(['\#', '\$' ,pexpect.EOF, pexpect.TIMEOUT], timeout=10)
if ret == 3:
relays = RelaysClient()
print_info('######################################')
print_info('ERROR: Not Find USB Go To Hard Restart')
print_info('######################################')
self.set_status_failed()
relays.__enter__()
relays.set_reset_connect_once()
relays.__exit__()
try:
self.p.expect(pexpect.TIMEOUT, timeout=1)
except Exception as e:
print_error(f'Exception={e}')
pass
#exec_result += str(p.before)
#self.log_str += exec_result
#print(self.log_str)
#print(f'platform_name={self.platform}')
#if self.platform in ['SA6125']:
# self.send_cmd_and_return('export LD_LIBRARY_PATH=/tbox/umdp/lib')
# self.send_cmd_and_return("export LD_LIBRARY_PATH='/tbox/umdp/lib:/vendor/lib64:/system/lib64'")
# self.send_cmd_and_return('export LD_LIBRARY_PATH=\'/tbox/umdp/lib:/vendor/lib64:/system/lib64\'',
# 'export LD_LIBRARY_PATH.*system/lib64[^\n]*', timeout=10)
return p
def open_test(self, test_name, parse_menu=False, exp_str=None, timeout=None,test_dir=None):
"""打开test demo"""
exec_test_dir = self.exec_dir
if test_dir:
exec_test_dir = test_dir
#print_info(f'{test_name} run test case start')
if exp_str is None:
ret = self.send_cmd_and_expect(f'.{exec_test_dir}/{test_name}')
else:
ret = self.send_cmd_and_expect(f'.{exec_test_dir}/{test_name}', expect_str=f'{exp_str}', timeout=timeout)
time.sleep(2)
if parse_menu:
try:
self.p.expect(pexpect.TIMEOUT, timeout=2)
except Exception as e:
print(f'Exception={e}')
finally:
log = ''
if self.p.before is not None:
log = self.p.before.strip()
temp_cmd_list = log.splitlines()
id_name_list = []
for line_str in temp_cmd_list:
if re.match('\\d*:.', line_str):
temp = line_str.replace('\t', '').replace('\n', '').replace('\r', '')
temp_list = temp.split(':')
obj_dict = dict()
obj_dict['id'] = temp_list[0]
obj_dict['name'] = temp_list[1]
id_name_list.append(obj_dict)
self.id_name_list = id_name_list
#print('------------- menu item ------------')
# print(self.id_name_list)
# for item in self.id_name_list:
# print(item)
return ret
def open_tz_test(self, test_name, parse_menu=False, exp_str=None, timeout=None):
"""打开test demo"""
exec_test_dir = self.exec_dir
#print_info(f'{test_name} run test case start')
if exp_str is None:
ret = self.send_cmd_and_expect(f'./{test_name}')
else:
ret = self.send_cmd_and_expect(f'./{test_name}', expect_str=f'{exp_str}', timeout=timeout)
time.sleep(2)
if parse_menu:
try:
self.p.expect(pexpect.TIMEOUT, timeout=2)
except Exception as e:
print(f'Exception={e}')
finally:
log = ''
if self.p.before is not None:
log = self.p.before.strip()
temp_cmd_list = log.splitlines()
id_name_list = []
for line_str in temp_cmd_list:
if re.match('\\d*:.', line_str):
temp = line_str.replace('\t', '').replace('\n', '').replace('\r', '')
temp_list = temp.split(':')
obj_dict = dict()
obj_dict['id'] = temp_list[0]
obj_dict['name'] = temp_list[1]
id_name_list.append(obj_dict)
self.id_name_list = id_name_list
#print('------------- menu item ------------')
# print(self.id_name_list)
# for item in self.id_name_list:
# print(item)
return ret
def get_id_by_name(self, name):
for temp in self.id_name_list:
if temp['name'].lower() == name.lower():
# print(f'\n\n{temp}', end='')
return temp['id']
print_error(f'----------------------- get_id_by_name() 没有找到选项: name={name} -------------------')
return str(-1)
def send_cmd_and_expect(self, cmd=None, expect_str=None, timeout=None):
"""发送命令并判断期望的字符串是否出现"""
if cmd != None:
self.p.sendline(cmd)
if expect_str:
# 如果没有匹配到任何字符则抛出异常
if timeout is None:
nowstatus = self.p.expect([expect_str, pexpect.EOF, pexpect.TIMEOUT])
else:
nowstatus = self.p.expect([expect_str, pexpect.EOF, pexpect.TIMEOUT], timeout=timeout)
if nowstatus != 0:
self.status = nowstatus
print_error(f'not match:{expect_str} nowstatus:{nowstatus}')
#else:
# print(f'match {expect_str}')
#self.print_log()
#print(f'--- current status: {nowstatus} ---')
return nowstatus
time.sleep(0.5)
return 0
def send_cmd_and_return(self, cmd = None, expect_str=None, timeout=None):
"""发送命令并查找返回匹配的字符串,未匹配到返回None"""
if cmd != None:
self.p.sendline(cmd)
if expect_str:
if timeout is None:
nowstatus = self.p.expect([expect_str, pexpect.EOF, pexpect.TIMEOUT])
else:
nowstatus = self.p.expect([expect_str, pexpect.EOF, pexpect.TIMEOUT], timeout=timeout)
#self.print_log()
#print(f'--- current status: {nowstatus} ---')
if nowstatus == 0: # 匹配到
print_info(f'match:{expect_str}')
return self.p.after
else:
return None
def send_cmd_and_return_stdout(self, cmd, timeout=20):
"""发送命令并返回输出的字符串"""
self.p.expect(r".*", timeout=1) # 非阻塞读取所有已有数据
self.p.sendline(cmd)
self.p.expect([pexpect.EOF, pexpect.TIMEOUT], timeout=timeout)
stdout = self.p.before
return stdout
def send_cmd_result(self, cmd):
try:
"""发送命令并查找返回结果"""
res = self.p.sendline(cmd)
self.p.expect('sftp>')
except Exception as e:
print(f'Exception={e.msg}')
finally:
if self.p.before is None:
return ''
return self.p.before.strip()
def send_cmd_exp_list(self, cmd_exp_list, sleep_time=2):
"""执行多条命令和期望值来判断返回的status是否为0,为0则成功,否则失败"""
for cmd, exp_str in cmd_exp_list:
self.status = self.send_cmd_and_expect(cmd, expect_str=exp_str)
if self.status != 0:
break
time.sleep(sleep_time)
return self.status
def send_clear_expect_data(self):
#清空expect后的数据,保证下次期待值为输入指令后的输出
self.p.expect(r".*", timeout=1) # 非阻塞读取所有已有数据
def exit_test(self, cmd='-1'):
"""退出测试demo,发送-1"""
self.send_cmd_result(cmd)
def print_log(self):
"""打印当前信息"""
if isinstance(self.p.after, str): # 匹配到
expect_log_str = self.p.before + self.p.after
self.log_str += expect_log_str
print(expect_log_str)
else:
print_info(f"not find expect info") # Add by hla 2022/6/20
print(self.p.before) # Add by hla 2022/6/20
print(self.p.after) # <class 'pexpect.exceptions.TIMEOUT'>
def get_log_str(self):
"""获取日志信息"""
# remaining_log = self.p.read()
# if isinstance(remaining_log, str):
# print(remaining_log)
# self.log_str += remaining_log
# Modified by HLA,2022-6-27,self.p.read()会遇到读取异常的场景,添加异常处理
try:
remaining_log = self.p.read()
if isinstance(remaining_log, str):
print(remaining_log)
self.log_str += remaining_log
except:
remaining_log = 'get_log_str error'
print(remaining_log)
self.log_str += remaining_log
def check_status(self):
"""检查状态"""
if self.status == 0:
print_passed()
else:
print_failed()
def is_fail(self):
if self.status == 0:
return False
else:
return True
def set_status(self, status):
self.status = status
def get_status(self):
return self.status
def set_status_failed(self):
print_error('Set Test Result To Fail')
self.status = -100
def is_need_password(self):
return self.need_password
def get_root_permission(self,timeout=60,passwd=None):
"""获取root权限"""
count = 0
while count < 2:
'''
if self.device_type == 'AN960':
print_info(f'adb -s {self.device_id} wait-for-device root')
p = pexpect.spawn(
'adb', ['-s', self.device_id, 'wait-for-device', 'root'],
encoding='utf-8',
timeout=5,
)
else:
print_info(f'adb -s {self.device_id} wait-for-device shell root')
p = pexpect.spawn(
'adb', ['-s', self.device_id, 'wait-for-device', 'shell','root'],
encoding='utf-8',
timeout=5,
)
'''
print_info(f'adb -s {self.device_id} wait-for-device shell root')
p = pexpect.spawn(
'adb', ['-s', self.device_id, 'wait-for-device', 'shell','root'],
encoding='utf-8',
timeout=5,
)
p.logfile_read = sys.stdout
time.sleep(0.1)
ret = p.expect(['adb root success', 'Enter root Passwd:', 'adb has running as root', 'adbd is already running as root', 'adb is already running as root', 'root: not found','restarting adbd as root', pexpect.EOF, pexpect.TIMEOUT], timeout=timeout)
if ret == 0:
print_info('adb root success, current device dose not use passwd.')
time.sleep(1) # wait 1s for root permission to take effect.
count = 2
elif ret == 1:
if passwd:
p.sendline(passwd)
else:
p.sendline(self.passwd)
time.sleep(0.1)
passwd_status = p.expect(['adb root success', 'Error root Passwd'])
if passwd_status == 0:
print_info('get root permission success.')
time.sleep(1)
else:
print_error('get root permission failed.')
count = 2
elif ret == 6:
print_info('try again because eof.')
count = count + 1
elif ret == 7:
print_info('try again because timeout.')
count = count + 1
else:
#print_info(f'ret is {ret}.')
count = 2
def get_oemdata_permission(self):
"""get permission of /oemdata."""
#print_info('mount -T . -o remount,exec /oemdata')
#cmd = './mnt/sdcard/run_rild.sh'
cmd = 'mount -T . -o remount,exec /oemdata'
self.send_cmd_and_expect(cmd, '[#$]')
# self.send_cmd_and_expect(cmd, r"\[PEXPECT\][\$\#] ") # PS1='[PEXPECT]\$ '
def run_telsdk_subsystem(self):
if 0 != self.send_cmd_and_expect('ps -ef | grep rild',expect_str='rild -l'):
self.send_cmd_and_expect('./mnt/sdcard/run_rild.sh')
time.sleep(2)
# def set_device_sleep(self):
# gpio = SerialClient(serialType = SERIAL_TYPE_CONTROL)
# gpio.__enter__()
# self.open_test('telux_power_test_app -s')
# time.sleep(1)
# gpio.set_usb_line_disconnect()
# gpio.__exit__()
# def set_device_shutdown(self):
# gpio = SerialClient(serialType = SERIAL_TYPE_CONTROL)
# gpio.__enter__()
# self.open_test('telux_power_test_app -p')
# time.sleep(2)
# gpio.set_power_line_disconnect()
# gpio.__exit__()
def __enter__(self):
self.get_root_permission()
self.p = self.enter_to_module()
time_result = subprocess.run(['date', '-u', '+%Y-%m-%d %H:%M:%S'], capture_output=True, text=True)
self.send_cmd_and_expect(f'date -s "{time_result.stdout.strip()}"')
#self.get_oemdata_permission()
#if self.device_type != 'AN960':
# self.run_telsdk_subsystem()
return self
def __exit__(self, exc_type=None, exc_val=None, exc_tb=None):
"""退出"""
if exc_type:
print('遇到异常了,异常信息为:', exc_type, exc_val, exc_tb)
# print(f'### exit module {self.device_id} ###')
# self.get_log_str()
# if self.status != 0:
# self.copy_log()
if self.print_result:
self.check_status()
# return True # 抛出错误
# class NWOperator(AdbOperator):
# def set_network(self, mode, nw_type=''):
# print(f"set_network() mode={mode}, nw_type={nw_type}")
# """注网"""
# if mode in ['0x10', '0x40']:
# self.check_ims_status()
# self.open_test('nw_test')
# # fibo_nw_client_init
# self.send_cmd_and_expect('0', expect_str='ret\\s*[:=]\\s*0[^\n]*')
# # fibo_nw_set_config
# self.send_cmd_and_expect('1')
# # please input mode config hex(0x01:CDMA; 0x02:EVDO; 0x04:GSM; 0x08:UMTS; 0X10:LTE; 0x20:TDSCDMA; 0x40:SA; 0x80:AUTO)
# self.send_cmd_and_expect(mode)
# # please input roaming pref(0:off 1:on)
# self.send_cmd_and_expect('1', expect_str='ret\\s*[:=]\\s*0[^\n]*')
# time.sleep(5)
# for i in range(5):
# status = self.send_cmd_and_return('7', f'radio_tech:\\s*{nw_type}[^\n]*', timeout=10)
# if status != None:
# break
# self.exit_test()
# if status != None:
# print('### 注网成功 ###')
# return 0
# else:
# self.status = 2 # 标记用例失败
# print('### 注网失败 ###')
# return 2
# def get_network(self):
# """获取当前网络状态"""
# self.open_test('at_test')
# self.send_cmd_and_expect('AT+COPS?', 'COPS: 0,0,\".*?\",(\d+)')
# nw_status = self.p.match.group(1)
# print(f'### 当前网络状态码为{nw_status} ###')
# self.exit_test()
# return nw_status
# def check_ims_status(self):
# """
# 检测IMS是否被激活(二路获取到IP地址则为激活状态)
# """
# print('### 正在检测ims是否被激活 ###')
# self.open_test('nw_test')
# self.send_cmd_and_expect('0') # fibo_nw_client_init
# # self.send_cmd_and_expect('22', 'ims value:(\d)') # fibo_nw_get_ims
# ims_status = self.send_cmd_and_return('22', 'ims value:(\d)')
# # ims_status = self.p.match.group(1)
# if ims_status == 'ims value:1':
# print('### ims已被激活 ###')
# else:
# print('### 检测到ims尚未激活,正在重新激活 ###')
# self.send_cmd_and_expect('23')
# self.send_cmd_and_expect('1', 'fibo_nw_set_ims return:0')
# print('### 成功激活ims ###')
# self.exit_test()
# def set_ims_status(self, status):
# """
# 设置IMS状态(0-disable, 1-enable)
# :param status: ims状态
# :return:
# """
# self.open_test('nw_test')
# self.send_cmd_and_expect('0') # fibo_nw_client_init
# self.send_cmd_and_expect('23') # fibo_nw_client_init
# self.send_cmd_and_expect(status)
# self.send_cmd_and_expect('22', 'ims value:\d')
# print(f'### 设置IMS成功,当前状态为{status} ###')
# self.exit_test()
# class VoiceOperator(AdbOperator):
# def __init__(self, device_id, passwd, timeout=30, print_result=True,phone=None):
# super().__init__(device_id, passwd, timeout, print_result,exec_dir='/usr/bin',device_type='')
# self.phone = phone
# def init_voice_client(self):
# """初始化voice_client, 开启主动上报"""
# print(f'### 正在初始化模组{self.device_id}的voice_test ###')
# self.send_cmd_and_expect('0') # Fibo_VOICE_Client_Init
# self.send_cmd_and_expect('12') # Fibo_VOICE_Call_AddStateHandle
# self.send_cmd_and_expect('18') # fibo_voice_register_bitmask
# self.send_cmd_and_expect('1') # bitmask mode 0x01 ->call event
# def call(self):
# """拨打电话"""
# print(f'### 模组{self.device_id}拨打电话,号码为{self.phone} ###')
# self.open_test('telsdk_console_app')
# self.send_cmd_and_expect('2', expect_str='Dialer Menu')
# self.send_cmd_and_expect('4 1')
# self.send_cmd_and_expect('4 2') #hangup all Inprogress call
# self.send_cmd_and_expect(f'1 {self.phone}', expect_str='makeCall response ErrorCode: 0') # phone number
# self.send_cmd_and_expect('0', expect_str='Telematics SDK') #exit Data Menu
# self.exit_test('0')
# def answer(self):
# """接听电话"""
# self.open_test('telsdk_console_app')
# self.send_cmd_and_expect('2', expect_str='Dialer Menu')
# self.send_cmd_and_expect(expect_str='Enter 2 to answer call', timeout=60) #wait incoming call
# self.send_cmd_and_expect('2', expect_str='Call State: Active call',timeout=10)
# self.send_cmd_and_expect('0', expect_str='Telematics SDK') #exit Data Menu
# self.exit_test('0')
# def Hangup(self):
# """挂断电话"""
# self.open_test('telsdk_console_app')
# self.send_cmd_and_expect('2', expect_str='Dialer Menu')
# self.send_cmd_and_expect('4 1')
# self.send_cmd_and_expect('4 2')
# self.send_cmd_and_expect('0', expect_str='Telematics SDK') #exit Data Menu
# self.exit_test('0')
# def AirplaneSIM(self):
# """SIM卡飞行模式"""
# self.open_test('telsdk_console_app')
# self.send_cmd_and_expect('1', expect_str='Phone Menu')
# self.send_cmd_and_expect('6', expect_str='Enter Operating Mode')
# self.send_cmd_and_expect('1')
# self.send_cmd_and_expect('0', expect_str='Telematics SDK') #exit Data Menu
# self.exit_test('0')
# def OnlineSIM(self):
# """SIM ONLINE"""
# self.open_test('telsdk_console_app')
# self.send_cmd_and_expect('1', expect_str='Phone Menu')
# self.send_cmd_and_expect('6', expect_str='Enter Operating Mode')
# self.send_cmd_and_expect('0')
# self.send_cmd_and_expect('0', expect_str='Telematics SDK') #exit Data Menu
# self.exit_test('0')
# def DisableIMS(self):
# """电话关机"""
# self.open_test('telsdk_console_app')
# self.send_cmd_and_expect('10', expect_str='IMS Settings Menu')
# self.send_cmd_and_expect('2', expect_str='Available IMS Service configurations')
# self.send_cmd_and_expect('1', expect_str='Enable/Disable config')
# self.send_cmd_and_expect('0', expect_str='Select the configuration type')
# self.send_cmd_and_expect('q', expect_str='VOIMS is disabled')
# self.send_cmd_and_expect('0', expect_str='Telematics SDK')
# self.exit_test('0')
# def EnableIMS(self):
# """电话开机"""
# self.open_test('telsdk_console_app')
# self.send_cmd_and_expect('10', expect_str='IMS Settings Menu')
# self.send_cmd_and_expect('2', expect_str='Available IMS Service configurations')
# self.send_cmd_and_expect('1', expect_str='Enable/Disable config')
# self.send_cmd_and_expect('1', expect_str='Select the configuration type')
# self.send_cmd_and_expect('q', expect_str='VOIMS is enabled')
# self.send_cmd_and_expect('0', expect_str='Telematics SDK')
# self.exit_test('0')
根据上面提供的函数编写测试脚本:
用例编号:MT273X.DRJK.PTC.SYS.NET.DEV.PHY.002.002
用例名称:MT2735_东软CN_以太网驱动适配_SGMII/RGMII驱动切换
开发单:AN758CNH06-105
前置条件:
1.ADP或客户样机一台
测试步骤:
1.开机上电后,查询串口日志是否有RGMII Mode的打印
2.给C56输入高电平,重启模组或样机查看日志是否有RGMII Mode的打印
预期结果:
1.有RGMII Mode的打印
2.有RGMII Mode的打印