本文提供了一种在UVM验证过程中,常用的用例自动化回归的脚本。该自动化脚本基于nohup命令实现,包括后台提交测试用例、检测任务进程状态及回归测试报告分析等功能。
一、nohup是什么
nohup 是一个在 Unix 和 Linux 系统中使用的命令,用于运行另一个命令时忽略挂断(HUP)信号。这意味着你可以使用 nohup 来启动一个应用程序或脚本,并确保它在你关闭终端或者注销后继续运行。nohup具备以下几个显著的使用优势,尤其适用于需要长时间运行的任务或后台服务,主要优势如下:
持续运行:使用 nohup 启动的进程即使在用户注销或者终端关闭之后也能继续运行。这对于需要长时间执行的任务非常有用,比如数据处理、文件传输、服务器监控等。
输出重定向:默认情况下,nohup 会将命令的标准输出和标准错误输出重定向到一个名为 nohup.out 的文件中。这有助于保存程序的输出日志,方便后续查看。当然,你也可以手动指定输出文件的位置,以便更好地管理日志文件。
资源利用:通过将任务放到后台运行,可以释放你的终端用于其他任务,提高工作效率。同时,这也意味着系统资源能够被更有效地分配和使用,尤其是在多任务环境下。
简化任务管理:对于需要定期执行的脚本或任务,结合 nohup 使用可以简化任务管理和调度过程。无需复杂的守护进程设置,即可实现简单可靠的后台任务执行方案。
使用 nohup 的基本语法是:
nohup your_command &
这里 your_command 是你希望执行的命令,末尾的 & 符号表示将该命令放到后台执行。默认情况下,nohup 会将命令的输出重定向到一个名为 nohup.out 的文件中,除非你另外指定了输出文件。如下命令,后台运行python脚本,将输出文件指定到output.log
nohup python your_command.py > output.log 2>&1 &
二、脚本实现过程
脚本的实现过程分为四部分,分别为回归列表读取、后台提交测试任务、定期检测后台任务状态、回归测试报告分析,回归脚本使用shell语言实现。
(一) 读取回归列表
shell脚本读取regression_list.f文件,将回归用例及用例参数存储下来,供后续提交任务部分使用。如下代码,读取regression_list.f文件,将每行测试用例存放在line中,并进行打印输出。
num_tc=0
while read line;
do
#read regression_list.f and print tc
let "num_tc=num_tc+1"
echo "$num_tc.$line"
done < regression_list.f
(二) 后台提交测试测任务
将regression_list.f中的测试任务逐行进行后台提交,同时记录测试任务的ID编号,便于后续检测任务状态。
id=0
while read line;
do
#run tc
((id++))
nohup ./run_sim $line &
echo "$id" | tee -a job_id
done < regression_list.f
提交任务2min后,使用jobs -l $id命令查看后台该任务的运行状态,如果任务正在运行中,则返回“Running”;如果任务结束则返回“Done”或“”;如果任务返回“error”,则任务出现问题,打印warning信息,提醒用户关注用例的编译结果。
for id in $(cat ${1});
do
while true
do
sleep 2m
job_info=$(jobs -l $id 2>/dev/null)
job_status=$(echo "$job_info" | awk '{print $3}')
echo "Job $id status: $job_status"
if [[ "$job_status" == @("Running"|"Done") ]];
then
break;
elif [[ $job_status == @("error") ]]
then
echo " !!!!!!!!!!!!!!!!!!!!! WARINING !!!!!!!!!!!!!!!!!!!!!!!!!"
echo " Job is Failed, Please check Compile and Elab!!!"
fi
done
done < job_id
rm -rf job_id
(三) 定期检测后台任务状态
将任务id从job_id文件中逐行读出,将其放入数组job_list[]中。后续轮询检查job_list数组中的任务状态,如果任务已结束,则将其从数组中剔除,直至所有任务结束,跳出轮询检测,进入到下一过程。
while read line;
do
job_list[line_cnt]=$line;
let "line_cnt=line_cnt+1"
done < job_id
rm -rf job_id
echo ${job_list[*]}
while true
do
echo ${job_list[*]}
for i in "${job_list[@]}"
do
sleep 30s
job_info=$(jobs -l %"$i" 2>/dev/null)
job_status=$(echo "$job_info" | awk '{print $3}')
echo "Job1 $i status: $job_status"
if [[ $job_status == @("error"|"Done"|"") ]];
then
let "job_cmp_cnt=job_cmp_cnt+1";
unset 'job_list[(($i-1))]'
fi
done
echo "job_cmp_cnt = $job_cmp_cnt"
echo "line_cnt = $line_cnt"
if [ "$job_cmp_cnt" -eq "$line_cnt" ]
then
break;
fi
done
(四) 分析回归测试报告
用例结束后,将所有测试用例的报告整合为一份log文件,读取log文件,寻找testcase_success或testcase_fail标识。统计用例总数、通过用例个数、失败用例个数与异常结束用例个数,以表格的形式打印出来,方便用例查看结果。
ls ./logfiles/*.log > total_loglist.txt
while read line;
do
if [ "$(find $line -type f -exec grep -l "testcase_success" {} \;)" ]
then
let "PASSCOUNT=PASSCOUNT+1"
echo "$line Test passed"
elif [ "$(find $line -type f -exec grep -l "testcase_failed" {} \;)" ]
then
let "FAILCOUNT=FAILCOUNT+1"
echo "$line !!!--TEST FAILED---!!!"
else
let "NOBANNERCNT=NOBANNERCNT+1"
echo "No Banner for test $line"
fi
done < total_loglist.txt
echo "---------------------------------------------------------------------";
echo "************* VCS Regression Dashboard ************"
echo "---------------------------------------------------------------------";
echo "|Total No of Tests |Tests Passed| Tests Fail | Tests without banner |"
printf "| %3s | %3s | %3s | %3s |\n" "$FILECOUNT" "$PASSCOUNT" "$FAILCOUNT" "$NOBANNERCNT"
echo "---------------------------------------------------------------------";
三、改进与优化
需要添加一些异常场景的处理,提高回归脚本的健壮性。例如某条用例死循环,无法结束的情况。当前只能通过手动kill进程的方式将其停止,后续可在脚本中添加TIMEOUT检测,超时后自动杀死任务,弹出回归测试报告。
每日定时开启回归测试,并且在脚本中添加自动update库上最新代码的命令。可以避开服务器的使用高峰,同时也可以避免人为忘记回归的情况。