2 # Common function for test
3 # Expect should be installed for SSH Testing
4 # To execute `runqemu`, NOPASSWD needs to be set in /etc/sudoers for user
5 # For example, for user "builder", /etc/sudoers can be like following:
7 # #Members of the admin group may gain root privileges
8 # %builder ALL=(ALL) NOPASSWD: NOPASSWD: ALL
11 # Author: Jiajun Xu <jiajun.xu@intel.com>
13 # This file is licensed under the GNU General Public License,
19 # The folder to hold all scripts running on targets
20 TOOLS
="$COREBASE/scripts/qemuimage-tests/tools"
22 # The folder to hold all projects for toolchain testing
23 TOOLCHAIN_PROJECTS
="$COREBASE/scripts/qemuimage-tests/toolchain_projects"
25 # Test Directory on target for testing
26 TARGET_TEST_DIR
="/opt/test"
28 # Global variables for process id
32 # Global variable for target ip address
35 # Global variable for test project version during toolchain test
36 # Version of cvs is 1.12.13
37 # Version of iptables is 1.4.11
38 # Version of sudoku-savant is 1.3
41 # Global variable for test project download URL during toolchain test
42 # URL of cvs is http://ftp.gnu.org/non-gnu/cvs/source/feature/1.12.13/cvs-1.12.13.tar.bz2
43 # URL of iptables is http://netfilter.org/projects/iptables/files/iptables-1.4.11.tar.bz2
44 # URL of sudoku-savant is http://downloads.sourceforge.net/project/sudoku-savant/sudoku-savant/sudoku-savant-1.3/sudoku-savant-1.3.tar.bz2
45 PROJECT_DOWNLOAD_URL
=0
47 # SDK folder to hold toolchain tarball
48 TOOLCHAIN_DIR
="${DEPLOY_DIR}/sdk"
50 # Toolchain test folder to hold extracted toolchain tarball
53 # common function for information print
56 echo -e "\tTest_Error: $*"
61 echo -e "\tTest_Info: $*"
64 # function to update target ip address
65 # $1 is the process id of the process, which starts the qemu target
66 # $2 is the ip address of the target
72 if [ "$TEST_SERIALIZE" -eq 1 ]; then
73 echo "Saving $pid $ip_addr to $TARGET_IPSAVE"
74 echo "$pid $ip_addr" > $TARGET_IPSAVE
78 # function to copy files from host into target
79 # $1 is the ip address of target
80 # $2 is the files, which need to be copied into target
81 # $3 is the path on target, where files are copied into
87 local tmpfile
=`mktemp`
91 # We use expect to interactive with target by ssh
92 local exp_cmd
=`cat << EOF
93 eval spawn scp -o UserKnownHostsFile=$tmpfile "$src" root@$ip_addr:"$des"
96 "*assword:" { send "\r"; exp_continue}
97 "*(yes/no)?" { send "yes\r"; exp_continue }
98 eof { exit [ lindex [wait] 3 ] }
102 expect
=`which expect`
103 if [ ! -x "$expect" ]; then
104 Test_Error
"ERROR: Please install expect"
114 # function to run command in $ip_addr via ssh
120 local tmpfile
=`mktemp`
123 local exp_cmd
=`cat << EOF
124 eval spawn ssh -o UserKnownHostsFile=$tmpfile root@$ip_addr "$command"
125 set timeout $time_out
127 "*assword:" { send "\r"; exp_continue}
128 "*(yes/no)?" { send "yes\r"; exp_continue }
129 eof { exit [ lindex [wait] 3 ] }
133 expect
=`which expect`
134 if [ ! -x "$expect" ]; then
135 Test_Error
"ERROR: Please install expect"
145 # function to check if ssh is up in $ip_addr
152 # If TEST_SERIALIZE is set, use existing running qemu for testing
153 if [ ${TEST_SERIALIZE} -eq 1 -a -e ${TARGET_IPSAVE} ]; then
157 while [ ${interval} -lt ${timeout} ]
159 Test_SSH
${ip_addr} "hostname"
160 if [ $?
-ne 0 ]; then
161 interval
=`expr $interval + 10`
164 Test_Info
"We can ssh on ${ip_addr} within ${interval} seconds"
170 Test_Info
"We can not ssh on ${ip_addr} in ${timeout} seconds"
174 # function to prepare target test environment
175 # $1 is the ip address of target system
176 # $2 is the files, which needs to be copied into target
182 # Create a pre-defined folder for test scripts
183 Test_SSH
$ip_addr "mkdir -p $TARGET_TEST_DIR"
184 if [ $?
-eq 0 ]; then
185 # Copy test scripts into target
186 Test_SCP
$ip_addr $testscript $TARGET_TEST_DIR && return 0
188 Test_Error
"Fail to create $TARGET_TEST_DIR on target"
195 # function to record test result in $TEST_RESULT/testresult.log
201 if [ $2 -eq 0 ]; then
203 elif [ $2 -eq 1 ]; then
209 # Format the output of the test result
210 echo -e "$1 $PASS $FAIL $NORESULT" |
awk '{printf("\t"); for(i=1;i<=NF;i++) printf("%-15s",$i); printf("\n");}' >> $TEST_RESULT/testresult.log
213 # Test_Kill_Qemu to kill child pid with parent pid given
214 # $1 is qemu process id, which needs to be killed
221 # When TEST_SERIALIZE is set, qemu process will not be
222 # killed until all the cases are finished
223 if [ ${TEST_SERIALIZE} -eq 1 -a -e ${TEST_STATUS} ]; then
224 index
=`sed -n 2p ${TEST_STATUS} | awk '{print $3}'`
225 total
=`sed -n 2p ${TEST_STATUS} | awk '{print $4}'`
226 if [ ${index} != ${total} ]; then
227 Test_Info
"Do not kill the qemu process and use it for later testing (step $index of $total)"
228 Test_Update_IPSAVE
$XTERMPID $TARGET_IPADDR
236 if [ $k -eq 1 ]; then
237 running
=`ps -wwfp $QEMUPID`
238 if [ $?
-eq 0 ]; then
239 echo "killing $QEMUPID"
242 running
=`ps -wwfp $XTERMPID`
243 if [ $?
-eq 0 ]; then
244 echo "killing $XTERMPID"
252 # function to check if network is up
255 ping -c1 $1 1> /dev
/null
256 if [ $?
-ne 0 ]; then
257 Test_Info
"IP $1 is not up"
260 Test_Info
"IP $1 is up"
265 # function to find kernel/rootfs image
275 while getopts "l:k:a:t:" Option
288 *) echo "invalid option: -$Option" && return 1
293 if [ ! -z $kernel ]; then
294 if [ -L ${where}/${kernel}-${arch}.${extension} ]; then
295 echo ${where}/${kernel}-${arch}.${extension}
298 for i
in `dir ${where}`
300 # Exclude qemux86-64 when target is qemux86
301 echo $i |
grep "${kernel}.*${arch}.*\.${extension}" | grep -qv "${kernel}.*${arch}-64.*\.${extension}"
302 if [ $?
-eq 0 ]; then
311 if [ ! -z $target ]; then
312 if [ -L ${where}/${target}-${arch}.${extension} ]; then
313 rootfs
=`readlink -f ${where}/${target}-${arch}.${extension}`
317 for i
in `dir ${where}`
319 # Exclude qemux86-64 when target is qemux86
320 echo $i |
grep "${target}-${arch}.*\.${extension}" | grep -qv "${target}-${arch}-64.*\.${extension}"
321 if [ $?
-eq 0 ]; then
332 # function to parse IP address of target
333 # $1 is the pid of qemu startup process
334 Test_Fetch_Target_IP
()
339 # Check if $1 pid exists and contains ipaddr of target
340 ip_addr
=`ps -wwfp $opid | grep -o "192\.168\.7\.[0-9]*::" | awk -F":" '{print $1}'`
347 # function to check if qemu and its network
353 RUNQEMU
=`which runqemu`
354 if [ $?
-ne 0 ]; then
355 Test_Error
"Can not find runqemu in \$PATH, return fail"
359 if [ "$QEMUARCH" = "qemux86" -o "$QEMUARCH" = "qemux86-64" ]; then
360 KERNEL
=$
(Test_Find_Image
-l ${DEPLOY_DIR}/images
-k bzImage
-a ${QEMUARCH})
361 elif [ "$QEMUARCH" = "qemuarm" -o "$QEMUARCH" = "spitz" -o "$QEMUARCH" = "borzoi" -o "$QEMUARCH" = "akita" -o "$QEMUARCH" = "nokia800" ]; then
362 KERNEL
=$
(Test_Find_Image
-l ${DEPLOY_DIR}/images
-k zImage
-a ${QEMUARCH})
363 elif [ "$QEMUARCH" = "qemumips" -o "$QEMUARCH" = "qemuppc" ]; then
364 KERNEL
=$
(Test_Find_Image
-l ${DEPLOY_DIR}/images
-k vmlinux
-a ${QEMUARCH})
367 # If there is no kernel image found, return failed directly
368 if [ $?
-eq 1 ]; then
369 Test_Info
"No kernel image file found under ${DEPLOY_DIR}/images for ${QEMUARCH}, pls. have a check"
373 ROOTFS_IMAGE
=$
(Test_Find_Image
-l ${DEPLOY_DIR}/images -t ${QEMUTARGET} -a ${QEMUARCH})
375 # If there is no rootfs image found, return failed directly
376 if [ $?
-eq 1 ]; then
377 Test_Info
"No ${QEMUTARGET} rootfs image file found under ${DEPLOY_DIR}/images for ${QEMUARCH}, pls. have a check"
381 TEST_ROOTFS_IMAGE
="${TEST_TMP}/${QEMUTARGET}-${QEMUARCH}-test.ext3"
385 # When TEST_SERIALIZE is set, we use the existing image under tmp folder
386 if [ ${TEST_SERIALIZE} -eq 1 -a -e "$TARGET_IPSAVE" ]; then
387 # If TARGET_IPSAVE exists, check PID of the qemu process from it
388 XTERMPID
=`awk '{print $1}' $TARGET_IPSAVE`
391 rm -rf $TEST_ROOTFS_IMAGE
392 echo "Copying rootfs $ROOTFS_IMAGE to $TEST_ROOTFS_IMAGE"
393 $CP $ROOTFS_IMAGE $TEST_ROOTFS_IMAGE
394 if [ $?
-ne 0 ]; then
395 Test_Info
"Image ${ROOTFS_IMAGE} copy to ${TEST_ROOTFS_IMAGE} failed, return fail"
399 export MACHINE
=$QEMUARCH
401 # Create Qemu in localhost VNC Port 1
402 echo "Running xterm -display ${DISPLAY} -e 'OE_TMPDIR=${OE_TMPDIR} ${RUNQEMU} ${KERNEL} ${TEST_ROOTFS_IMAGE} || /bin/sleep 60' &"
403 xterm
-display ${DISPLAY} -e "OE_TMPDIR=${OE_TMPDIR} ${RUNQEMU} ${KERNEL} ${TEST_ROOTFS_IMAGE} ||
/bin
/sleep 60" &
405 # Get the pid of the xterm processor, which will be used in Test_Kill_Qemu
407 echo "XTERMPID is
$XTERMPID"
408 # When starting, qemu can reexecute itself and change PID so wait a short while for things to settle
412 while [ ${up_time} -lt 10 ]
414 QEMUPID=`qemuimage-testlib-pythonhelper --findqemu $XTERMPID`
415 if [ $? -ne 0 ]; then
416 Test_Info "Wait
for qemu up...
"
417 up_time=`expr $up_time + 5`
420 Test_Info "Begin to check
if qemu network is up
"
421 echo "QEMUPID is
$QEMUPID"
426 if [ ${up_time} == 10 ]; then
427 Test_Info "No qemu process appeared to start
, exiting
"
431 # Parse IP address of target from the qemu command line
432 TARGET_IPADDR=`Test_Fetch_Target_IP $QEMUPID`
433 echo "Target IP is
${TARGET_IPADDR}"
434 if [ -z ${TARGET_IPADDR} ]; then
435 Test_Info "There is no qemu process or qemu ip address found
, return failed
"
439 while [ ${up_time} -lt ${timeout} ]
441 Test_Check_IP_UP ${TARGET_IPADDR}
442 if [ $? -eq 0 ]; then
443 Test_Info "Qemu Network is up
, ping with
${TARGET_IPADDR} is OK within
${up_time} seconds
"
446 Test_Info "Wait
for Qemu Network up
"
447 up_time=`expr $up_time + 5`
452 Test_Info "Qemu or its network is not up
in ${timeout} seconds
"
453 Test_Update_IPSAVE $XTERMPID $TARGET_IPADDR
457 # Function to prepare test project for toolchain test
458 # $1 is the folder holding test project file
459 # $2 is the test project name
460 Test_Project_Prepare()
462 local toolchain_dir=$1
464 if [ ! -d ${toolchain_dir} ]; then
465 mkdir -p ${toolchain_dir}
466 if [ $? -ne 0 ]; then
468 Test_Info "Create
${toolchain_dir} fail
, return"
473 # Download test project tarball if it does not exist
474 if [ ! -f ${toolchain_dir}/${2}-${PROJECT_PV}.${suffix} ]; then
475 wget -c -t 5 $PROJECT_DOWNLOAD_URL -O ${toolchain_dir}/${2}-${PROJECT_PV}.${suffix}
476 if [ $? -ne 0 ]; then
478 Test_Info "Fail to download
${2}-${PROJECT_PV}.${suffix} from
$PROJECT_DOWNLOAD_URL"
479 rm -rf ${toolchain_dir}/${2}-${PROJECT_PV}.${suffix}
484 # Extract the test project into ${TEST_TMP}
485 tar jxf ${toolchain_dir}/${2}-${PROJECT_PV}.${suffix} -C ${TEST_TMP}
486 if [ $? -ne 0 ]; then
488 Test_Info "Fail to extract
${2}-${PROJECT_PV}.${suffix} into ${TEST_TMP}"
491 Test_Info "Extract
${2}-${PROJECT_PV}.${suffix} into ${TEST_TMP} successfully
"
495 # Function to prepare toolchain environment
496 # $1 is toolchain directory to hold toolchain tarball
497 # $2 is prefix name for toolchain tarball
498 Test_Toolchain_Prepare()
500 local toolchain_dir=$1
504 if [ ! -d ${toolchain_dir} ]; then
505 Test_Info "No directory
${toolchain_dir}, which holds toolchain tarballs
"
509 # Check if there is any toolchain tarball under $toolchain_dir with prefix $sdk_name
510 for i in `dir ${toolchain_dir}`
512 echo $i | grep "${sdk_name}-toolchain-gmae"
513 if [ $? -eq 0 ]; then
514 rm -rf ${TEST_TMP}/opt
515 tar jxf ${toolchain_dir}/${i} -C ${TEST_TMP}
521 if [ $ret -eq 0 ]; then
522 Test_Info "Check
if /opt is accessible
for non-root user
"
524 # Check if the non-root test user has write access of $TOOLCHAIN_TEST
525 if [ -d ${TOOLCHAIN_TEST} ]; then
526 touch ${TOOLCHAIN_TEST}
527 if [ $? -ne 0 ]; then
528 Test_Info "Has no right to modify folder
$TOOLCHAIN_TEST, pls. chown it to
test user
"
532 mkdir -p ${TOOLCHAIN_TEST}
533 if [ $? -ne 0 ]; then
534 Test_Info "Has no right to create folder
$TOOLCHAIN_TEST, pls. create it and chown it to
test user
"
539 # If there is a toolchain folder under $TOOLCHAIN_TEST, let's remove it
540 if [ -d ${TOOLCHAIN_TEST}/poky ]; then
541 rm -rf ${TOOLCHAIN_TEST}/poky
544 # Copy toolchain into $TOOLCHAIN_TEST
545 cp -r ${TEST_TMP}/opt/poky ${TOOLCHAIN_TEST}
548 if [ $ret -eq 0 ]; then
549 Test_Info "Successfully copy toolchain into
$TOOLCHAIN_TEST"
552 Test_Info "Meet error when copy toolchain into
$TOOLCHAIN_TEST"
556 Test_Info "No tarball named
${sdk_name}-toolchain-gmae under
${toolchain_dir}"
561 # Function to execute command and exit if run out of time
562 # $1 is timeout value
563 # $2 is the command to be executed
577 # Run command in background
578 ($command; echo $? > $tmp) &
580 while ps -e -o pid | grep -qw $pid; do
581 if [ $date -ge $timeout ]; then
582 Test_Info "$timeout Timeout when running
command $command"
585 # Find all child processes of pid and kill them
592 # If yes, get the child pid and check if the child pid has other child pid
593 # Continue the while loop until there is no child pid found
594 pid_l[$i]=`ps -f --ppid $ppid | awk '{if ($2 != "PID
") print $2}'`
601 # Kill these children pids from the last one
614 date=`expr $date + 5`
621 # Function to test toolchain
622 # $1 is test project name
623 # $2 is the timeout value
626 local test_project=$1
629 local suffix="tar.bz2
"
631 local pro_install="${TEST_TMP}/pro_install
"
633 # Set value for PROJECT_PV and PROJECT_DOWNLOAD_URL accordingly
634 if [ $test_project == "cvs
" ]; then
636 PROJECT_DOWNLOAD_URL="http
://ftp.gnu.org
/non-gnu
/cvs
/source
/feature
/1.12.13/cvs-1.12
.13.
tar.bz2
"
637 elif [ $test_project == "iptables
" ]; then
639 PROJECT_DOWNLOAD_URL="http
://netfilter.org
/projects
/iptables
/files
/iptables-1.4
.11.
tar.bz2
"
640 elif [ $test_project == "sudoku-savant
" ]; then
642 PROJECT_DOWNLOAD_URL="http
://downloads.sourceforge.net
/project
/sudoku-savant
/sudoku-savant
/sudoku-savant-1.3
/sudoku-savant-1.3.
tar.bz2
"
644 Test_Info "Unknown
test project name
$test_project"
648 # Download test project and extract it
649 Test_Project_Prepare $TOOLCHAIN_PROJECTS $test_project
650 if [ $? -ne 0 ]; then
651 Test_Info "Prepare
test project
file failed
"
655 # Extract toolchain tarball into ${TEST_TMP}
656 Test_Toolchain_Prepare $TOOLCHAIN_DIR $SDK_NAME
658 if [ $ret -ne 0 ]; then
659 Test_Info "Prepare toolchain
test environment failed
"
663 if [ ! -d ${pro_install} ]; then
664 mkdir -p ${pro_install}
667 # Begin to build test project in toolchain environment
668 env_setup=`find ${TOOLCHAIN_TEST}/poky -name "environment-setup
*"`
672 if [ $test_project == "cvs
" -o $test_project == "iptables
" ]; then
673 cd ${TEST_TMP}/${test_project}-${PROJECT_PV}
674 Test_Time_Out $timeout ./configure ${CONFIGURE_FLAGS} || { Test_Info "configure failed with
$test_project"; return 1; }
675 Test_Time_Out $timeout make -j4 || { Test_Info "make failed with
$test_project"; return 1; }
676 Test_Time_Out $timeout make install DESTDIR=${pro_install} || { Test_Info "make failed with
$test_project"; return 1; }
679 elif [ $test_project == "sudoku-savant
" ]; then
680 cd ${TEST_TMP}/${test_project}-${PROJECT_PV}
681 Test_Time_Out $timeout ./configure ${CONFIGURE_FLAGS} || { Test_Info "configure failed with
$test_project"; return 1; }
682 Test_Time_Out $timeout make -j4 || { Test_Info "make failed with
$test_project"; return 1; }
686 Test_Info "Unknown
test project
$test_project"