poky/scripts/qemuimage-testlib
Jiajun Xu 3e052919c9 qemuimagetest: Use same image during sanity testing instead of copying a new image for each case
To reduce the time on sanity testing, we remove variable SHARE_IMAGE and use
a new variable TEST_SERIALIZE in local.conf. It is by default set to 1. Poky
will copy and boot the to-be tested image for only once. It will not remove
or kill the image and test cases will be serialized executed against the same
image. If it is set to 0, image is always be copied for each cases, which takes
much time. I had a experiment that latest qemuppc sato only takes 7 minutes to
finish 9 sanity test cases, which takes more than 20 minutes before.

I also removed sanity case "boot" from sato/sdk/lsb because the other cases for
these targets already cover the check point of "boot".

Signed-off-by Jiajun Xu <jiajun.xu@intel.com>
2011-01-20 21:36:57 +00:00

11 KiB

#!/bin/bash

Common function for test

Expect should be installed for SSH Testing

To execute runqemu, NOPASSWD needs to be set in /etc/sudoers for user

For example, for user "builder", /etc/sudoers can be like following:

#Members of the admin group may gain root privileges

%builder ALL=(ALL) NOPASSWD: NOPASSWD: ALL

Author: Jiajun Xu jiajun.xu@intel.com

This file is licensed under the GNU General Public License,

Version 2.

TYPE="ext3"

The folder to hold all scripts running on targets

TOOLS="$POKYBASE/scripts/qemuimage-tests/tools"

Test Directory on target for testing

TARGET_TEST_DIR="/opt/test"

Global variable for process id

PID=0

Global variable for target ip address

TARGET_IPADDR=0

common function for information print

Test_Error() { echo -e "\tTest_Error: $*" }

Test_Info() { echo -e "\tTest_Info: $*" }

function to update target ip address

$1 is the process id of the process, which starts the qemu target

$2 is the ip address of the target

Test_Update_IPSAVE() { local pid=$1 local ip_addr=$2

if [ "$TEST_SERIALIZE" -eq 1 ]; then
	echo "$pid $ip_addr" > $TARGET_IPSAVE
fi

}

function to copy files from host into target

$1 is the ip address of target

$2 is the files, which need to be copied into target

$3 is the path on target, where files are copied into

Test_SCP() { local ip_addr=$1 local src=$2 local des=$3 local tmpfile=mktemp local timeout=60 local ret=0

# We use expect to interactive with target by ssh
local exp_cmd=`cat << EOF

eval spawn scp -o UserKnownHostsFile=$tmpfile "$src" root@$ip_addr:"$des" set timeout $time_out expect { "assword:" { send "\r"; exp_continue} "(yes/no)?" { send "yes\r"; exp_continue } eof { exit [ lindex [wait] 3 ] } } EOF` expect -c "$exp_cmd" ret=$? rm -rf $tmpfile return $ret }

function to run command in $ip_addr via ssh

Test_SSH() { local ip_addr=$1 shift local command=$@ local tmpfile=mktemp local timeout=60 local ret=0 local exp_cmd=cat << EOF eval spawn ssh -o UserKnownHostsFile=$tmpfile root@$ip_addr "$command" set timeout $time_out expect { "*assword:" { send "\r"; exp_continue} "*(yes/no)?" { send "yes\r"; exp_continue } eof { exit [ lindex [wait] 3 ] } } EOF expect -c "$exp_cmd" ret=$? rm -rf $tmpfile return $ret }

function to check if ssh is up in $ip_addr

Test_SSH_UP() { local ip_addr=$1 local timeout=$2 local interval=0

# If TEST_SERIALIZE is set, use existing running qemu for testing
if [ ${TEST_SERIALIZE} -eq 1 -a -e ${TARGET_IPSAVE} ]; then
	timeout=50
fi

while [ ${interval} -lt ${timeout} ]
do
	Test_SSH ${ip_addr} "hostname"
	if [ $? -ne 0 ]; then
		interval=`expr $interval + 10`
		sleep 10
	else
		Test_Info "We can ssh on ${ip_addr} within ${interval} seconds"
		return 0
	fi

done

Test_Info "We can not ssh on ${ip_addr} in ${timeout} seconds"
return 1

}

function to prepare target test environment

$1 is the ip address of target system

$2 is the files, which needs to be copied into target

Test_Target_Pre() { local ip_addr=$1 local testscript=$2

# Create a pre-defined folder for test scripts
Test_SSH $ip_addr "mkdir -p $TARGET_TEST_DIR"
if [ $? -eq 0 ]; then
	# Copy test scripts into target
	Test_SCP $ip_addr $testscript $TARGET_TEST_DIR && return 0
else
	Test_Error "Fail to create $TARGET_TEST_DIR on target"
	return 1
fi

return 1

}

function to record test result in $TEST_RESULT/testresult.log

Test_Print_Result() { local PASS=0 local FAIL=0 local NORESULT=0 if [ $2 -eq 0 ]; then PASS=1 elif [ $2 -eq 1 ]; then FAIL=1 else NORESULT=1 fi

# Format the output of the test result
echo -e "$1 $PASS $FAIL $NORESULT" | awk '{printf("\t"); for(i=1;i<=NF;i++) printf("%-15s",$i); printf("\n");}' >> $TEST_RESULT/testresult.log

}

Test_Kill_Qemu to kill child pid with parent pid given

$1 is qemu process id, which needs to be killed

Test_Kill_Qemu() { local ret=0 local ppid=0 local i=0 local index=0 local total=0 declare local pid

# Check if $1 pid exists and is a qemu process
ps -fp $PID | grep -iq "qemu"

# Find all children pid of the pid $1
if [ $? -eq 0 ]; then

	# Check if there is any child pid of the pid $PID
	ppid=$PID
	ps -f --ppid $ppid
	ret=$?

	while [ $ret -eq 0 ]
	do
		# If yes, get the child pid and check if the child pid has other child pid
		# Continue the while loop until there is no child pid found
		pid[$i]=`ps -f --ppid $ppid | awk '{if ($2 != "PID") print $2}'`
		ppid=${pid[$i]}
		i=$((i+1))
		ps -f --ppid $ppid
		ret=$?
	done

	# When TEST_SERIALIZE is set, qemu process will not be
	# killed until all the cases are finished
	if [ ${TEST_SERIALIZE} -eq 1 -a -e ${TEST_STATUS} ]; then
		index=`sed -n 2p ${TEST_STATUS} | awk '{print $3}'`
		total=`sed -n 2p ${TEST_STATUS} | awk '{print $4}'`
		if [ ${index} != ${total} ]; then
			Test_Info "Do not kill the qemu process and use it for later testing"
			Test_Update_IPSAVE $PID $TARGET_IPADDR
		else
			# If it is the last case, let's kill it
			while [ $i -ne 0 ]
			do
				i=$((i-1))
				kill ${pid[$i]}
				sleep 2
			done

			# Kill the parent id
			kill $PID
		fi

	else
		# Kill these children pids from the last one
		while [ $i -ne 0 ]
		do
			i=$((i-1))
			kill ${pid[$i]}
			sleep 2
		done

		# Kill the parent id
		kill $PID
	fi
fi

return

}

function to check if there is any qemu process

Test_Check_Qemu_UP() { local count=ps -eo command | cut -d " " -f 1 | grep -c "\(^qemu\|.*/qemu\)" if [ ${count} -lt 1 ]; then Test_Info "There is no Qemu process" return 1 else Test_Info "There is at least one Qemu process running" return 0 fi }

function to check if network is up

Test_Check_IP_UP() { ping -c1 $1 if [ $? -ne 0 ]; then Test_Info "IP $1 is not up" return 1 else Test_Info "IP $1 is up" return 0 fi }

function to find kernel/rootfs image

Test_Find_Image() { where="" kernel="" arch="" target="" extension="" rootfs=""

while getopts "l:k:a:t:" Option
do
	case $Option in
		l) where="$OPTARG"
		   ;;
		k) kernel="$OPTARG"
		   extension="bin"
		   ;;
		a) arch="$OPTARG"
		   ;;
		t) target="$OPTARG"
		   extension="ext3"
		   ;;
		*) echo "invalid option: -$Option" && return 1
		   ;;
	 esac
done

if [ ! -z $kernel ]; then
	if [ -L ${where}/${kernel}-${arch}.${extension} ]; then
		echo ${where}/${kernel}-${arch}.${extension}
		return 0
	else
		for i in `dir ${where}`
		do
			echo $i | grep -q "${kernel}.*${arch}.*\.${extension}"
			if [ $? -eq 0 ]; then
				echo ${where}/${i}
				return 0
			fi
		done
		return 1
	fi
fi

if [ ! -z $target ]; then
	if [ -L ${where}/${target}-${arch}.${extension} ]; then
		rootfs=`readlink -f ${where}/${target}-${arch}.${extension}`
		echo ${rootfs}
		return 0
	else
		for i in `dir ${where}`
		do
			echo $i | grep -q "${target}-${arch}.*\.${extension}"
			if [ $? -eq 0 ]; then
				echo ${where}/${i}
				return 0
			fi
		done
		return 1
	fi
fi
return 1

}

function to parse IP address of target

$1 is the pid of qemu startup process

Test_Fetch_Target_IP() { local opid=$1 local ppid=0 local ip_addr=0 local i=0 declare local pid

# Check if $1 pid exists and contains ipaddr of target
ps -fp $opid | grep -oq "192\.168\.7\.[0-9]*::"

# Find all children pid of the pid $1
# and check if they contain ipaddr of target
if [ $? -ne 0 ]; then
	# Check if there is any child pid of the pid $1
	ppid=$opid
	ps -f --ppid $ppid > /dev/zero
	ret=$?

	while [ $ret -eq 0 ]
	do
		# If yes, get the child pid and check if the child pid has other child pid
		# Continue the while loop until there is no child pid found
		pid[$i]=`ps -f --ppid $ppid | awk '{if ($2 != "PID") print $2}'`
		ppid=${pid[$i]}
		i=$((i+1))
		ps -f --ppid $ppid > /dev/zero
		ret=$?
	done

	# Check these children pids, if they have ipaddr included in command line
	while [ $i -ne 0 ]
	do
		i=$((i-1))
		ps -fp ${pid[$i]} | grep -oq "192\.168\.7\.[0-9]*::"
		if [ $? -eq 0 ]; then
			ip_addr=`ps -fp ${pid[$i]} | grep -o "192\.168\.7\.[0-9]*::" | awk -F":" '{print $1}'`
		fi
		sleep 1
	done
else
	ip_addr=`ps -fp $opid | grep -o "192\.168\.7\.[0-9]*::" | awk -F":" '{print $1}'`
fi

echo $ip_addr

return

}

function to check if qemu and its network

Test_Create_Qemu() { local timeout=$1 local ret=1 local up_time=0

which poky-qemu
if [ $? -eq 0 ]; then
	RUNQEMU=`which poky-qemu`
else
	Test_Error "Can not find poky-qemu in \$PATH, return fail"
	exit 1
fi

if [ "$QEMUARCH" = "qemux86" -o "$QEMUARCH" = "qemux86-64" ]; then
	KERNEL=$(Test_Find_Image -l ${DEPLOY_DIR}/images -k bzImage -a ${QEMUARCH})
elif [ "$QEMUARCH" = "qemuarm" -o "$QEMUARCH" = "spitz" -o "$QEMUARCH" = "borzoi" -o "$QEMUARCH" = "akita" -o "$QEMUARCH" = "nokia800" -o "$QEMUARCH" = "qemuppc" ]; then
	KERNEL=$(Test_Find_Image -l ${DEPLOY_DIR}/images -k zImage -a ${QEMUARCH})
elif [ "$QEMUARCH" = "qemumips" ]; then
	KERNEL=$(Test_Find_Image -l ${DEPLOY_DIR}/images -k vmlinux -a ${QEMUARCH})
fi

# If there is no kernel image found, return failed directly
if [ $? -eq 1 ]; then
	Test_Info "No kernel image file found under ${DEPLOY_DIR}/images for ${QEMUARCH}, pls. have a check"
	return $ret
fi

ROOTFS_IMAGE=$(Test_Find_Image -l ${DEPLOY_DIR}/images -t ${QEMUTARGET} -a ${QEMUARCH})

# If there is no rootfs image found, return failed directly
if [ $? -eq 1 ]; then
	Test_Info "No ${QEMUTARGET} rootfs image file found under ${DEPLOY_DIR}/images for ${QEMUARCH}, pls. have a check"
	return $ret
fi

TEST_ROOTFS_IMAGE="${TEST_TMP}/${QEMUTARGET}-${QEMUARCH}-test.ext3"

CP=`which cp`

# When TEST_SERIALIZE is set, we use the existing image under tmp folder
if [ ${TEST_SERIALIZE} -eq 1 -a -e "$TARGET_IPSAVE" ]; then
	# If TARGET_IPSAVE exists, check PID of the qemu process from it
	PID=`awk '{print $1}' $TARGET_IPSAVE`
	timeout=50
else
	rm -rf $TEST_ROOTFS_IMAGE
	$CP $ROOTFS_IMAGE $TEST_ROOTFS_IMAGE
	if [ $? -ne 0 ]; then
		Test_Info "Image ${ROOTFS_IMAGE} copy to ${TEST_ROOTFS_IMAGE} failed, return fail"
		return $ret
	fi

	export MACHINE=$QEMUARCH

	# Create Qemu in localhost VNC Port 1
	echo "Running xterm -display ${DISPLAY} -e 'BUILDDIR=${TOPDIR} ${RUNQEMU} ${KERNEL} ${TEST_ROOTFS_IMAGE}' &"
    	xterm -display ${DISPLAY} -e "BUILDDIR=${TOPDIR} ${RUNQEMU} ${KERNEL} ${TEST_ROOTFS_IMAGE}" &

	# Get the pid of the xterm processor, which will be used in Test_Kill_Qemu
	PID=$!
fi

while [ ${up_time} -lt 10 ]
do
	Test_Check_Qemu_UP
	if [ $? -ne 0 ]; then
		Test_Info "Wait for qemu up..."
		up_time=`expr $up_time + 5`
		sleep 5
	else
		Test_Info "Begin to check if qemu network is up"
		break
	fi
done

# Parse IP address of target from the qemu command line
if [ ${up_time} -lt ${timeout} ]; then
	sleep 5
	TARGET_IPADDR=`Test_Fetch_Target_IP $PID`
	# If IP address is 0, means there is no qemu process found
	if [ ${TARGET_IPADDR} == "0" ]; then
		Test_Info "There is no qemu process or qemu ip address found, return failed"
		return $ret
	fi
fi

while [ ${up_time} -lt ${timeout} ]
do
	Test_Check_IP_UP ${TARGET_IPADDR}
	if [ $? -eq 0 ]; then
		Test_Info "Qemu Network is up, ping with ${TARGET_IPADDR} is OK within ${up_time} seconds"
		ret=0
		break
	else
		Test_Info "Wait for Qemu Network up"
		up_time=`expr $up_time + 5`
		sleep 5
	fi
done

if [ $ret -eq 0 ]; then
	Test_Info "Qemu and its network is up"
	return $ret
else
	Test_Info "Qemu or its network is not up in ${timeout} seconds"
	Test_Update_IPSAVE $PID $TARGET_IPADDR
	return $ret
fi

}