poky/scripts/qemuimage-testlib
Jiajun Xu d08a341af7 qemuimagetest: update cvs and iptables to newer version for toolchain test
The old versions of cvs and iptables may meet compile error under some architecture
- cvs 1.11.23 fails on x86-64 host and iptables 1.4.9 fails on arm host. Update them
to latest version could solve these build error.
Meanwhile, 240s timeout is set for sudoku becasue 120s is not enough to finish
compile.

Signed-off-by Jiajun Xu <jiajun.xu@intel.com>

Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2011-06-24 11:28:32 +01:00

19 KiB
Executable File

#!/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="$COREBASE/scripts/qemuimage-tests/tools"

The folder to hold all projects for toolchain testing

TOOLCHAIN_PROJECTS="$COREBASE/scripts/qemuimage-tests/toolchain_projects"

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

Global variable for test project version during toolchain test

Version of cvs is 1.12.13

Version of iptables is 1.4.11

Version of sudoku-savant is 1.3

PROJECT_PV=0

Global variable for test project download URL during toolchain test

URL of cvs is http://ftp.gnu.org/non-gnu/cvs/source/feature/1.12.13/cvs-1.12.13.tar.bz2

URL of iptables is http://netfilter.org/projects/iptables/files/iptables-1.4.11.tar.bz2

URL of sudoku-savant is http://downloads.sourceforge.net/project/sudoku-savant/sudoku-savant/sudoku-savant-1.3/sudoku-savant-1.3.tar.bz2

PROJECT_DOWNLOAD_URL=0

SDK folder to hold toolchain tarball

TOOLCHAIN_DIR="${DEPLOY_DIR}/sdk"

Toolchain test folder to hold extracted toolchain tarball

TOOLCHAIN_TEST="/opt"

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
			# Exclude qemux86-64 when target is qemux86
			echo $i | grep "${kernel}.*${arch}.*\.${extension}" | grep -qv "${kernel}.*${arch}-64.*\.${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
			# Exclude qemux86-64 when target is qemux86
			echo $i | grep "${target}-${arch}.*\.${extension}" | grep -qv "${target}-${arch}-64.*\.${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 runqemu
if [ $? -eq 0 ]; then
	RUNQEMU=`which runqemu`
else
	Test_Error "Can not find runqemu in \$PATH, return fail"
	return 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

}

Function to prepare test project for toolchain test

$1 is the folder holding test project file

$2 is the test project name

Test_Project_Prepare() { local toolchain_dir=$1 local ret=1

if [ ! -d ${toolchain_dir} ]; then
	mkdir -p ${toolchain_dir}
	ret=$?

	if [ $ret -ne 0 ]; then
		Test_Info "Create ${toolchain_dir} fail, return"
		return $ret
	fi
fi

ret=0
# Download test project tarball if it does not exist
if [ ! -f ${toolchain_dir}/${2}-${PROJECT_PV}.${suffix} ]; then
	wget -c -t 5 $PROJECT_DOWNLOAD_URL -O ${toolchain_dir}/${2}-${PROJECT_PV}.${suffix}
	ret=$?
fi

# Extract the test project into ${TEST_TMP}
if [ $ret -eq 0 ]; then
	tar jxf ${toolchain_dir}/${2}-${PROJECT_PV}.${suffix} -C ${TEST_TMP}
	ret=$?
	if [ $ret -eq 0 ]; then
		Test_Info "Extract ${2}-${PROJECT_PV}.${suffix} into ${TEST_TMP} successfully"
		return $ret
	else
		Test_Info "Fail to extract ${2}-${PROJECT_PV}.${suffix} into ${TEST_TMP}"
		return $ret
	fi
else
	Test_Info "Fail to download ${2}-${PROJECT_PV}.${suffix} from $PROJECT_DOWNLOAD_URL"
	rm -rf ${toolchain_dir}/${2}-${PROJECT_PV}.${suffix}
	return $ret
fi

}

Function to prepare toolchain environment

$1 is toolchain directory to hold toolchain tarball

$2 is prefix name for toolchain tarball

Test_Toolchain_Prepare() { local toolchain_dir=$1 local sdk_name=$2 local ret=1

if [ ! -d ${toolchain_dir} ]; then
	Test_Info "No directory ${toolchain_dir}, which holds toolchain tarballs"
	return 1
fi

# Check if there is any toolchain tarball under $toolchain_dir with prefix $sdk_name
for i in `dir ${toolchain_dir}`
do
	echo $i | grep "${sdk_name}-toolchain-gmae"
	if [ $? -eq 0 ]; then
		rm -rf ${TEST_TMP}/opt
		tar jxf ${toolchain_dir}/${i} -C ${TEST_TMP}
		ret=$?
		break
	fi
done

if [ $ret -eq 0 ]; then
	Test_Info "Check if /opt is accessible for non-root user"

	# Check if the non-root test user has write access of $TOOLCHAIN_TEST
	if [ -d ${TOOLCHAIN_TEST} ]; then
		touch ${TOOLCHAIN_TEST}
		if [ $? -ne 0 ]; then
			Test_Info "Has no right to modify folder $TOOLCHAIN_TEST, pls. chown it to test user"
			return 2
		fi
	else
		mkdir -p ${TOOLCHAIN_TEST}
		if [ $? -ne 0 ]; then
			Test_Info "Has no right to create folder $TOOLCHAIN_TEST, pls. create it and chown it to test user"
			return 2
		fi
	fi

	# If there is a toolchain folder under $TOOLCHAIN_TEST, let's remove it
	if [ -d ${TOOLCHAIN_TEST}/poky ]; then
		rm -rf ${TOOLCHAIN_TEST}/poky
	fi

	# Copy toolchain into $TOOLCHAIN_TEST
	cp -r ${TEST_TMP}/opt/poky ${TOOLCHAIN_TEST}
	ret=$?

	if [ $ret -eq 0 ]; then
		Test_Info "Successfully copy toolchain into $TOOLCHAIN_TEST"
		return $ret
	else
		Test_Info "Meet error when copy toolchain into $TOOLCHAIN_TEST"
		return $ret
	fi
else
	Test_Info "No tarball named ${sdk_name}-toolchain-gmae under ${toolchain_dir}"
	return $ret
fi

}

Function to execute command and exit if run out of time

$1 is timeout value

$2 is the command to be executed

Test_Time_Out() { local timeout=$1 shift local command=$* local date=0 local tmp=mktemp local ret=1 local pid=0 local ppid=0 local i=0 declare local pid_l

# Run command in background
($command; echo $? > $tmp) &
pid=$!
while ps -e -o pid | grep -qw $pid; do
	if [ $date -ge $timeout ]; then
		Test_Info "$timeout Timeout when running command $command"
		rm -rf $tmp

		# Find all child processes of pid and kill them
		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_l[$i]=`ps -f --ppid $ppid | awk '{if ($2 != "PID") print $2}'`
			ppid=${pid_l[$i]}
			i=$((i+1))
			ps -f --ppid $ppid
			ret=$?
		done

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

			# Kill the parent id
			kill $pid
			return 1
	fi
	sleep 5
	date=`expr $date + 5`
done
ret=`cat $tmp`
rm -rf $tmp
return $ret

}

Function to test toolchain

$1 is test project name

$2 is the timeout value

Test_Toolchain() { local test_project=$1 local timeout=$2 local ret=1 local suffix="tar.bz2" local env_setup="" local pro_install="${TEST_TMP}/pro_install"

# Set value for PROJECT_PV and PROJECT_DOWNLOAD_URL accordingly
if [ $test_project == "cvs" ]; then
	PROJECT_PV=1.12.13
	PROJECT_DOWNLOAD_URL="http://ftp.gnu.org/non-gnu/cvs/source/feature/1.12.13/cvs-1.12.13.tar.bz2"
elif [ $test_project == "iptables" ]; then
	PROJECT_PV=1.4.11
	PROJECT_DOWNLOAD_URL="http://netfilter.org/projects/iptables/files/iptables-1.4.11.tar.bz2"
elif [ $test_project == "sudoku-savant" ]; then
	PROJECT_PV=1.3
	PROJECT_DOWNLOAD_URL="http://downloads.sourceforge.net/project/sudoku-savant/sudoku-savant/sudoku-savant-1.3/sudoku-savant-1.3.tar.bz2"
else
	Test_Info "Unknown test project name $test_project"
	return 1
fi

# Download test project and extract it
Test_Project_Prepare $TOOLCHAIN_PROJECTS $test_project
if [ $? -ne 0 ]; then
	Test_Info "Prepare test project file failed"
	return 1
fi

# Extract toolchain tarball into ${TEST_TMP}
Test_Toolchain_Prepare $TOOLCHAIN_DIR $SDK_NAME
ret=$?
if [ $ret -ne 0 ]; then
	Test_Info "Prepare toolchain test environment failed"
	return $ret
fi

if [ ! -d ${pro_install} ]; then
	mkdir -p ${pro_install}
fi

# Begin to build test project in toolchain environment
env_setup=`find ${TOOLCHAIN_TEST}/poky -name "environment-setup*"`

source $env_setup

if [ $test_project == "cvs" -o $test_project == "iptables" ]; then
	cd ${TEST_TMP}/${test_project}-${PROJECT_PV}
	Test_Time_Out $timeout ./configure ${CONFIGURE_FLAGS} || { Test_Info "configure failed with $test_project"; return 1; }
	Test_Time_Out $timeout make -j4 || { Test_Info "make failed with $test_project"; return 1; }
	Test_Time_Out $timeout make install DESTDIR=${pro_install} || { Test_Info "make failed with $test_project"; return 1; }
	cd -
	ret=0
elif [ $test_project == "sudoku-savant" ]; then
	cd ${TEST_TMP}/${test_project}-${PROJECT_PV}
	Test_Time_Out $timeout ./configure ${CONFIGURE_FLAGS} || { Test_Info "configure failed with $test_project"; return 1; }
	Test_Time_Out $timeout make -j4 || { Test_Info "make failed with $test_project"; return 1; }
	cd -
	ret=0
else
	Test_Info "Unknown test project $test_project"
	ret=1
fi

return $ret

}