From 82e74b762a2c4a43a6141694ae977ba858d2317f Mon Sep 17 00:00:00 2001 From: Robert Schwebel Date: Wed, 13 Jun 2012 17:31:01 +0200 Subject: tests: add acctest template Signed-off-by: Robert Schwebel --- tests/acctest | 545 ++++++++++++++++++++++++++++ tests/common_testlib | 991 +++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 1536 insertions(+) create mode 100755 tests/acctest create mode 100644 tests/common_testlib (limited to 'tests') diff --git a/tests/acctest b/tests/acctest new file mode 100755 index 0000000..29c2042 --- /dev/null +++ b/tests/acctest @@ -0,0 +1,545 @@ +#!/bin/bash + +# +# One can use: +# PTXDIST_PTXCONFIG +# PTXDIST_PLATFORMCONFIG +# PTXDIST_COLLECTIONCONFIG +# PTXDIST_BOARDSETUP +# to query other content: $(ptxd_get_ptxconf PTXCONF_SYSROOT_HOST) +# + +# current running kernel +KERNEL_RELEASE="3.4.2" + +SSH_COMMAND='rsh' + +if [ ! -e "${PTXDIST_PLATFORMCONFIG}" ]; then + echo "platformconfig is missing" + exit 1 +fi + +. "${PTXDIST_PLATFORMCONFIG}" + +if test -f "${PTXDIST_TOPDIR}/tests/libptxdisttest.sh" +then + source "${PTXDIST_TOPDIR}/tests/libptxdisttest.sh" +else + echo "${PTXDIST_TOPDIR}/tests/libptxdisttest.sh not found." >&2 + exit 1 +fi + +if [ ! -e ${PTXDIST_WORKSPACE}/tests/common_testlib ]; then + echo "${PTXDIST_WORKSPACE}/tests/common_testlib not found." >&2 + exit 1 +fi + +. ${PTXDIST_WORKSPACE}/tests/common_testlib + +# +# sanity checks +# +acctest_boardsetup + +. "${PTXDIST_BOARDSETUP}" + +# +# do we have network access to the target? +# +acctest_ping + +# +# check for required PTXdist version +# +acctest_ptxdist 2012.06.0 + +# +# check that the platform announces the correct name [EDITME] +# +acctest_platform_name pengutronix-versatilepb + +# +# check that the platform announces the correct release number [EDITME] +# +# FIXME - acctest_platform_release 2012-fixme + +# +# check for RSH +# +acctest_rsh_available + +# +# no need to continue if vital things are missing +# +all_on_board + +# +# check that "Kernel announces correct kernel release number" [EDITME] +# +acctest_kernel_release ${KERNEL_RELEASE} + +# +# Do not change the U-Boot-v2 without testing all of its features! +# +#PTXCONF_U_BOOT_V2_VERSION = 2.0.0-rc9 + +# +# Check, if this CPU has no FPU +# +#imx_fpu_test false + +# +# first, acquire the time to enable a realtimeclock clockspeed judgment at the end +# + +startingtimethere=$(remote 'date +%s') +startingtimehere=$(date +%s) + +## +## check flash partitions [EDITME] +## +#mtd_line[0]='00040000 00020000 "barebox"' +#mtd_line[1]='00020000 00020000 "bareboxenv"' +#mtd_line[2]='00160000 00020000 "splash"' +#mtd_line[3]='00400000 00020000 "kernel"' +#mtd_line[4]='07a40000 00020000 "root"' +# +#for mtdX in mtd0 mtd1 mtd2 mtd3 mtd4; do acctest_flash_partition $mtdX; done + +hardware_tests() { + # + # check memory + # + acctest_memory +} + +system_tests() { + + # + # check for vital files and devices + # + for device in \ + /dev/rtc0 \ + /dev/autofs \ + /dev/console \ + /dev/cpu_dma_latency \ + /dev/full \ + /dev/kmem \ + /dev/kmsg \ + /dev/mem \ + /dev/network_latency \ + /dev/network_throughput \ + /dev/null \ + /dev/port \ + /dev/ptmx \ + /dev/random \ + /dev/ttyAMA0 \ + /dev/ttyAMA1 \ + /dev/ttyAMA2 \ + /dev/ttyAMA3 \ + /dev/urandom \ + /dev/zero + do acctest_devicenode "$device"; done + + for device in \ + /dev/sda \ + /dev/sda1 + do acctest_devicenode "$device" block; done + + # FIXME how to test pipes? + # /dev/initctl + # /dev/log + + # + # check the clocksource + # should contain "timer3" + # + acctest_file_content /sys/devices/system/clocksource/clocksource0/current_clocksource timer3 + + # + # check for network interface(s) in sysfs + # + for device in \ + eth0 + do acctest_network_device "$device"; done + + + # + # check for specific bus(ses) in sysfs + # + for bus in \ + amba \ + pci \ + platform \ + scsi + do acctest_bus "$bus"; done + + # + # check that unwanted devices do not exist + # + for device in \ + /dev/ttyS0 \ + /dev/ttyS1 \ + /dev/ttyPSC0 \ + /dev/ttyPSC1 \ + /dev/fb1 \ + /dev/loop0 \ + /dev/loop1 + do acctest_nodevice "$device"; done + + # kernel module present? + #for module in \ + # usbcore \ + # usb_common \ + # ehci_hcd + #do acctest_module "$module"; done + + # + # Only the "noop" scheduler schould currently be present (and active) + # + #acctest_file_content /sys/block/mtdblock0/queue/scheduler "[noop] " + + # + # Ensure the network driver is in use + # + acctest_file_content /sys/bus/platform/devices/smc91x.0/modalias "platform:smc91x" + acctest_files /sys/bus/platform/devices/smc91x.0/driver + + # FIXME: do similar things for... + # + # /sys/bus/platform/devices/arm-charlcd + # /sys/bus/platform/devices/alarmtimer + # /sys/bus/platform/devices/versatile-i2c.0 + # /sys/bus/platform/devices/physmap-flash.0 + + # + # check for i2c devices in sysfs [EDITME] + # i2c IO PCA953x + #acctest_files /sys/bus/i2c/devices/0-0041 + # RTC PCF8563 + #acctest_files /sys/bus/i2c/devices/0-0051 + # LED Dimmer PCA9530 + #acctest_files /sys/bus/i2c/devices/0-0060 + + # + # check for wm97xx stuff + # + #acctest_files /sys/bus/platform/devices/wm9712-codec + #acctest_files /sys/bus/platform/devices/wm97xx-battery + #acctest_files /sys/bus/platform/devices/wm97xx-touch + + #acctest_files /sys/bus/ac97/devices/0-0:wm9712-codec + #acctest_files /sys/devices/platform/soc-audio/0-0:wm9712-codec + #acctest_files /sys/devices/platform/soc-audio/0-0:wm9712-codec/wm97xx-battery + #acctest_files /sys/devices/platform/soc-audio/0-0:wm9712-codec/wm97xx-touch + + # + # check for light sensor + # the driver for the max1037 is currently in staging + # so we do not really want it as default. + # the brave can find it after a modprobe with + # + # acctest_files /sys/bus/i2c/drivers/max1363 + +} + +environment_tests() { + # + # check if root filesystem is ext2 + # + acctest_rootfs_ext2 + + # + # check if vital processes are running, uhh sleeping + # FIXME: acctest_process seems to always return 0 + # as we have systemd running, this is no problem + # at the moment + acctest_process systemd + if [ $? -gt 0 ]; then + for process in \ + pure-ftpd \ + sshd \ + telnetd \ + udevd \ + lighttpd + # [EDITME] + do acctest_process "$process"; done + fi + # + # is an executable binary available + # + for command in \ + /bin/busybox \ + /bin/cp \ + /bin/dd \ + /bin/lsmod \ + /bin/mount \ + /bin/ping \ + /bin/ps \ + /bin/umount \ + /sbin/insmod \ + /sbin/rmmod \ + /sbin/modprobe + do acctest_command_executable "$command"; done + + # + # every target should support various filesystems + # + for filesystem in \ + ext2 \ + pipefs \ + tmpfs \ + devpts \ + mqueue + do acctest_filesystem_support "$filesystem"; done + # FIXME: vfat, msdos, nfs + + # + # deprecated filesystem that should NOT be supported + # + for filesystem in \ + usbfs + do acctest_filesystem_not_supported "$filesystem"; done + + # + # every target should support the inotify syscalls for + # file/dir monitoring + # + acctest_files /proc/sys/fs/inotify + + # + # check for a running busybox multi-call binary + # + acctest_busybox +} + +services_tests() { + # + # check network services + # + # because the systemd was unstable in the past and services got killed + # we do a really simple pentest here. Lower the last number (256), if + # fewer repetitions suffice + # + test_begin + + #acctest_network_services "ftp port is reachable" "21" "21/tcp open ftp" 2 + acctest_network_services "ssh port is reachable" "22" "22/tcp open ssh" 2 + #acctest_network_services "telnet port is reachable" "23" "23/tcp open telnet" 2 + acctest_network_services "http port is reachable" "80" "80/tcp open http" 2 + + checking "that thttpd is not running" + remote_assure_process "thttpd" + exitstatus=$? + host "test ${exitstatus} = 1" + result + + test_end +} + +audio_tests() { + # + # if the audio subsystem is up and running + # + acctest_files /proc/asound + + # SPI Host Controller + acctest_files /sys/bus/platform/devices/imx27-cspi.0 + acctest_files /sys/bus/platform/drivers/spi_imx/imx27-cspi.0 + + # if the first card is the correct one + # this file should contain "PMICaudio" + acctest_file_content /proc/asound/card0/id "xxx" + + + # + # aplay, arecord, madplay, alsactl and alsamixer are present + # + acctest_command_executable "/usr/bin/aplay" + acctest_command_executable "/usr/bin/arecord" + acctest_command_executable "/usr/bin/madplay" + acctest_command_executable "/usr/sbin/alsactl" + acctest_command_executable "/usr/bin/alsamixer" + + # check if the default audio settings are present + acctest_files /etc/asound.state +} + +usb_tests() { + # + # USB + # at least the host controller must be present + # + acctest_file_content /sys/bus/usb/devices/usb1/product "Freescale On-Chip EHCI Host Controller" + + # + # USB + # usbfs must NOT be present + # deprecated + acctest_filesystem_not_mounted /proc/bus/usb usbfs + + # + # USB: Does it work? + # + acctest_usb_working + + # USB Stick + acctest_filesystem "USB-Stick" "sda" "sda" "vfat" "/sbin/mkfs.vfat -F32" ",,b" +} + +sdcard_tests() { + # SDCard + # Note: if the SD card has a partition table the device node is mmcblk0p1 + # If it has no partition table the device node is mmcblk0 + acctest_filesystem "SDCard" "mmcblk0" "mmcblk0" "vfat" "/sbin/mkfs.vfat -F32" +} + +eeprom_tests() { + # AT24 EEPROM + acctest_files /sys/bus/i2c/devices/1-0052 + + # + # check eeprom read and write capability + # + acctest_eeprom_rw /sys/bus/i2c/devices/1-0052/eeprom 2048 +} + +eth_tests() { + # is the network up and running? + # + # FIXME - contains "unknown" + # acctest_file_content /sys/class/net/eth0/operstate "up" + + # + # Check if the MAC is setup correctly + # FIXME: Add all known i.MX27 MAC addresses here + # BTW: Its hard to test a valid MAC via network, when network is not running + # due to the lack of a MAC. ROTFL + acctest_valid_mac eth0 "52:54:00:12:34:56" +} + +devices_tests() { + + # check network throughput with iperf + # broken-iperf OFF + #acctest_network_throughput 10 50000 + + # + # check fb display resolution + # + acctest_display_resolution 640 480 + + # + # SRAM + # + # acctest_filesystem "SRAM" "mtdblock8" "mtdblock8" "minix" "/sbin/mkfs.minix -n 30 -v" "" + + + # + # check if hardware clock is accepting and reproducing date/time + # + acctest_hwclock + + # + # check CPU frequency scaling + # no cpufreq support for imx27 + # + # unless Big Brother wins, this tests never get executed + + if [ 4 -eq 5 ]; then + acctest_cpufreq() { + test_begin + checking "for ondemand as default cpufreq governor" + remote_compare "cat $1/scaling_governor" "ondemand" + result + checking "CPU frequency with performance governor" + remote "echo performance > $1/scaling_governor" + remote_compare "cat $1/cpuinfo_cur_freq" "399000" + result + checking "CPU frequency with powersave governor" + remote "echo powersave > $1/scaling_governor" + remote_compare "cat $1/cpuinfo_cur_freq" "133000" + result + checking "for ondemand as last set cpufreq governor on test exit" + remote "echo ondemand > $1/scaling_governor" + remote_compare "cat $1/scaling_governor" "ondemand" + result + test_end + } + + acctest_cpufreq /sys/devices/system/cpu/cpu0/cpufreq + + # + # ensure the ondemand governor speeds up when there is more than 30% load + # (default is 95%!) + # + acctest_file_content /sys/devices/system/cpu/cpu0/cpufreq/ondemand/up_threshold 30 + + # + # Check, if the scaling driver is setup correctly + # + acctest_file_content /sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_min_freq 66500 + acctest_file_content /sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_max_freq 400000 + acctest_file_content /sys/devices/system/cpu/cpu0/cpufreq/scaling_min_freq 66500 + acctest_file_content /sys/devices/system/cpu/cpu0/cpufreq/scaling_max_freq 400000 + fi + + # + # Check correct alignment of kernel and userland components + # + acctest_alignment + + # + # Realtime test cyclictest + # No -rt available for 2.6.28 yet OFF + #acctest_cyclictest + + # + # at last, remember that we wanted to compare the two realtime clocks + # + acctest_realtime_clock + + # check network reliability + # DEVELTIME OFF + acctest_network_reliability 1 +} + +print_banner() { + echo >&2 + echo "***** $1 *****" >&2 + echo >&2 +} + + + +echo Starting the tests. >&2 + +print_banner "Testing basic hardware" +hardware_tests + +print_banner "Testing if all devices are present." +system_tests + +print_banner "Testing the OS environment." +environment_tests + +print_banner "Testing for services." +services_tests + +print_banner "Testing installed devices." +#audio_tests +#usb_tests +#sdcard_tests +#eeprom_tests +eth_tests +#devices_tests + +echo -n All tests completed. >&2 +if [ $fail_count -gt 0 ] +then + printf "%8b" "${RED} $fail_count TEST(S) FAILED.${NC}\n" >&2 + exit 1 +else + echo >&2 + exit 0 +fi diff --git a/tests/common_testlib b/tests/common_testlib new file mode 100644 index 0000000..a37b196 --- /dev/null +++ b/tests/common_testlib @@ -0,0 +1,991 @@ +# +# Common test library +# + +# +# sanity checks +# +acctest_boardsetup() { + test_begin + checking "for boardsetup file" + test -f "${PTXDIST_BOARDSETUP}" + result fatal + test_end +} + +# +# test if we have a ptxconfig file in the project +# +acctest_ptxconfig() { + test_begin + checking "if ptxconfig exists" + test -e "${PTXDIST_WORKSPACE}/selected_ptxconfig" + result + test_end +} + +# +# do we have network access to the target? +# +acctest_ping() { + test_begin + checking "response to icmp ping requests" + ping -q -n -c1 ${PTXCONF_BOARDSETUP_TARGETIP} + result + test_end +} + +# +# Check if the target listens on a specific port +# Note: Runs on the host +# +# $1 name or ip address +# $2 check for port +# +function acctest_open_port() { + test_begin + checking "if port '$2' at '$1' waits for connections" + nc -z $1 $2 + result + test_end +} + +# +# check for required PTXdist version +# +# $1 Version to check for +# +acctest_ptxdist() { + test_begin + checking "ptxdist version" + test "${PTXDIST_VERSION_FULL}" = "$1" + result + test_end +} + +# +# $1 Partition string to test for +# +acctest_flash_partition() { + test_begin + local mtdX=$1 + local X=${mtdX/"mtd"} + checking "${mtdX} layout" + remote_compare "grep \"^${mtdX}\" /proc/mtd" "${mtdX}: ${mtd_line[$X]}" + result + test_end +} + +# +# check memory +# +acctest_memory() { + test_begin + local memory=$(echo $(remote 'grep "^MemTotal" /proc/meminfo') | sed -e "s/^MemTotal: *//g") + checking "memory: $memory" + test "${memory: -2}" = "kB" + result + test_end +} + +# +# Check for CPU's FPU feature (or not) +# +imx_fpu_test() { + + local fpu="" + test_begin + if [ $1 = true ]; then + checking "FPU support" + else + checking "No FPU support" + fi + fpu=$(echo $(remote 'grep "^Features" /proc/cpuinfo | grep vfp')) + if [ $1 = true ]; then + if [ -z "$fpu" ]; then + result_fail + else + result_ok + fi + else + if [ -z "$fpu" ]; then + result_ok + else + result_fail + fi + fi + test_end +} + +# +# check if root filesystem is jffs2 +# +acctest_rootfs_jffs2() { + test_begin + checking "if root filesystem is jffs2 and rw" + remote_compare 'mount | grep "/dev/root" | cut -f5 -d" "' 'jffs2' + result + test_end +} + +# +# check if root filesystem is ext2 +# +acctest_rootfs_ext2() { + test_begin + checking "if root filesystem is ext2 and rw" + remote_compare 'mount | grep "/dev/root" | cut -f5 -d" "' 'ext2' + result + test_end +} + +# +# check if root filesystem is ubifs +# +acctest_rootfs_ubifs() { + test_begin + checking "if root filesystem is ubifs and rw" + remote_compare 'mount | grep "ubi0:root" | cut -f5 -d" "' 'ubifs' + result + test_end +} + +# +# check if vital files are present +# +# $1 file to check for +# +acctest_files() { + test_begin + checking "if file $1 exists" + remote_file "$1" exists + result + test_end +} + +# +# check if a file is not present +# +# $1 file to check for +# +acctest_no_files() { + test_begin + checking "if file $1 not exists" + remote_file "$1" exists + local exitstatus=$? + test ${exitstatus} -eq 1 + result + test_end +} +# +# check if a link is not present +# +# $1 file to check for +# +acctest_no_link() { + test_begin + checking "if link $1 not exists" + echo "remote \"test -h $1\"" >> "$LOGFILE" + remote "test -h \"$1\"" 2>> "$LOGFILE" + local exitstatus=$? + test ${exitstatus} -eq 1 + result + test_end +} + +# +# check if vital processes are running, uhh sleeping +# +acctest_process() { + test_begin + checking "if process $1 is active" + remote_assure_process "$1" + result + test_end +} + +# +# check for vital devices nodes +# +acctest_devicenode() { + + local DEV_TYPE=${2:-character} + test_begin + checking "if device $1 exists" + remote_file "$1" $DEV_TYPE + result + test_end +} + +# +# check for network interface(s) in sysfs +# +acctest_network_device() { + test_begin + checking "if network interface $1 exists" + remote_file "/sys/class/net/$1" exists + result + test_end +} + +# +# check for specific bus(ses) in sysfs +# +acctest_bus() { + test_begin + checking "if bus $1 exists" + remote_file "/sys/bus/$1" exists + result + test_end +} + +# +# check for specific class(ses) in sysfs +# +acctest_class() { + test_begin + checking "if class $1 exists" + remote_file "/sys/class/$1" exists + result + test_end +} + +# +# check that unwanted devices do not exist +# +acctest_nodevice() { + test_begin + checking "that device $1 does not exist" + remote_file "$1" exists + local exitstatus=$? + test ${exitstatus} -eq 1 + result + test_end +} + +# +# is an executable binary available +# +acctest_command_executable() { + test_begin + checking "if command $1 is executable" + remote_file "$1" executable + result + test_end +} + +# +# kernel module present? +# +acctest_module() { + test_begin + checking "if module $1 appears in lsmod" + remote_assure_module "$1" + result + test_end +} + +# +# check that "Kernel announces correct kernel release number" +# +# $1 kernel release string +# +acctest_kernel_release() { + test_begin + checking "kernel release number" + remote_compare 'uname -r' "$1" + result + test_end +} + +# +# check that the platform announces the correct name [EDITME] +# +# $0 platform name +# +acctest_platform_name() { + test_begin + checking "platform name" + test "${PTXCONF_PLATFORM}" = "$1" + result + test_end +} + +# +# check that the platform announces the correct release number +# +# $1 Release number string +# +acctest_platform_release() { + test_begin + checking "platform release number" + test "${PTXCONF_PLATFORM_VERSION}" = "$1" + result + test_end +} + +# +# check network services (multiple test) +# +# $1 title +# $2 port number +# $3 string to check +# $4 penetration counter +# +acctest_network_services() { + checking "$1" + for i in $(seq $4) + do + local nmap=$(nmap ${PTXCONF_BOARDSETUP_TARGETIP}) + done + test "$(echo "$nmap" | grep "^$2/" | sed 's/ */ /g')" = "$3" + result +} + +# +# check network reliability +# +# $1 repeats +# +acctest_network_reliability() { + # test_begin in for loop + checking "for netcat on target" + remote_file "/bin/netcat" executable + result fatal + local repeats=$1 + local ddoptions="bs=10M count=1" + local randomdata=$(mktemp) || exit 1 + dd if=/dev/urandom of=$randomdata $ddoptions 2> /dev/null + local correctmd5=($(md5sum $randomdata)) + for i in `seq 1 $repeats`; + do + test_begin + checking "network reliability, pass $i of $repeats" + remote "(dd if=/dev/stdout $ddoptions 2>/dev/null | netcat -l -p 12222 > /dev/stdin &)"& + sleep 1 + local receivedmd5=($(netcat -q 3 ${PTXCONF_BOARDSETUP_TARGETIP} 12222 < $randomdata | md5sum)) + test ${receivedmd5[0]} = ${correctmd5[0]} + result + test_end + done + rm -f $randomdata +} + +# +# check network throughput with iperf +# +# $1 durations +# $2 how many kbits/s do we expect for a PASS +# +acctest_network_throughput() { + checking "for iperf on target" + remote_file "/usr/bin/iperf" executable + result fatal + checking "for running iperf server on this machine" + curl -s -m 1 "telnet://${PTXCONF_BOARDSETUP_SERVERIP}:5001" + if [ $? = 28 ] # iperf is running on this machine + then + result + local duration=$1 + local threshold=$2 + checking "network throughput averaged over $duration seconds" + local ret=$(remote "iperf -c ${PTXCONF_BOARDSETUP_SERVERIP} -d -t $duration -f k") + local upstream_id=$(echo "$ret" | grep ".* connected with .* 5001$" | sed 's/^\[\(.*\)\].*/\1/') + local downstream_id=$(echo "$ret" | grep "port 5001 connected with" | sed 's/^\[\(.*\)\].*/\1/') + local upstreamkbits=$(echo "$ret" | grep "^\[$upstream_id\] " | sed 's/ */ /g' | cut -f7 -d" ") + local upstreamkbits=$(echo "$upstreamkbits/1" | bc) # cut away decimal places + local downstreamkbits=$(echo "$ret" | grep "^\[$downstream_id\] " | sed 's/ */ /g' | cut -f7 -d" ") + local downstreamkbits=$(echo "$downstreamkbits/1" | bc) # cut away decimal places + write_to_log "Upstream (DUT to server): $upstreamkbits kbits/s" + write_to_log "Downstream (server to DUT): $downstreamkbits kbits/s" + test $upstreamkbits -ge $threshold -a $downstreamkbits -ge $threshold + result + else + write_to_log "There is no iperf server running on this machine at ${PTXCONF_BOARDSETUP_SERVERIP}!" + false + result + fi +} + +# +# check for a running busybox multi-call binary +# +acctest_busybox() { + test_begin + checking "for busybox" + ret=$(remote 'busybox | head -n1') + test "${ret:0:7}" = "BusyBox" + result + test_end +} + +# +# check fb display resolution +# +# $1 width +# $2 height +# +acctest_display_resolution() { + test_begin + local expected_resolution="$1 $2" + checking "frame buffer display resolution" + local ret=$(remote 'busybox | head -n1') +# remote_compare "/usr/sbin/fbset | awk \"NR == 2 {print \\\$2, \\\$3}\"" "${expected_resolution}" + remote_compare "/usr/sbin/fbset | grep geometry | awk \"{print \\\$2, \\\$3}\"" "${expected_resolution}" + result + test_end +} + +# +# check eeprom read and write capability +# +# $1 path to the entry +# $2 size +# +acctest_eeprom_rw() { + local zeromd5[1024]="0f343b0931126a20f133d67c2b018a3b" + local zeromd5[2048]="c99a74c555371a433d121f551d6c6398" + local zeromd5[4096]="620f0b67a91f7f74151bc5be745b7110" + local zeromd5[8192]="0829f71740aab1ab98b33eae21dee122" + local zeromd5[16384]="ce338fe6899778aacfc28414f2d9498b" + local zeromd5[32768]="bb7df04e1b0a2570657527a7e108ae23" + + test_begin + local eeprom_rw_startingtime=$(date +%s) + local path="$1" + local size=$2 + # The first 2KiB are used by uboot environment, we don't want to overwrite it, + # hence we only test the upper 2KiB + checking "eeprom read/write with random data" + remote "dd if=/dev/urandom bs=${size} count=1 2>/dev/null > /tmp/random.dat" + local correctmd5=($(remote "md5sum /tmp/random.dat")) + remote "dd if=/tmp/random.dat of=${path} bs=${size} seek=1 2>/dev/null" + remote "dd if=${path} of=/tmp/eeprom.dat bs=${size} skip=1 2>/dev/null" + local readmd5=($(remote "md5sum /tmp/eeprom.dat")) + test ${readmd5[0]} = ${correctmd5[0]} + result + checking "eeprom read/write with zeros" + remote "dd if=/dev/zero of=${path} bs=${size} count=1 seek=1 2>/dev/null" + remote "dd if=${path} of=/tmp/eeprom.dat bs=${size} skip=1 2>/dev/null" + local readzeromd5=($(remote "md5sum /tmp/eeprom.dat")) + local eeprom_rw_endingtime=$(date +%s) + test ${readzeromd5[0]} = ${zeromd5[${size}]} + result + test_end + # Now check if it took way too long to test the EEPROM. + # This happens for example when single-byte writing is being used + # instead of page-writing + test_begin + local timediff=$(($eeprom_rw_endingtime-$eeprom_rw_startingtime)) + checking "if test duration (= $timediff s) was below limit" + test ${timediff} -le 20 + result + test_end +} + +# +# check if hardware clock is accepting and reproducing date/time +# +acctest_hwclock() { + test_begin + local first=$(remote "date -u +%s") + local present_time=$(remote "date -u +%m%d%H%M%Y.%S") + # store present system time in hardware + remote "/sbin/hwclock --systohc" + checking "y2k capability of system clock" + # set a completely different date in system clock (and test y2k en route) + remote "date -u -s 200101010000.00" + local y2k=$(remote "date -u +%s") + test $(($y2k-978307200)) -le 2 + result + checking "functionality of hardware clock" + # restore the present time from hardware to system + remote "/sbin/hwclock --hctosys" + local second=$(remote "date -u +%s") + test $(($second-$first)) -le 2 + result + test_end +} + +# +# compare the two realtime clocks +# +acctest_realtime_clock() { + test_begin + local endingtimethere=$(remote 'date +%s') + local endingtimehere=$(date +%s) + local elapsedtimethere=$(($endingtimethere-$startingtimethere)) + local elapsedtimehere=$(($endingtimehere-$startingtimehere)) + checking "realtime clock retardation over a period of $elapsedtimehere seconds" + test \( $(($elapsedtimehere-$elapsedtimethere)) -le 2 \) -a \( $(($elapsedtimethere-$elapsedtimehere)) -le 2 \) + result + test_end +} + +# +# CAN tests +# Note: Don't use unfinished yet +# +acctest_can() { + local canhost="himalia" + local canhostport="can1" + local cantargetport="can0" + checking "for existing $cantargetport device on target" + remote_file "/dev/$cantargetport" exists + result fatal + checking "for candump on target" + remote "which candump" + result fatal + checking "for canconfig on target" + remote "which canconfig" + result fatal + for baudrate in 125 250 500 1000 + # for baudrate in 10 20 50 100 125 250 500 800 1000 + do + # CAN receive (host_cansend -> target_candump) + checking "CAN reception at $baudrate kbit/s" + remote 'rm -f cantest.log' + remote "canconfig $cantargetport baudrate $baudrate" + remote "candump -d -o cantest.log $cantargetport" + ssh -q $canhost "sudo ifconfig $canhostport down" + ssh -q $canhost "sudo canconfig $canhostport bitrate ${baudrate}000" + ssh -q $canhost "sudo ifconfig $canhostport up" + ssh -q $canhost "cansend $canhostport 0x43 0x41 0x4e 0x2d 0x54 0x45 0x53 0x54" + remote 'kill -SIGINT $(pidof candump)' + remote 'grep "<0x001> \[8\] 43 41 4e 2d 54 45 53 54" cantest.log' + local grepretval=$? + remote 'rm -f cantest.log' + test $grepretval = 0 + result + # CAN transmit (host_cansend -> target_cansend -> host_candump) + checking "CAN transmission at $baudrate kbit/s" + local candumpdata=$(ssh -q $canhost mktemp) + ssh -q $canhost "sudo ifconfig $canhostport down" + ssh -q $canhost "sudo canconfig $canhostport bitrate ${baudrate}000" + ssh -q $canhost "sudo ifconfig $canhostport up" + ssh -q $canhost "candump -d -o $candumpdata $canhostport" + remote "canconfig $cantargetport baudrate $baudrate" + local ret=$(remote 'cansend can0 0x43 0x41 0x4e 0x2d 0x54 0x45 0x53 0x54 2>&1') + local cansendretval=$? + if echo "$ret" | grep "write: No buffer space available" + then + write_to_log "write: No buffer space available" + false + result + else + ssh -q $canhost 'kill -SIGINT $(pidof candump)' + ssh -q $canhost "grep \"<0x001> \[8\] 43 41 4e 2d 54 45 53 54\" $candumpdata" + local grepretval=$? + ssh -q $canhost "rm -f $candumpdata" + test $cansendretval = 0 -a $grepretval = 0 + result + fi + # bulk cansend + checking "CAN queue filling at $baudrate kbit/s, 15000 frames" + ret=$(remote "cansend $cantargetport 0x43 0x41 0x4e 0x2d 0x54 0x45 0x53 0x54 --loop 15000 2>&1") + cansendretval=$? + if echo "$ret" | grep "write: No buffer space available" + then + write_to_log "write: No buffer space available" + false + result + else + test $cansendretval = 0 + result + fi + done +} + +# +# Realtime test cyclictest +# +acctest_cyclictest() { + test_begin + local threshold=100 # [EDITME], how many microseconds we allow for a PASS + checking "realtime performance with cyclictest (average < $threshold us)" + local ret=$(remote "cyclictest -n -p80 -t1 -i1000 -q -l10000") + local min=$(echo "${ret}" | sed "s/.*Min: *\([^ ]*\) .*/\1/") + local avg=$(echo "${ret}" | sed "s/.*Avg: *\([^ ]*\) .*/\1/") + local max=$(echo "${ret}" | sed "s/.*Max: *\([^ ]*\)/\1/") + # FIXME: We are using the *average* value as criterion while still not RT-PREEMPT. + test $avg -le $threshold + result + test_end +} +# +# Check if a filesystem is supported by the running kernel +# +acctest_filesystem_support() { + + test_begin + checking "if filesystem '$1' is available" + remote "grep $1 /proc/filesystems" + result + test_end +} + +# +# Check if a specific filesystem is NOT supported by the running kernel +# +acctest_filesystem_not_supported() { + test_begin + checking "if filesystem '$1' is disabled" + remote "grep $1 /proc/filesystems" + local exitstatus=$? + test ${exitstatus} -eq 1 + result + test_end +} + +# +# Check if a specific filesystem type is mounted at a specific location +# +acctest_filesystem_mounted() { + test_begin + checking "if '$2' is mounted at '$1'" + remote "mount | grep $1 | grep $2" + result + test_end +} + +# +# Check if a specific filesystem type is NOT mounted +# +acctest_filesystem_not_mounted() { + test_begin + checking "if '$1' is NOT mounted" + remote "mount | grep $1" + local exitstatus=$? + test ${exitstatus} -eq 1 + result + test_end +} + +# +# Check if the USB is working +# +acctest_usb_working() { + test_begin + checking "if the USB is working" + remote "/usr/bin/lsusb -vv" + result + test_end +} + +# +# Check a file content +# +acctest_file_content() { + acctest_files "$1" + test_begin + checking "if '$1' contains '$2'" + local string=$(remote "cat $1") + test "$string" = "$2" + result + test_end +} + +# +# Check for a valid MAC address +# +acctest_valid_mac() { + test_begin + checking "if '$1' has a valid MAC address" + local string=$(remote "cat /sys/class/net/$1/address") + if [ -z $string ]; then + result_fail + test_end + return 1 + fi + shift + until [ -z "$1" ]; do + if [ "$string" = "$1" ]; then + result_ok + test_end + return + fi + shift + done + + result_fail + test_end +} + +# +# check for RSH server running on target and its usability +# +acctest_rsh_available() { + acctest_open_port ${PTXCONF_BOARDSETUP_TARGETIP} 514 + local rsh_avail=$? + + if [ $rsh_avail -ne 0 ]; then + echo >&2 + echo "RSH port 514 isn\'t open though, exiting." >&2 + exit 1 + fi + + if ! remote_compare 'echo RSH RESPONSE TEST' 'RSH RESPONSE TEST' + then + echo >&2 + echo "RSH is selected as connection method. Port 514 seems to be open," >&2 + echo "but the RSH server does not respond as expected. Exiting." >&2 + exit 1 + fi +} + +# +# Do some tests on some kind of blockdevice +# +acctest_filesystem() { + local TESTFILE=/bin/busybox + local TESTFILE_BASE=$(basename ${TESTFILE}) + local NAME=$1 + local DEVICE=$2 + local PARTITION=$3 + local FS=$4 + local FS_MKFS=$5 + local SFDISK_OPTS=$6 + + test_begin + checking "for ${NAME} as device ${DEVICE}" + remote "grep '${DEVICE}\$' /proc/partitions" + result + [ $? != 0 ] && return 1 + + checking "for ${FS} support in the kernel" + remote "grep ${FS} /proc/filesystems" + result + [ $? != 0 ] && return 1 + + if [ -n "${SFDISK_OPTS}" ]; then + checking "if we can create a ${FS} partition" + remote "echo ${SFDISK_OPTS} | /sbin/sfdisk /dev/${DEVICE} 2>&1" + result + fi + + if [ -n "${FS_MKFS}" ]; then + checking "if we can create a ${FS} filesystem" + remote "${FS_MKFS} /dev/${PARTITION} 2>&1" + result + fi + checking "if we can mount a ${FS} filesystem" + remote "mount -t ${FS} /dev/${PARTITION} /mnt 2>&1" + result + + checking "write() on ${FS}" + remote "cp ${TESTFILE} /mnt" + result + + checking "read() on ${FS}" + remote "cmp /mnt/${TESTFILE_BASE} ${TESTFILE}" + result + + checking "unlink() on ${FS}" + remote "rm /mnt/${TESTFILE_BASE}" + result + + checking "if we can unmount a ${FS} filesystem" + remote 'umount /mnt 2>&1' + result + + test_end +} + +# +# Do some tests on some kind of flash device +# +acctest_flashfilesystem() { + + local TESTFILE=/bin/busybox + local TESTFILE_BASE=$(basename ${TESTFILE}) + local ERASE_CMD=${5:-flash_eraseall} + + acctest_devicenode "/dev/$2" + acctest_devicenode "/dev/$3" block + acctest_filesystem_support "$4" + + checking "if we can erase $1 flash partition $2" + remote "$ERASE_CMD /dev/$2 2>&1" + result || return 1 + + checking "if we can mount a $4 filesystem" + remote "mount -t $4 /dev/$3 /mnt 2>&1" + result + + checking "write() on $4" + remote "cp ${TESTFILE} /mnt" + result + + checking "read() on $4" + remote "cmp /mnt/${TESTFILE_BASE} ${TESTFILE}" + result + + checking "unlink() on $4" + remote "rm /mnt/${TESTFILE_BASE}" + result + + checking "if we can unmount a $4 filesystem" + remote 'umount /mnt 2>&1' + result + + test_end +} + +# +# On ARM we must monitoring /proc/cpu/alignment +# If there are other values than 0, our kernel has problems with incorrect +# alignment. +# +function acctest_alignment { + + local alignment="" + local ar="" + + test_begin + checking "if we can get content of /proc/cpu/alignment" + alignment=$(remote "cat /proc/cpu/alignment") + if [ -z "$alignment" ]; then + result_fail + test_end + return 1 + fi + result_ok + + ar=( ${alignment} ) + + checking "if user alignment counter is zero" + if [ ${ar[1]} -ne 0 ]; then + result_fail + else + result_ok + fi + + checking "if system alignment counter is zero" + if [ ${ar[3]} -ne 0 ]; then + result_fail + else + result_ok + fi + + checking "if skipped alignment is zero" + if [ ${ar[5]} -ne 0 ]; then + result_fail + else + result_ok + fi + + checking "if half alignment is zero" + if [ ${ar[7]} -ne 0 ]; then + result_fail + else + result_ok + fi + + checking "if word alignment is zero" + if [ ${ar[9]} -ne 0 ]; then + result_fail + else + result_ok + fi + + checking "if dword alignment is zero" + if [ ${ar[11]} -ne 0 ]; then + result_fail + else + result_ok + fi + + checking "if multi alignment is zero" + if [ ${ar[13]} -ne 0 ]; then + result_fail + else + result_ok + fi + + checking "if user faults is at least at 'fixup+warn'" + if [ ${ar[16]} -ge 3 ]; then + result_ok + else + result_fail + fi + + test_end +} + +# +# Measure target's time +# $1 period to measure (in seconds) +# +# This function is an exception. Its not a 'step', its a full +# 'test' due to the very special handling we need to get the 'time' +# command to provide the correct data we need. +# +function acctest_compare_time { + +( + local timeret=$(mktemp -q -u -p /tmp $timeret_XXXXXXXXX) + local ignore="" + local result="" + + test_begin + checking "for time anomalies ($1 seconds)" + + # change the time format for easier result parsing + TIMEFORMAT=$'%3R %3U %3S' + # FIXME here comes the qouting hell + ignore=$( { time rsh -n -l root ${PTXCONF_BOARDSETUP_TARGETIP} "sleep $1"; } 2> $timeret ) + if [ $? -ne 0 ]; then + echo "Something went wrong when rsh was running" + cat "$timeret" + rm -f "$timeret" + result_fail + test_end + return 1 + fi + + # the local time will measure the time the rsh command runs. + # we will get something like that: + # 10.01 0.00 0.01 + # we are interested in the first value + local ar=( $(cat $timeret) ) + + if [ -z "${ar[0]}" ]; then + echo "acctest_compare_time: Can't extract time" + cat "$timeret" + rm -f "$timeret" + result_fail + test_end + return 1 + fi + + # OK when the difference is less than 0.5s + result=$(echo "(${ar[0]}-${1}) < .5" | bc -l) + + if [ $result -eq 1 ]; then + result_ok + else + result_fail + fi + + rm -f "$timeret" + test_end +) +} + +USER_OUTPUT_PREFIX="${BLUE}* " +USER_OUTPUT_POSTFIX="${NC}" + +message_to_user() { + echo -e "${USER_OUTPUT_PREFIX}" >&2 + while [ $# != 0 ]; do + echo -e "${USER_OUTPUT_PREFIX}$1" >&2 + shift + done + echo -e "${USER_OUTPUT_PREFIX}${USER_OUTPUT_POSTFIX}" >&2 +} + +line_from_user() { + echo -ne "${USER_OUTPUT_PREFIX}" >&2 + read -p "$1 " >&2 + echo -e "${USER_OUTPUT_POSTFIX}" >&2 +} -- cgit v1.2.3