20230322
[shlib.git] / bin / attr
blob0e5c7e5c4429c1156fbd3956578c4208c7439c88
1 #!/bin/bash
2 ############################################################
3 # source: attr
4 # author: devenkong(18151155@qq.com)
5 # date: 2022-12-05
6 ############################################################
7 # note:
8 # attr is a cmd for attr variable info display, while env
9 # is a cmd for environment variable info display. attr is based
10 # on env var, it filter env var by prefix string, and dispaly
11 # info about attr.
13 ############################################################
16 # todo:
17 # @
18 # @
22 . shlibinc
25 include stdio.shlib
26 include term.shlib
27 include args.shlib
29 include attr.shlib
30 include cataid.shlib
33 ##############################
34 # section: public comment info
35 ##############################
39 ##############################
40 # section: variable define
41 ##############################
44 xxx="
45 param -l --list --- = %<catalog_list> !<args_catalog_list> '列出testing目录下的测试单元/模块/目录,及测试项。'
46 param -S --save --- =<save_desc_file> %<save_desc_file> !<args_save_desc_file> '根据测试目录下的测试文件目录结构,生成测试信息描述文件。如果文件已存在,只显示提示信息。添加-f参数用于覆盖生成的文件。'
47 param -y --sync --- =[vsync_to_test_frame] %<sync_to_test_frame> !<args_sync_to_test_frame> '根据测试信息描述文件,生成测试目录及测试脚本等文件,用于用户编写各种测试用例。'
49 param -n --num --- =<task_exec_cnt> %<task_exec_cnt> ! '测试N个testcase。'
50 param -t --test --- =<test_id> %<test_id> !<args_test_id> '根据指定测试编号运行测试脚本。用于测试目录下的所有测试脚本,'
51 '或指定一个测试脚本。当该参数不添加参数时,表示保存的起始id开始的单项测试。'
52 param -b --begin --- =<begin_test_id> %<begin_test_id> !<args_begin_test_id> '从该id值开始测试。'
53 param -e --end --- =<end_test_id> %<end_test_id> !<args_end_test_id> '测试到该id值为止。'
54 param -x --exclude --- =<exclude_id> %<exclude_id> !<args_exclude> '从该id值开始测试。'
55 param -R --rollup --- = %<test_id_rollup> !<args_test_id_rollup> '保存的测试起始编号加1,用于表示当前项测试后进入下一项测试。'
56 param -B --rollback --- = %<test_id_rollback> ! '测试n项item。'
58 param -d --dir --- =<test_dir> %<test_dir> ! '指定测试信息的目录。默认值为当前目录下的testing目录。'
60 param -C --config --- = %<config_file> !<args_config_file> '保存-b和-e参数设置的测试范围。-n参数测试时在该范围内测试。'
62 param -s --set --- = %<set_test_info> !<args_set_test_info> '保存-b和-e参数设置的测试范围。-n参数测试时在该范围内测试。'
63 param -c --clean --- = %<clean> !<args_clean> '将保存的起始和结束id,以及lastfailed-id删除,并删除测试目录下的临时文件。'
65 param -m --mono --- = %<mono> !<args_mono> '输出非彩色的字符串信息。'
66 param -V --version --- = %<version_info> !<args_version_info> '程序的版本信息。'
67 param -h --help --- = %<help_info> !<help_info> '程序的参数helper信息。'
70 usage="usage: $(basename $0) [options]
72 This program process catalog id file and dir structrue.
74 option descript:
75 -l list items under catalog path, specified by -d <path>.
76 -S <desc_file> save catalog file from dir.
77 -y syncronize between catalog file and dir.
79 -n <count> execute item by <count> times.
80 -t <cata-id> execute the item by specified cata-id.
82 -b <cata-id> execute begin with cata-id.
83 -e <cata-id> stop execute at cata-id.
84 -x <cata-id> execlude cata-id when executing.
85 -R increase begin id.
86 -B decrease begin id to last cata-id.
88 -d <path> the dir path syncronize with catalog file.
90 -C <cataid_file> file to store begin & end cata id
91 -s save begin & end cata id to file specified by -C paramter.
92 -c helper information.
94 -m display with mono charactor.
95 -V verion information.
96 -h helper information.
99 # lS:yn:t:b:e:x:RBd:C:scmVh
101 ##############################
102 # section: private function
103 ##############################
106 # 描述文件中第一个有效行的空格数或tab数为缩进字符串的单位,用于计算目录层数。
107 # tabh空格不能混用。
109 testcase_framework_gen ()
111 local type=
112 local id=
113 local name=
114 local desc=
115 local tmp=$1
116 local lastcnt=0
117 local cnt=0
118 local tab
119 local tabcnt
120 local i
121 local xxx
122 local tabstr
124 # 使用' '时 read读取数据,' '用于分隔。
125 IFS_OLD=$IFS
126 IFS=$'\n'
128 cd $catalog_path
130 tmp=${tmp:-"funclist.txt"}
131 if [[ ! -e $tmp ]]; then
132 err "function list file '$tmp' is not exist.\n"
133 exit
136 cp $tmp $TESTING_TMP_DIR/
137 tmp=$TESTING_TMP_DIR/`basename $tmp`
138 dos2unix $tmp
139 while read -r line; do
140 [[ $verbose == "enable" ]] && dbgoutd "line=$line\n"
141 [[ ! $line =~ "[" || ${line:0:1} == '#' ]] && continue
143 # 使用第一个有效行的空格数为tabcnt
144 IFS=' '
145 tmp=${line%%[*}
146 tmp=${tmp//[^ ]/}
148 # dbgoutd "tmp=(${tmp[@]})\n"
149 # dbgoutd "tmp=(${#tmp[@]})\n"
151 # echo "$tmp" | dbgout_cmd hexdump
152 tmp=`echo "$tmp" | wc -c`
154 # dbgoutd "tmp=$tmp\n"
155 lastcnt=${cnt:-"$((tmp-1))"}
156 cnt=$(( tmp-1 ))
157 [[ -z $tabcnt ]] && tabcnt=$(( tmp-1 )) && tabstr=`printf "%*s" $((tab*tabcnt)) " "`
158 [[ $tabcnt == 0 ]] && tabcnt=4 && tabstr=`printf "%*s" $((tab*4)) " "`
159 tab=$(( cnt/${tabcnt:-'4'} ))
161 # dbgoutd "cnt=$cnt\n"
162 # dbgoutd "lastcnt=$lastcnt\n"
163 # dbgoutd "tab=$tab\n"
165 # 字符串冗余符号处理
166 line=`echo $line | tr '.' ' ' | tr -s "[\t| ]"`
167 IFS=' '
168 line=( $line )
169 IFS=$'\n'
170 # dbgoutd "tmp=(${line[@]})\n"
171 type=${line[0]}
172 id=${line[1]}
173 name=${line[2]}
174 desc=${line[3]}
176 type=${type:1}
177 type=${type%]*}
179 # 根据缩进字符数判断所需创建的目录结构
180 if [[ $cnt -gt $lastcnt ]]; then
181 if [[ -n $lastdir ]]; then
182 [[ ! -d $lastdir ]] && dbgoutd "create dir ($lastdir)\n" && mkdir -p $lastdir
183 cd $lastdir
184 # dbgoutd "cd $lastdir\n"
186 elif [[ $cnt -eq $lastcnt ]]; then
187 if [[ "${lastdir##*.}" =~ "txt" ]]; then
188 # [[ -n $lastdir ]] && dbgoutd "item $lastdir\n"
189 [[ ! -e "$lastdir" ]] && dbgoutd "create item ($lastdir)\n" && touch $lastdir && touch ${lastdir%.sh*}.sh
190 else
191 [[ ! -d "$lastdir" ]] && dbgoutd "create dir ($lastdir)\n" && mkdir -p $lastdir
193 else
194 if [[ "${lastdir##*.}" =~ "txt" ]]; then
195 # [[ -n $lastdir ]] && dbgoutd "item $lastdir\n"
196 [[ ! -e "$lastdir" ]] && dbgoutd "create item ($lastdir)\n" && touch $lastdir && touch ${lastdir%.sh*}.sh
197 else
198 [[ ! -d "$lastdir" ]] && dbgoutd "create dir ($lastdir)\n" && mkdir -p $lastdir
200 for (( i=cnt/tabcnt; i < lastcnt/tabcnt; i++ )); do
201 cd ..
202 done
203 # dbgoutd "cd ..\n"
206 case $type in
207 "module" | "unit" | "dir" )
208 # printf "%*s" $((tab*4)) " "
209 # dbgoutd "$id.$name.$type\n"
210 lastdir="$id.$name.$desc.$type"
212 "item" )
213 # printf "%*s" $((tab*4)) " "
214 # dbgoutd "$id.$name.sh.$desc.txt\n"
216 lastdir="$id.$name.sh.$desc.txt"
219 warn "unkown type [$type] ($line)\n"
221 esac
223 done < $tmp
225 # last配置项
226 if [[ $cnt -gt $lastcnt ]]; then
227 if [[ -n $lastdir ]]; then
228 [[ ! -d $lastdir ]] && dbgoutd "create dir ($lastdir)\n" && mkdir -p $lastdir
229 cd $lastdir
230 # dbgoutd "cd $lastdir\n"
232 elif [[ $cnt -eq $lastcnt ]]; then
233 if [[ "${lastdir##*.}" =~ "txt" ]]; then
234 [[ ! -e "$lastdir" ]] && dbgoutd "create item ($lastdir)\n" && touch $lastdir && touch ${lastdir%.sh*}.sh
235 else
236 [[ ! -d "$lastdir" ]] && dbgoutd "create dir ($lastdir)\n" && mkdir -p $lastdir
238 else
239 if [[ "${lastdir##*.}" =~ "txt" ]]; then
240 [[ ! -e "$lastdir" ]] && dbgoutd "create item ($lastdir)\n" && touch $lastdir && touch ${lastdir%.sh*}.sh
241 else
242 [[ ! -d "$lastdir" ]] && dbgoutd "create dir ($lastdir)\n" && mkdir -p $lastdir
244 for (( i=cnt/tabcnt; i < lastcnt/tabcnt; i++ )); do
245 cd ..
246 done
247 # dbgoutd "cd ..\n"
250 IFS=$OLD_IFS
252 task_subject=task
254 # fsyntax: task_paths_init [<base-tmp-dir>]
255 # fdesc:
256 task_paths_init ()
259 # task目录使用-d参数对应的catalog_dir环境变量
260 # 指定的目录作为task信息目录。
261 # 默认为当前路径下的task目录。
263 if [[ -n $catalog_dir ]]; then
264 if [[ -d $catalog_dir ]]; then
265 catalog_path=$catalog_dir
266 else
267 err "err: parameter -d specified a invalid path $catalog_dir\n"
268 exit
272 if [[ ! -d $catalog_path ]]; then
273 catalog_path="$task_subject/"
276 [[ ! -d $catalog_path ]] && err "err: task dir '$catalog_path' is not exist.\n" && exit
278 # get absolutly path
279 mkdir -p $catalog_path
280 cd $catalog_path
281 catalog_path=$PWD
282 cd - > /dev/null
285 # task的tmp目录设置
286 # 目录名称添加testcase路径的cksum,避免同一个软件包不同目录时,
287 # 使用同一个tmp目录。
289 TESTING_TMP_DIR=$(basename $0)-$TESTING_TMP_DIR
290 if [[ -n $1 ]]; then
291 TESTING_TMP_DIR="$1/"
292 [[ -d $1 ]] && TESTING_TMP_DIR=~/.task/ && warn "directoy specified \"$1\" is not existing, use default directrory \"$TESTING_TMP_DIR\" instead.\n"
293 else
294 TESTING_TMP_DIR=~/.task/
297 mkdir -p $TESTING_TMP_DIR
298 cd $TESTING_TMP_DIR
299 TESTING_TMP_DIR=$PWD
300 cd - > /dev/null
302 TESTING_TMP_DIR=$TESTING_TMP_DIR/$(basename $0)-$(echo $catalog_path | cksum - | cut -d ' ' -f1)
304 mkdir -p $TESTING_TMP_DIR
306 # echo TESTING_TMP_DIR = $TESTING_TMP_DIR
309 # 列出指定目录下的task内容,包括模块、单元、目录、task项
310 # catalog_dir_list_content <path>
311 catalog_dir_list_curr_content ()
313 local tmp=0
314 local script_name=
315 local catalog_dir_desc=
317 catalog_dir_list_depth=$((catalog_dir_list_depth++))
319 # dbgoutd "curr content $1\n"
320 ls $1 | sort -n |
321 while read file; do
322 # 忽略.txt文件,在处理.sh文件时再进行处理
323 [[ $file =~ ".txt" ]] && continue
325 # 以小数点分隔,包含3个字符串的为task脚本
326 # 包含3个字符串的为task模块/单元/目录
327 # 包含5个字符串的为task项信息描述文件
328 OLD_IFS=$IFS
329 IFS="."
330 tmp=( $file )
331 IFS=$OLD_IFS
332 # echo "tmp(${#tmp[@]}) = ${tmp[@]}"
334 # todo:添加非数字idx过滤
335 # [[ ${tmp[1]} =~ "^[:digital:]" ]] && continue
337 if [[ ${#tmp[@]} == 5 ]]; then
338 catalog_dir_desc=`ls -d -1 $file.*.txt`
339 [[ -z $catalog_dir_desc ]] && echo "err: txt descript file not found for $file." >&2 && return 1
340 catalog_dir_desc=${catalog_dir_desc#$file\.}
341 catalog_dir_desc=${catalog_dir_desc%\.txt}
342 script_name=${tmp[1]}
343 elif [[ ${#tmp[@]} == 4 ]]; then
344 case ${tmp[3]} in
345 "module" )
346 echo "${tmp[3]} ${tmp[0]} ${tmp[2]} ${tmp[1]}"
348 "unit" )
349 echo "${tmp[3]} ${tmp[0]} ${tmp[2]} ${tmp[1]}"
351 "dir" )
352 echo "${tmp[3]} ${tmp[0]} ${tmp[2]} ${tmp[1]}"
354 esac
355 elif [[ ${#tmp[@]} == 3 ]]; then
356 if [[ "${tmp[2]}" == "sh" ]]; then
357 catalog_dir_desc=`ls -d -1 $file.*.txt`
358 [[ -z $catalog_dir_desc ]] && echo "err: txt descript file not found for $file." >&2 && return 1
359 catalog_dir_desc=${catalog_dir_desc#$file\.}
360 catalog_dir_desc=${catalog_dir_desc%\.txt}
362 echo "item ${tmp[0]} $catalog_dir_desc ${tmp[1]}"
365 done
367 catalog_dir_list_depth=$((catalog_dir_list_depth--))
371 # fsyntax: catalog_linedata_dispatch
372 # fdesc: catalog文件中一行字符串的解析函数。输出到CATALOG_ITEM[]数组,以及CATALOG_LVL。
373 catalog_linedata_dispatch ()
375 CATALOG_LVL=
376 CATALOG_ITEM=
380 CATALOG_ITEM_FILES=
381 CATALOG_ITEM_COLUMS=
384 # fsyntax: catalog_linedata_dispatch
385 # fdesc: CATALOG_ITEM_FILES数组中放置id的文件列表,解析成item的格式,并保存到
386 # CATALOG_ITEM_COLUMS中。
387 catalog_filename_dispatch ()
389 CATALOG_LVL=
390 CATALOG_ITEM=
395 # catalog_dir_list_full_content <catalog_dir>
396 catalog_dir_list_full_content ()
398 local tmp=
399 local catalog_dir=$1
401 cd $1
402 catalog_dir_list_curr_content $catalog_dirs |
403 while read line; do
404 tmp=( $line )
405 case ${tmp[0]} in
406 "item" )
407 catalog_dir_level=$(( catalog_dir_level + 1 ))
408 TPREFIX=`printf "%*s" $(( $catalog_dir_level * 4)) " "`
410 echo -ne "$TPREFIX[item] ${tmp[1]} ${tmp[3]} ${tmp[2]}\n"
412 catalog_dir_level=$(( catalog_dir_level - 1 ))
413 TPREFIX=`printf "%*s" $(( $catalog_dir_level * 4)) " "`
415 "module" | "unit" | "dir" )
416 catalog_dir_level=$(( catalog_dir_level + 1 ))
417 TPREFIX=`printf "%*s" $(( $catalog_dir_level * 4)) " "`
419 echo -ne "$TPREFIX[${tmp[0]}] ${tmp[1]} ${tmp[3]} ${tmp[2]}\n"
421 catalog_dir_list_full_content ${tmp[1]}.${tmp[3]}.${tmp[2]}.${tmp[0]}
423 catalog_dir_level=$(( catalog_dir_level - 1 ))
424 TPREFIX=`printf "%*s" $(( $catalog_dir_level * 4)) " "`
426 esac
427 done
428 cd ..
431 catalog_item_list ()
433 local tmp=
434 local catalog_dir=$1
436 cd $1
437 catalog_dir_list_curr_content $catalog_dir |
438 while read line; do
439 tmp=( $line )
440 case ${tmp[0]} in
441 "item" )
442 catalog_dir_level=$(( catalog_dir_level + 1 ))
443 TPREFIX=`printf "%*s" $(( $catalog_dir_level * 4)) " "`
445 echo -ne "$TPREFIX[item] ${tmp[1]} ${tmp[3]} ${tmp[2]}\n"
447 catalog_dir_level=$(( catalog_dir_level - 1 ))
448 TPREFIX=`printf "%*s" $(( $catalog_dir_level * 4)) " "`
450 "module" | "unit" | "dir" )
451 catalog_dir_level=$(( catalog_dir_level + 1 ))
452 TPREFIX=`printf "%*s" $(( $catalog_dir_level * 4)) " "`
454 echo -ne "$TPREFIX[${tmp[0]}] ${tmp[1]} ${tmp[3]} ${tmp[2]}\n"
456 catalog_dir_list_full_content ${tmp[1]}.${tmp[3]}.${tmp[2]}.${tmp[0]}
458 catalog_dir_level=$(( catalog_dir_level - 1 ))
459 TPREFIX=`printf "%*s" $(( $catalog_dir_level * 4)) " "`
461 esac
462 done
463 cd ..
466 ##############################
467 # section: public function
468 ##############################
472 # fsyntax: args_list_catalog_dir_list
473 # fdesc: catalog的dir目录结构列表。
474 args_list_catalog_dir_list ()
476 # 初始化task目录
477 task_paths_init
479 dbgoutd "$FUNCNAME is invoked!\n"
481 # xxx: 目录多行输出时的more程序运行。
482 if [[ $catalog_force == "enable" ]]; then
483 catalog_dir_list_full_content $catalog_path
484 else
485 catalog_dir_list_full_content $catalog_path | more
488 exit
492 # fsyntax: args_save_desc_file <save-file-name>
493 # fdesc: catalog的dir目录结构列表。
494 args_save_desc_file ()
496 dbgoutd "$FUNCNAME is invoked!\n"
498 [[ -z $1 ]] && return
500 args_list_catalog_dir_list > $1
502 exit
507 # fsyntax: args_save_desc_file <save-file-name>
508 # fdesc: 将catalog文件的内容同步到对应的目录结构中。catalog描述文件
509 # 中第一个有效行的空格数或tab数为缩进字符串的单位,用于计算目录层数。
510 # tabn空格不能混用。
511 args_sync_catalog_to_dir_framework ()
513 local tmp=$1
514 local path
516 dbgoutd "$FUNCNAME is invoked!\n"
518 dbgoutd "param=$@\n"
520 [[ -z $tmp || ! -f $tmp ]] && tmp=$3
522 # 初始化task目录
523 task_paths_init
525 dbgoutd "tmp=$tmp\n"
527 [[ ! -f $tmp ]] && tmp="$catalog_path/funclist.txt"
528 [[ ! -f $tmp ]] && err "err: file ($tmp) does not exist.\n" && exit
530 path=$(basename $tmp)
531 tmp=$(dirname $tmp)
532 cd $tmp
533 path=$(pwd)/$path
534 cd - 2>/dev/null
537 # todo:
538 # 比较已有的testcase目录与func_list,对差异部分进行更新。
540 testcase_framework_gen $path
542 exit
546 # fsyntax: args_exec_single_task_by_catalog_id <catalog-id> ["continue"]
547 # fdesc: 单项catalog-id的task运行。参数2为字符串continue时,以函数返回。
548 # 为空时,调用exit结束程序运行。
549 # 函数用于args的参数响应函数,只运行单个catalog项的task,运行后exit。
550 # 函数还可用于多个catalog-id的task的运行,运行一个catalog-id的task
551 # 后,return函数,进行另外的catalog-id的task的运行。
552 args_exec_single_task_by_catalog_id ()
554 local catalog_id
555 local id
556 local i
557 local cnt
558 local tmp
559 local curr_path=$PWD
560 local ret
562 catalog_set_begin_id ""
563 catalog_set_end_id ""
564 # begin_catalog_id=""
565 # end_catalog_id=""
567 # 初始化task目录
568 task_paths_init
569 catalog_id_init
571 [[ ! ( -n $2 && "$2" == "continue" ) ]] && dbgoutd "$FUNCNAME is invoked!\n"
573 catalog_id=$1
574 [[ "$1" =~ [^0-9.] ]] && catalog_id=$3
575 [[ "$catalog_id" =~ [^0-9.] ]] && echo xxx && exit
577 OLD_IFS=$IFS
578 IFS="."
579 catalog_id=( $catalog_id )
580 cnt=${#catalog_id[@]}
581 IFS=$OLD_IFS
583 # set -x
584 cd $catalog_path
585 IFS=$'\n'
586 for (( i=0; i<cnt; i++ )); do
587 [[ -z ${catalog_id[$i]} ]] && err "err: catalog_id[$i] does not invalid.\n" && exit
588 id=${catalog_id[$i]}
589 tmp="`find $id.* -maxdepth 1 -type d 2>/dev/null`"
590 tmp=( $tmp )
591 # dbgoutd "id=$id\n"
592 # dbgoutd "tmp=$tmp\n"
594 # dbgcmd ls -d $i.*
595 # dbgoutd "tmp=$tmp\n"
596 if [[ -d $tmp ]]; then
597 cd $tmp
598 tmp=""
599 catalog_step_into "$id"
600 continue
602 tmp=( `ls -1 $id.*.sh 2>/dev/null` )
603 # dbgoutd "tmp=$tmp\n"
604 [[ -e ${tmp[0]} ]] && break
605 dbgoutd "catalog id '$1' is not a valid id.\n"
606 exit
607 done
608 IFS=$OLD_IFS
610 [[ ! ( -n $2 && "$2" == "continue" ) ]] && dbgoutd "catalog path is $(pwd)/$tmp\n"
612 # set+x
614 # dbgoutd "catalog_id=${catalog_id[@]}\n"
615 # dbgoutd "i=$i\n"
616 # dbgoutd "cnt=$cnt\n"
617 # dbgoutd "tmp=$tmp\n"
618 if [[ $i == $cnt ]]; then
619 # xxx:
620 catalog_unit .
621 ret=$?
622 catalog_result_info
624 [[ -z $2 || "$2" == "continue" ]] && exit
626 return $ret
629 # todo:这里可以改为运行一个task-unit
630 [[ -z $tmp ]] && err "err: catalog id ($1) does not specify a valide catalog item file.\n" && exit
632 tmp=`ls -d $id.*.txt`
633 [[ -z $tmp ]] && err "err: catalog id ($i) does not contain a corresponding txt description file.\n" && exit
635 OLD_IFS=$IFS
636 IFS="."
637 tmp=( $tmp )
638 IFS=$OLD_IFS
640 catalog_step "${tmp[0]}"
642 # xxx:
643 catalog_item ${tmp[0]} ${tmp[1]} ${tmp[3]}
644 ret=$?
646 [[ ! ( -n $2 && "$2" == "continue" ) ]] && exit
648 return $ret
653 args_exclude ()
655 dbgoutd "$FUNCNAME is invoked!\n"
657 exclude_id+=" $1"
659 dbgoutd "x exclude_id=${exclude_id}\n"
671 # task脚本输出信息的显示。
672 args_verbose ()
674 dbgoutd "$FUNCNAME is invoked!\n"
676 IFCCOLOR="$FCBLUE"
679 main ()
682 # 参数解析
684 while getopts lS:yn:t:b:e:x:RBd:C:scmVh opt; do
685 case "$opt" in
687 args_list_catalog_dir_list
690 args_save_desc_file "$OPTARG"
693 args_sync_catalog_to_dir_framework
696 task_exec_cnt="$OPTARG"
699 args_exec_single_task_by_catalog_id
702 begin_catalog_id="$OPTARG"
705 end_catalog_id="$OPTARG"
708 exclude_id="$OPTARG"
711 catalog_id_rollup="enable"
714 catalog_id_rollback="enable"
717 task_dir="$OPTARG"
720 echo -ne "param -C and its opt $OPTARG\n"
723 set_catalog_info="enable"
726 clean="enable"
729 FCCOLOR=""
730 IFCCOLOR=""
731 EFCCOLOR=""
734 echo "$PROG_VERSION"
735 exit
738 echo "$usage"
739 exit
742 echo -ne "does not use '$@' opt.\n"
744 esac
745 done
747 # shift to rest paramters
748 shift $(( $OPTIND - 1 ))
750 # init_dbglogout 2 task 20000
752 # todo:
753 # item-task-running
757 #echo xxxxxxxxxx
758 #exit
760 main "$@"
764 ##############################
765 # section: file tail
766 ##############################
779 task_catalog_id_init ()
781 local tmp
783 # load保存的id参数
784 tmp_exclude_id="$exclude_id"
785 tmp_begin_catalog_id="$begin_catalog_id"
786 tmp_end_catalog_id="$end_catalog_id"
787 dbgoutd "tmp_exclude_id=${tmp_exclude_id}\n"
788 [[ -e $TESTING_TMP_DIR/catalog_id.txt ]] && source $TESTING_TMP_DIR/catalog_id.txt
789 [[ -n $tmp_exclude_id && $tmp_exclude_id =~ [^\ ] ]] && exclude_id="$tmp_exclude_id"
790 [[ -n $tmp_begin_catalog_id ]] && begin_catalog_id="$tmp_begin_catalog_id"
791 [[ -n $tmp_end_catalog_id ]] && end_catalog_id="$tmp_end_catalog_id"
792 unset tmp_exclude_id
793 unset tmp_begin_catalog_id
794 unset tmp_end_catalog_id
796 dbgoutd "begin_catalog_id=${begin_catalog_id[@]}\n"
797 dbgoutd "end_catalog_id=${end_catalog_id[@]}\n"
798 dbgoutd "tmp_exclude_id=${tmp_exclude_id}\n"
799 dbgoutd "exclude_id=${exclude_id}\n"
801 # exclude_id=( $exclude_id )
804 # task的id起止范围和状态的初始化
805 # 以task目录中保存的起止id、参数设置、failed的task项的
806 # 顺序设置id值。
808 if [[ $failed_begin == "enable" && -f $TESTING_TMP_DIR/task_failed_list.txt ]]; then
809 # cat $TESTING_TMP_DIR/task_failed_list.txt
810 tmp=$(head -n 1 $TESTING_TMP_DIR/task_failed_list.txt)
811 [[ -n $tmp ]] && begin_catalog_id=$tmp #&& dbgoutd xxxxx
812 # echo xxx begin_catalog_id=$begin_catalog_id
815 if [[ $task_exec_all == "enable" ]]; then
816 exclude_id=""
817 task_exec_cnt=
818 task_ignor_err="enable"
819 else
820 exclude_id=$(echo "${exclude_id}" | tr ' ' '\n' | sort - | uniq)
821 exclude_id=" $(echo "${exclude_id}" | tr "$'\n'" ' ') "
824 # inner
825 catalog_set_init_state "inner"
826 if [[ -n $end_catalog_id ]]; then
827 catalog_set_end_id end_catalog_id
830 if [[ -n $begin_catalog_id ]]; then
831 catalog_set_begin_id begin_catalog_id
833 # 如果有begin-id,默认起始状态为 lower
834 catalog_set_init_state "lower"
837 # dbgoutd "CATA_ID_STATE=${CATA_ID_STATE[@]}\n"
838 # dbgoutd "CATA_ID_BEGIN=${CATA_ID_BEGIN[@]}\n"
839 # dbgoutd "CATA_ID_END=${CATA_ID_END[@]}\n"
841 if [[ $task_exec_all == "enable" ]]; then
842 begin_catalog_id=""
843 end_catalog_id=""
845 catalog_set_begin_id begin_catalog_id
846 catalog_set_end_id end_catalog_id
848 # 如果有begin-id,默认起始状态为 lower
849 catalog_set_init_state "inner"
852 # id起止范围有效性判断
853 catalog_begin_end_chk
855 # task起始范围递增1
856 if [[ $catalog_id_rollup == "enable" ]]; then
857 [[ -z $begin_catalog_id ]] && echo "请使用-b参数指定起始task编号" && exit
859 catalog_begin_id_rollup begin_catalog_id $task_path
860 ret=$?
861 [[ $ret != 0 ]] && exit
863 begin_catalog_id=${CATA_ID_BEGIN[@]}
864 begin_catalog_id=${begin_catalog_id// /.}
865 set_catalog_info="enable"
868 # task起始范围回退1
869 if [[ $catalog_id_rollback == "enable" ]]; then
870 [[ -z $begin_catalog_id ]] && echo "请使用-b参数指定起始task编号" && exit
872 catalog_begin_id_rollback begin_catalog_id $task_path
873 [[ $? != 0 ]] && exit
875 begin_catalog_id=${CATA_ID_BEGIN[@]}
876 begin_catalog_id=${begin_catalog_id// /.}
877 set_catalog_info="enable"
880 # 保存-b -e参数指定的id
881 if [[ $set_catalog_info == "enable" ]]; then
882 [[ -z $begin_catalog_id && -z $end_catalog_id && -z $exclude_id && ! $exclude_id =~ [^\ ] ]] && echo "请使用-x-b-e参数指定起止task编号和exclude-id" && exit
884 dbgoutd "begin_catalog_id=${begin_catalog_id[@]}\n"
885 dbgoutd "end_catalog_id=${end_catalog_id[@]}\n"
886 dbgoutd "exclude_id='$exclude_id'\n"
888 # 保存参数
889 mkdir -p $TESTING_TMP_DIR
890 echo "# [paramters]" > $TESTING_TMP_DIR/task_id.txt
891 [[ -n $begin_catalog_id ]] && echo "begin_catalog_id=${begin_catalog_id}" >> $TESTING_TMP_DIR/task_id.txt
892 [[ -n $end_catalog_id ]] && echo "end_catalog_id=${end_catalog_id}" >> $TESTING_TMP_DIR/task_id.txt
893 [[ -n $exclude_id && $exclude_id =~ [^\ ] ]] && echo "exclude_id='`echo ${exclude_id}`'" >> $TESTING_TMP_DIR/task_id.txt
895 dbgoutd "task catalog id saved!\n"
897 # task-id保存时,不进行task运行,便于testcase中task起止id编号
898 exit
901 # dbgoutd "begin_catalog_id=${begin_catalog_id[@]}\n"
902 # dbgoutd "end_catalog_id=${end_catalog_id[@]}\n"
903 # dbgoutd "exclude_id=${exclude_id}\n"
907 # task运行函数
910 testing ()
913 # 参数解析
914 # task起止范围id的初始化
915 # 初始化task的tmp目录路径,设置testcase的目录
917 ProgOptDispatch "$@"
919 # todo:
920 # ini文件加载环境变量
922 init_dbglogout 2 testing 20000
924 testing_paths_init $output_dir
925 if [[ $clean == "enable" ]]; then
926 dbgoutd "reinit tmp dir.\n"
927 rm $TESTING_TMP_DIR -rf
928 exit
931 # 使用task目录中的begin-id和end-id
932 catalog_id_init
933 testing_catalog_id_init
936 # 指定task信息目录的task循环运行
938 dbgoutd "begin testing ... \n"
939 dbgoutd "testcase dir is \"$task_path\"\n"
940 task_unit $task_path
941 if [[ -e $TESTING_TMP_DIR/testing_failed_list.txt ]]; then
942 cat $TESTING_TMP_DIR/testing_failed_list.txt | sort -n | uniq > ~/testing_failed_list.txt
943 mv ~/testing_failed_list.txt $TESTING_TMP_DIR/testing_failed_list.txt
945 dbgoutd "end testing ...\n"
948 # testing info
950 task_result_info
956 # testcase目录下task程序的调用,及输出比较。
960 # task_item <id> <script_name> <desc_str>
961 task_item ()
963 local ret=
964 local tmp=
965 local script_name=
966 local task_desc=
967 local exetime=
969 script_name="$1.$2.sh"
970 task_desc=$3
971 # dbgoutd "script_name = $script_name\n"
973 # 参数有效性判断
974 if [[ ! -f $script_name ]]; then
975 err "err: file $script_name is not exist.\n"
976 return 1
979 if [[ -z $task_desc ]]; then
980 err "err: descript string is missing.\n"
981 return 1
984 if [[ ! -f $script_name.$task_desc.txt ]]; then
985 err "err: file $script_name.$task_desc.txt is not exist.\n"
986 return 1
989 # task-item字符串信息输出
990 dbgoutd "$CHIGHL$IFCCOLOR$TPREFIX[item] $1 $2 $3 ... "
992 # 删除原有目录,重新创建,并复制task文件
993 rm $TESTING_TMP_DIR/$1.$2/ -rf
994 mkdir -p $TESTING_TMP_DIR/$1.$2/{,scripts}
995 cp $1.* $TESTING_TMP_DIR/$1.$2/ -rf
996 cp -rf scripts/$1.* $TESTING_TMP_DIR/$1.$2/scripts/ 2> /dev/null
997 cp -rf scripts/testing/ $TESTING_TMP_DIR/$1.$2/scripts/ 2> /dev/null
998 cd $TESTING_TMP_DIR/$1.$2
999 # dbgcmd ls -l
1000 chmod +x *.sh scripts/* 2> /dev/null
1002 # 如有task运行时间信息,显示该项task所需时间
1003 if [[ -f $1.$2.time.txt ]]; then
1004 exetime=`head -n 2 $1.$2.time.txt`
1005 tmp=${exetime##$'\nreal '}
1006 tmp=${tmp%%m*}
1007 [[ -z $tmp ]] && err "err: the syntax of task running time info is not correct.\n"
1008 exetime=${exetime##*m}
1009 exetime=${exetime%.*}
1010 exetime=$(( tmp * 60 + exetime ))
1011 # 多于5秒的task项显示运行时间
1012 [[ -n $exetime && $exetime -gt 5 ]] && dbgoutd "(time:${exetime}s) "
1016 # 在这里重定向和pipe操作比较复杂时,为了使输出调试信息不被重定向,使用ttyout函数,
1017 # 即便是sub-process的调试信息也可以显示在终端,而不会对程序中的重定向操作产生影响。
1019 # ttyout dbgout_ttydev=$dbgout_ttydev
1021 dbgoutd "$CNORMAL"
1022 # 带运行时间信息输出的task项运行
1023 if [[ $verbose == "enable" ]]; then
1025 # time语句的code-block,stdout调试信息输出使用stderr,time语句输出到stderr,设置stderr输出为time.txt
1026 # time语句内的code-block,stderr输出到stdout
1027 # 这样,time的stderr输出到time.txt文件,time之内的code-block输出到vch_dbgout(stderr)
1030 time ( {
1031 dbgoutd "\n${INFOCOLOR} + ###############################################${CNORMAL}\n" ;
1032 { ./$script_name 2>&1 | tee log.txt; } | { IFS=$'\n'; while read -r line; do echo -ne "$verbos_pfx$line\n"; done } ;
1033 dbgoutd "${INFOCOLOR} + ###############################################${CNORMAL}\n" ;
1034 } 2>&1 )
1035 } >&$vch_dbgout 2>time.txt
1037 # ( time (
1038 # dbgoutd "abc\n";
1039 # ttyout "testing\n";
1040 # dbgoutd "\n###############################################\n" ;
1041 # ttyout "testing\n";
1042 # # 输出task脚本的stdout和stderr到管道,管道的调试信息使用tee在控制台stdout输出,并保存到日志文件
1043 # ( ./$script_name 2>&1 ) | tee log.txt;
1044 # dbgoutd "###############################################\n" ;
1045 # ttyout "testing\n";
1046 # ) 2>&1 # | { IFS=$'\n'; while read -r line; do echo "$verbos_pfx$line"; done } >&$vch_dbgout #2> /dev/null
1047 # ) 2> time.txt #2>&1
1048 else
1049 ( time ( ./$script_name > log.txt 2>&1 ) ) 2> time.txt #2>&1
1052 diff log.txt $script_name.$task_desc.txt > diff.txt
1053 if [[ -z "`head -n 5 diff.txt`" ]]; then
1054 dbgoutd "$CHIGHL$IFCCOLOR[ ok ]$CNORMAL\n"
1055 ret=0
1057 # 如果有failed record,进行记录。
1058 sed -i $TESTING_TMP_DIR/testing_failed_list.txt -e "/^$(catalog_get_curr_id)$/d" 2>/dev/null
1059 else
1060 dbgoutd "$CHIGHL$IFCCOLOR[failed]$CNORMAL\n"
1061 if [[ $quiet != "enable" ]]; then
1062 dbgoutd "testing result difference from correct output.\n"
1063 dbgoutd "###############################################\n"
1064 dbgout_cmd cat diff.txt # >&2
1065 # 将task运行failed项的日志保存到log目录,便于运行后的查看。
1066 dbgoutd "###############################################\n"
1068 ret=1
1070 # faled record
1071 sed -i $TESTING_TMP_DIR/testing_failed_list.txt -e "/^$(catalog_get_curr_id)$/d" 2>/dev/null
1072 catalog_get_curr_id >> $TESTING_TMP_DIR/testing_failed_list.txt
1075 cd - > /dev/null
1076 if [[ $update_task_result_file == "enable" ]]; then
1077 cp $TESTING_TMP_DIR/$1.$2/log.txt $script_name.$task_desc.txt
1078 exetime=`head -n 2 $TESTING_TMP_DIR/$1.$2/time.txt`
1079 tmp=${exetime%%m*}
1080 tmp=${tmp##`echo -ne "\nreal "`} # }
1081 exetime=${exetime##*m}
1082 exetime=${exetime%.*}
1083 exetime=$(( tmp * 60 + exetime ))
1084 [[ -n $exetime && $exetime -gt 5 ]] && cp $TESTING_TMP_DIR/$1.$2/time.txt $1.$2.time.txt
1087 # clean testing info
1088 rm $TESTING_TMP_DIR/$1.$2/ -rf
1090 return $ret
1094 # task_unit <task_dir>
1095 task_unit ()
1097 local tmp=
1098 local task_dir=$1
1099 local ret=0
1100 local chkret=0
1101 local saved_catalog_id=
1103 # dbgout_func_stub
1105 cd $1
1106 task_cnt=`task_list_curr_content $task_dirs |
1107 ( while read line; do
1108 tmp=( $line )
1110 catalog_step "${tmp[1]}"
1111 # dbgoutd "\${tmp[1]}=${tmp[1]}\n"
1112 # curr_catalog_id[$(( DIR_DEPTH + 1 ))]="${tmp[1]}"
1114 # id范围判断
1115 catalog_curr_id_compare "${tmp[1]}"
1116 chk_ret=$?
1117 # dbgoutd "chk_ret=$chk_ret\n"
1118 case $chk_ret in
1119 0 | 3 )
1123 continue
1126 break
1128 esac
1130 # dbgoutd "DIR_DEPTH = $DIR_DEPTH\n"
1131 case ${tmp[0]} in
1132 "item" )
1133 # DIR_DEPTH=$(( DIR_DEPTH + 1 ))
1134 ## curr_catalog_id[$saved_catalog_id]="${tmp[1]}"
1136 TPREFIX=$(printf "%*s" $(( $DIR_DEPTH * 4 + 4)) " ")
1138 task_cnt=$(( task_cnt + 1 ))
1140 # dbgoutd "task_cnt = $task_cnt\n"
1141 # dbgoutd "task_cnt_num = $task_cnt_num\n"
1143 #dbgoutd "$CHIGHL$IFCCOLOR$TPREFIX${tmp[1]} ${tmp[3]} ${tmp[2]} ... "
1144 task_item ${tmp[1]} ${tmp[3]} ${tmp[2]}
1145 if [[ $? != 0 ]]; then
1146 err_cnt=$(( err_cnt + 1 ))
1147 err_continue_cnt=$(( err_continue_cnt + 1 ))
1148 if [[ $task_ignor_err != "enable" ]]; then
1149 err "err interrupt ...\n"
1150 ret=1
1151 else
1152 ret=0
1153 [[ $err_continue_cnt -ge 10 ]] && ret=1
1155 else
1156 if [[ $err_continue_cnt != 0 ]]; then
1157 err_continue_cnt=0
1159 ret=0
1161 if [[ -n $task_cnt_num && $task_cnt -ge $task_cnt_num ]]; then
1162 ret=1
1165 # curr_task_id[$saved_catalog_id]="${tmp[1]}"
1166 # DIR_DEPTH=$(( DIR_DEPTH - 1 ))
1167 # TPREFIX=$(printf "%*s" $(( $DIR_DEPTH * 4)) " ")
1169 [[ $ret == 1 ]] && break
1171 "module" | "unit" | "dir" )
1172 if [[ -n $task_cnt_num && $task_cnt -gt $task_cnt_num ]]; then
1173 ret=1
1174 break
1177 catalog_step_into "${tmp[1]}"
1178 # dbgoutd "1 DIR_DEPTH = $DIR_DEPTH\n"
1180 # DIR_DEPTH=$(( DIR_DEPTH + 1 ))
1181 TPREFIX=$(printf "%*s" $(( $DIR_DEPTH * 4)) " ")
1183 dbgoutd "$CHIGHL$FCCOLOR$TPREFIX[${tmp[0]}] ${tmp[1]}.${tmp[2]} begin testing ...$CNORMAL\n"
1185 task_unit "${tmp[1]}.${tmp[3]}.${tmp[2]}.${tmp[0]}"
1186 ret=$?
1188 # dbgoutd "2 DIR_DEPTH = $DIR_DEPTH\n"
1189 catalog_step_out "${tmp[1]}"
1190 # dbgoutd "3 DIR_DEPTH = $DIR_DEPTH\n"
1192 # curr_catalog_id[$DIR_DEPTH]=""
1193 # DIR_DEPTH=$(( DIR_DEPTH - 1 ))
1195 TPREFIX=$(printf "%*s" $(( $DIR_DEPTH * 4)) " ")
1196 [[ $ret != 0 ]] && break
1199 # echo $task_cnt
1200 break
1202 esac
1203 [[ $chk_ret == 3 ]] && break
1204 done; echo $task_cnt $err_cnt $err_continue_cnt $CATA_ID_STATE $DIR_DEPTH ; return $ret ); return $?`
1206 # while语句由于|pipe操作符,以一个sub-process运行,所以使用return和exit都只是从sub-process中退出。
1207 # sub-proc中的环境变量task_cnt在return之前echo,在循环结束时echo,以stdout赋值给外部的task_cnt。
1208 ret=$?
1210 task_cnt=( $task_cnt )
1211 err_cnt=${task_cnt[1]}
1212 err_continue_cnt=${task_cnt[2]}
1213 CATA_ID_STATE=${task_cnt[3]}
1214 DIR_DEPTH=${task_cnt[4]}
1215 # dbgoutd "DIR_DEPTH = $DIR_DEPTH\n"
1216 # dbgoutd "err_continue_cnt = $err_continue_cnt\n"
1217 unset task_cnt[1]
1218 unset task_cnt[2]
1219 # dbgoutd "task_cnt[@]=\"${task_cnt[@]}\"\n"
1221 [[ $err_continue_cnt -ge 10 ]] && dbgoutd "连续10个task项failed,暂停运行。\n" && ret=1
1223 # dbgoutd "task_cnt = $task_cnt\n"
1224 cd ..
1225 return $ret