diff options
author | Rui Miguel Silva <rmfrfs@gmail.com> | 2017-12-12 16:10:55 +0000 |
---|---|---|
committer | Rui Miguel Silva <rmfrfs@gmail.com> | 2017-12-12 16:10:55 +0000 |
commit | 37ab1fafe3615200d0f6fa26267f6159293da211 (patch) | |
tree | 20677179a7590e18b07937aa3e213e91a8bab273 | |
parent | a746a9ee8c3d6f5983aab5024f96f1f3a0ce09ff (diff) |
kernel_test: add initial script for testing kernel subsystemslinaro_kernel_testing
Add script and lib script, that have some basic tests that can be
extended to some of the kernel subsystems. for now it supports the
following subsystems and tests:
Subsystems Tests
accel:
present
axis
pressure:
present
value
temp
blte:
present
scan
gyro:
present
axis
temp
audio:
present
wifi:
present
scan
connect
transfer
disconnect
magn:
present
axis
docker:
kernel-mandatory
kernel-optional
mounts
This as it first run in warp7 board but can be adapted to any board and
devices. Please not the dependency to bash >= 4
Signed-off-by: Rui Miguel Silva <rui.silva@linaro.org>
-rwxr-xr-x | mbl_kernel_test | 488 | ||||
-rw-r--r-- | mbl_kernel_test_util.sh | 199 |
2 files changed, 687 insertions, 0 deletions
diff --git a/mbl_kernel_test b/mbl_kernel_test new file mode 100755 index 0000000..5573ab9 --- /dev/null +++ b/mbl_kernel_test @@ -0,0 +1,488 @@ +#!/bin/bash + +# tools needed to be installed in path +needed_commands='date cat' +machine='' +command='' + +subsystem='' +test_name='' + +bash_version_major_required=4 + +declare -A subsystems_tests=( [wifi]="present scan connect transfer disconnect" \ + [gyro]="present axis temp" \ + [pressure]="present value temp" \ + [blte]="present scan" \ + [audio]="present" \ + [accel]="present axis" \ + [magn]="present axis" \ + [docker]="kernel-mandatory kernel-optional mounts" \ + ) + +# Warp Devices +subsystem_dev_wifi="wlan0" +subsystem_dev_blte="hci0" +subsystem_dev_audio_warp="imx7sgtl5000" +subsystem_dev_gyro_warp="fxas2100x" +subsystem_dev_accel_warp="fxos8700" +subsystem_dev_magn_warp="fxos8700" +subsystem_dev_pressure_warp="mpl3115" + +# Warp Paths +subsystem_path_gyro="/sys/bus/iio/devices" +subsystem_path_accel="/sys/bus/iio/devices" +subsystem_path_magn="/sys/bus/iio/devices" +subsystem_path_pressure="/sys/bus/iio/devices" +subsystem_path_audio="/sys/class/sound/" + +docker_kernel_mandatory="NAMESPACES NET_NS PID_NS IPC_NS UTS_NS CGROUPS CGROUP_CPUACCT \ +CGROUP_DEVICE CGROUP_FREEZER CGROUP_SCHED CPUSETS MEMCG KEYS \ +VETH BRIDGE BRIDGE_NETFILTER NF_NAT_IPV4 IP_NF_FILTER IP_NF_TARGET_MASQUERADE \ +NETFILTER_XT_MATCH_ADDRTYPE NETFILTER_XT_MATCH_CONNTRACK NETFILTER_XT_MATCH_IPVS \ +IP_NF_NAT NF_NAT NF_NAT_NEEDED POSIX_MQUEUE" + +docker_kernel_optional="USER_NS SECCOMP CGROUP_PID MEMCG_SWAP MEMCG_SWAP_ENABLED \ +BLK_CGROUP BLK_DEV_THROTTLING IOSCHED_CFQ CFQ_GROUP_IOSCHED CGROUP_PERF \ +CGROUP_HUGETLB NET_CLS_CGROUP CGROUP_NET_PRIO CFS_BANDWIDTH FAIR_GROUP_SCHED \ +RT_GROUP_SCHED IP_VS IP_VS_NFCT IP_VS_RR EXT4_FS EXT4_FS_POSIX_ACL \ +EXT4_FS_SECURITY VXLAN CRYPTO CRYPTO_AEAD CRYPTO_GCM CRYPTO_SEQIV CRYPTO_GHASH \ +XFRM XFRM_USER XFRM_ALGO INET_ESP INET_XFRM_MODE_TRANSPORT IPVLAN \ +MACVLAN DUMMY NF_NAT_FTP NF_CONNTRACK_FTP NF_NAT_TFTP NF_CONNTRACK_TFTP AUFS_FS\ +BTRFS_FS BLK_DEV_DM DM_THIN_PROVISIONING OVERLAY_FS" + +docker_mount_points="/sys/fs/cgroup /sys/fs/cgroup/memory /sys/fs/cgroup/cpu \ +/sys/fs/cgroup/cpuactt /sys/fs/cgroup/freezer /sys/fs/cgroup/devices \ +/sys/fs/cgroup/cpuset" + +# Get Install Full Path +script=$(which $0) +script_path=$(dirname $script) +pushd $script_path > /dev/null +script_path=$(pwd -P) +popd > /dev/null + +source ${script_path}/./mbl_kernel_test_util.sh + +reset_command() { + command=$(printf "mbl_%s_%s" ${1} ${2}) + shift; shift; + args=$* +} + +print_usage() { + print_blue "Usage:" + print_blue "mbl_kernel_test [subsystem] [test] or create a link to this script" + print_blue "\n\twith the following format mbl_[subsystem]_[test]" + print_blue "\n\tEx: mbl_kernel_test blte present or..." + print_blue "\n\tcreate a link to this script named: mbl_blte_present" + + print_green "\nSubsystems\tTests" + for subsystem in ${!subsystems_tests[@]}; do + print_green "\n${subsystem}:" + for test in ${subsystems_tests[${subsystem}]}; do + print_green "\t\t${test}" + done + done + + exit 122 +} + +parse_command() { + local commands='' + command=$(basename $0) + args=${@} + + IFS='_' read -a commands <<< "${command%.*}" + # if command does not start with mbl_ it is not mbl test command # + [[ ${commands[0]} != mbl ]] && print_die "This is not a mbl test command!!!" + + # if second element in command is kernel, means that the script was + # call directly and that the arguments are the subsystem and test + if [[ ${commands[1]} == kernel ]]; then + reset_command ${args[0]} + IFS='_' read -a commands <<< "${command%.*}" + fi + + # Now start to parse and get the real subsystem and test to run # + subsystem=${commands[1]} + test_name=${commands[2]} + + contains_exactly ${subsystem} ${!subsystems_tests[@]}; ret_s=$? + ((ret_s != 0 )) && print_red "Tests for subsystem: ${subsystem} do not exist" + ((ret_s != 0)) && print_usage + + contains_exactly ${test_name} ${subsystems_tests[${subsystem}]}; ret_t=$? + ((ret_t != 0)) && print_red "Test ${test_name} for subsystem ${subsystem} does not exist" + ((ret_t != 0)) && print_usage +} + +# Wifi Subsystem +test_wifi_present() { + local needed_commands='ip nmcli wget mktemp cut' + local ip_out='' + local up_status='' + + print_blue "Checking needed commands..." + check_commands ${needed_commands} + ret=$? + (($ret == 0)) && print_ok || print_nok; (($ret != 0)) && return $ret + + print_blue "Checking subsystem device..." + set_subsystem_dev + ret=$? + (($ret == 0)) && print_ok || print_nok; (($ret != 0)) && return $ret + + print_blue "Checking Interface ${subsys_dev} present..." + ip_out=$(ip addr show | grep ${subsys_dev}) + (($ret == 0)) && print_ok || print_nok; (($ret != 0)) && return $ret + + print_blue "Checking Interface ${subsys_dev} is up..." + up_status=$(ip addr show | grep ${subsys_dev} | grep -i ",UP") + (($ret == 0)) && print_ok || print_nok; (($ret != 0)) && return $ret + + return 0 +} + +test_wifi_scan() { + local nmcli_out='' + local num_ssid=0 + + test_wifi_present + ret=$?; (($ret != 0)) && return $ret + + print_blue "Checking nmcli list command..." + nmcli_out="$(nmcli -f SSID d wifi list)" + ret=$? + (($ret == 0)) && print_ok || print_nok; (($ret != 0)) && return $ret + + print_blue "Checking nmcli list output..." + num_ssid=$(echo $nmcli_out | wc -w) + (($num_ssid > 1)) && print_ok || print_nok; (($num_ssid < 2)) && return 122 + + return 0 +} + +test_wifi_connect() { + local nmcli_out='' + local num_ssid=0 + local num_args=$# + + print_blue "Checking needed arguments (SSID and Passkey)..." + ((num_args == 2)) && ret=0 || ret=22 + (($ret == 0)) && print_ok || print_nok; (($ret != 0)) && return $ret + + SSID=${1} + PassKey=${2} + + test_wifi_present + ret=$?; (($ret != 0)) && return $ret + + print_blue "Checking nmcli connection..." + nmcli_out="$(nmcli d wifi c ${SSID} password ${PassKey})" + ret=$? + (($ret == 0)) && print_ok || print_nok; (($ret != 0)) && return $ret + + return 0 +} + +test_wifi_transfer() { + local needed_commands='wget mktemp' + local default_to_transfer="http://google.pt" + local output_file='' + local wget_output='' + local num_args=$# + + test_wifi_present + ret=$?; (($ret != 0)) && return $ret + + output_file=$(mktemp "/tmp/$(basename $0).XXXXXXXXXXXX") + + print_blue "Checking optional arguments (url to transfer)..." + ((num_args == 1)) && url=${1} || url=${default_to_transfer} + print_ok + + print_blue "Checking wget transfer of ${url}..." + wget_output=$(wget -O ${output_file} ${url} 2>&1 1> /dev/null) + ret=$? + (($ret == 0)) && print_ok || print_nok; (($ret != 0)) && return $ret + + print_blue "Checking transfered file..." + [[ -f ${output_file} ]] && ret=0 || ret=22 + rm -f ${output_file} + (($ret == 0)) && print_ok || print_nok; (($ret != 0)) && return $ret + + return 0 +} + +test_wifi_disconnect() { + local num_args=$# + local connection_uuid='' + + test_wifi_present + ret=$?; (($ret != 0)) && return $ret + + print_blue "Checking if arguments are given to connect before (SSID and Passkey)..." + ((num_args == 2)) && ret=0 || ret=22 + + if (($ret==0)); then + print_blue "\nGoing to connect first to SSID: ${1}" && + test_wifi_connect $@ + ret=$? + (($ret == 0)) || return $ret + else + print_blue " None Given " + print_ok + fi + + print_blue "Checking current active connection..." + nmcli_output=$(nmcli --fields uuid,device c show --active | grep ${subsys_dev}) + ret=$? + (($ret == 0)) && print_ok || print_nok; (($ret != 0)) && return $ret + + connection_uuid=$(echo $nmcli_output | cut -d " " -f 1) + + print_blue "Checking disconnect command..." + nmcli_output=$(nmcli c down ${connection_uuid}) + ret=$? + (($ret == 0)) && print_ok || print_nok; (($ret != 0)) && return $ret + + print_blue "Checking connecting again command..." + nmcli_output=$(nmcli c up ${connection_uuid}) + ret=$? + (($ret == 0)) && print_ok || print_nok; (($ret != 0)) && return $ret + + return 0 +} + +_test_device_present() { + local needed_commands='grep cat dc' + local find_out='' + + print_blue "Checking needed commands..." + check_commands ${needed_commands} + ret=$? + (($ret == 0)) && print_ok || print_nok; (($ret != 0)) && return $ret + + print_blue "Checking subsystem device..." + set_subsystem_dev + ret=$? + (($ret == 0)) && print_ok || print_nok; (($ret != 0)) && return $ret + + print_blue "Checking Device ${subsys_dev} present..." + set_subsystem_dev_path + ret=$? + (($ret == 0)) && print_ok || print_nok; (($ret != 0)) && return $ret + + return 0 +} + +_test_device_value() { + value_name=${1} + value_units=${2} + value_min=${3} + value_max=${4} + + print_blue "Checking reading ${value_name}..." + value_raw=$(cat ${subsys_dev_path}/in_${value_name}_raw) + ret=$? + (($ret != 0)) && return $ret + + value_scale=$(cat ${subsys_dev_path}/in_${value_name}_scale 2> /dev/null ) + ret_scale=$? + (($ret_scale == 0)) && value=$(echo "${value_raw} ${value_scale} * p" | dc) || value=${value_raw} + + print_blue "${value}${value_units}" + + [[ ! -z ${value_min} ]] && \ + ((${value%.*} < $value_min)) && print_blue " less than minimum allow $value_min" && return 22 + [[ ! -z ${value_max} ]] && \ + ((${value%.*} > $value_max)) && print_blue " more than maximum allow $value_max" && return 22 + + return 0 +} + +# Gyroscope Subsystem +test_gyro_present() { + _test_device_present + + return $? +} + +test_gyro_axis() { + test_gyro_present + ret=$?; (($ret != 0)) && return $ret + + all_axis="x y z" + + for axis in ${all_axis[@]}; do + print_blue "Checking reading ${axis} axis..." + axis_output=$(cat ${subsys_dev_path}/in_anglvel_${axis}_raw) + ret=$? + (($ret == 0)) && print_ok || print_nok; (($ret != 0)) && return $ret + done + + return 0 +} + +test_gyro_temp() { + test_gyro_present + ret=$?; (($ret != 0)) && return $ret + + _test_device_value "temp" "C" 0 45 + ret=$?; (($ret == 0)) && print_ok || print_nok; (($ret != 0)) && return $ret + + return 0 +} + +# Pressure Subsystem +test_pressure_present() { + _test_device_present + + return $? +} + +test_pressure_value() { + test_pressure_present + ret=$?; (($ret != 0)) && return $ret + + _test_device_value "pressure" "kPa" 60 110 + ret=$?; (($ret == 0)) && print_ok || print_nok; (($ret != 0)) && return $ret + + return 0 +} + +test_pressure_temp() { + test_pressure_present + ret=$?; (($ret != 0)) && return $ret + + _test_device_value "temp" "C" 0 45 + ret=$?; (($ret == 0)) && print_ok || print_nok; (($ret != 0)) && return $ret + + return 0 +} + +# Bluetooth Subsystem +test_blte_present() { + local needed_commands='hcitool' + + print_blue "Checking needed commands..." + check_commands ${needed_commands} + ret=$?; (($ret == 0)) && print_ok || print_nok; (($ret != 0)) && return $ret + + print_blue "Checking subsystem device..." + set_subsystem_dev + ret=$?; (($ret == 0)) && print_ok || print_nok; (($ret != 0)) && return $ret + + print_blue "Checking Interface ${subsys_dev} present..." + ip_out=$(hcitool dev | grep ${subsys_dev}) + ret=$?; (($ret == 0)) && print_ok || print_nok; (($ret != 0)) && return $ret + + return 0 +} + +test_blte_scan() { + + test_blte_present + ret=$?; (($ret != 0)) && return $ret + + print_blue "Checking ${subsys_dev} scan command..." + hcitool_out="$(hcitool -i ${subsys_dev} scan)" + ret=$?; (($ret == 0)) && print_ok || print_nok; (($ret != 0)) && return $ret + + return 0 +} + +# Audio System +test_audio_present() { + _test_device_present +} + +# Accelerometer System +test_accel_present() { + _test_device_present +} + +test_accel_axis() { + test_accel_present + ret=$?; (($ret != 0)) && return $ret + + all_axis="x y z" + + for axis in ${all_axis[@]}; do + print_blue "Checking reading ${axis} axis..." + axis_output=$(cat ${subsys_dev_path}/in_accel_${axis}_raw) + ret=$? + (($ret == 0)) && print_ok || print_nok; (($ret != 0)) && return $ret + done + + return 0 +} + +# Magnetometer System +test_magn_present() { + _test_device_present +} + +test_magn_axis() { + test_accel_present + ret=$?; (($ret != 0)) && return $ret + + all_axis="x y z" + + for axis in ${all_axis[@]}; do + print_blue "Checking reading ${axis} axis..." + axis_output=$(cat ${subsys_dev_path}/in_magn_${axis}_raw) + ret=$? + (($ret == 0)) && print_ok || print_nok; (($ret != 0)) && return $ret + done + + return 0 +} + +# Docker +test_docker_kernel-mandatory() { + zgrep_config ${docker_kernel_mandatory} + return $? +} + +test_docker_kernel-optional() { + zgrep_config ${docker_kernel_optional} + + # since this are optional we do not fail the test for nok in here # + return 0 +} + +test_docker_mounts() { + path_check ${docker_mount_points} + return $? +} + +start_test() { + print_green "##### Starting ${machine} Subsystem: ${subsystem} ----- Test: ${test_name}" + + # first check if there is a specific test function for this machine, + # if there is call it, if not call the generic one + [[ $(type -t test_${machine}_${subsystem}_${test_name}) ]] && + test_${machine}_${subsystem}_${test_name} $@ || + test_${subsystem}_${test_name} $@ + ret=$? + (($ret == 0)) && \ + print_pass "***** Ended ${machine} Subsystem: ${subsystem} -------- Test: ${test_name}" || \ + print_fail "***** Ended ${machine} Subsystem: ${subsystem} -------- Test: ${test_name}" + + exit $ret +} + +# +# Real Script Starts Here +# +check_bash_version + +check_commands ${needed_commands} + +check_machine + +parse_command $@ + +start_test ${args} diff --git a/mbl_kernel_test_util.sh b/mbl_kernel_test_util.sh new file mode 100644 index 0000000..28a1c45 --- /dev/null +++ b/mbl_kernel_test_util.sh @@ -0,0 +1,199 @@ +#!/bin/bash + + +with_timestamp=0 +with_color=0 +keep_going=0 +_needed_commands='which grep date cat echo tr' + +declare -A _supported_machines=( [warp]=i.MX7 [rpi3]=BCM2709 ) + +_print() { + local _color_prefix='' + local _color_sufix='' + local _timestamp='' + (($with_color > 0)) && { _color_prefix="\e[1;${2}m" ; _color_sufix="\e[0m" ; } + + if (( ${with_timestamp} > 0 )); then + _date=$(date "+%Y%m%d_%H%M%S") + _timestamp="[${_date}]: " + fi + [[ ! -z ${3} ]] && opt="-en" || opt="-e" + + echo $opt "${_color_prefix} ${_timestamp} ${1} ${_color_sufix}" +} + +print_blue() { + _print "$1" 34 n +} + +print_red() { + _print "$1" 31 +} + +print_yellow() { + _print "$1" 33 +} + +print_green() { + _print "$1" 32 +} + +print_ok() { + _print "[OK]" 32 +} + +print_nok() { + _print "***NOK***" 31 +} + +print_pass() { + _print "$1 ...................................... [PASS]" 32 +} + +print_die() { + print_red "$1" + exit 2 +} + +print_fail() { + print_red "$1 ...................................... [FAIL]" + exit 2 +} + +print_fatal() { + if (($keep_going > 0)); then + print_red "$1" + else + print_die "$1" + fi +} + +print_yn() { + print_blue "$1" + read -p "[y/n]? " + [[ "$REPLY" == "y" ]] && return 0 || return 1 +} + +path_check() { + local ret_final=0 + + for p in ${@}; do + print_blue "Checking path exists ${p}..." + [[ -d ${p} ]] && ret=0 || ret=-22 + ret=$?; (($ret == 0)) && print_ok || print_nok + (($ret != 0)) && (($ret_final == 0)) && ret_final=-22 + done + + return $ret_final +} + +zgrep_config() { + local needed_commands='zcat' + local options=${@} + local kernel_config="/proc/config.gz" + local zout='' + local ret_final=0 + + if [[ ! -f ${kernel_config} ]]; then + print_red "Kernel Config File ${kernel_config} does not exist..." + print_nok + return -22 + fi + + check_commands ${needed_commands} + ret=$?; (($ret != 0)) && return $ret + + for c in ${@}; do + print_blue "Checking config option ${c}..." + zout=$(zcat ${kernel_config} | grep "CONFIG_${c}=[y|m]") + ret=$?; (($ret == 0)) && print_ok || print_nok + (($ret != 0)) && (($ret_final == 0)) && ret_final=-22 + done + + return $ret_final +} + +assign() { + export "$1"="$2" +} + +contains_exactly() { + local e; for e in "${@:2}"; do [[ "$e" == "$1" ]] && return 0; done; return 1; +} + +contains() { + local e; for e in "${@:2}"; do [[ "$e" == *"$1"* ]] && return 0; done; return 1; +} + +check_bash_version() { + [[ ! -z ${bash_version_major_required} ]] && ((${BASH_VERSINFO[0]} < ${bash_version_major_required})); ret=$? + (( $ret == 0 )) && print_die "Sorry!! you need at least bash major version ${bash_version_major_required} to run this script" + [[ ! -z ${bash_version_minor_required} ]] && ((${BASH_VERSINFO[1]} < ${bash_version_minor_required})) + (( $ret == 0 )) && print_die "Sorry!! you need at least bash major version ${bash_version_minor_required} to run this script" + + return 0 +} + +check_commands() { + local needed_commands="${@} ${_needed_commands}" + missing_counter=0 + for needed_command in $needed_commands; do + if ! hash "${needed_command}" >/dev/null 2>&1; then + print_red "\n Command not found in PATH: $needed_command" >&2 + ((missing_counter++)) + fi + done + + if ((missing_counter > 0)); then + print_red "Minimum $missing_counter commands are missing in PATH,\ + \n please install them in your host machine aborting " >&2 + return 127 + fi +} + +check_machine() { + local hostname=$(cat /etc/hostname) + local hardware=$(cat /proc/cpuinfo | grep Hardware) + + # try to find machine using the hostname + for machine in ${!_supported_machines[@]}; do + [[ ${hostname} == *${machine}* ]] && break || machine='' + done + + # we could get the machine type from hostname, no need for other check # + [[ ! -z ${machine} ]] && return + + # if hostname was changed, try using the cpuinfo + for m in ${!_supported_machines[@]}; do + [[ ${hardware} == *${_supported_machines[$m]}* ]] && machine=$m && break || machine='' + done + + [[ -z ${machine} ]] && print_die "Failed to find the running machine" +} + +set_subsystem_dev() { + local subsys_dev_name=subsystem_dev_${subsystem} + subsys_dev=${!subsys_dev_name} + + [[ -z ${subsys_dev} ]] && subsys_dev_name=subsystem_dev_${subsystem}_${machine} + subsys_dev=${!subsys_dev_name} + + [[ -z ${subsys_dev} ]] && return 22 || return 0 +} + +set_subsystem_dev_path() { + local subsys_path_name=subsystem_path_${subsystem} + local subsys_path=${!subsys_path_name} + + [[ -z ${subsys_path} ]] && subsys_path_name=subsystem_dev_${subsystem}_${machine} + subsys_path=${!subsys_path_name} + + find_out=$(grep -l ${subsys_dev} ${subsys_path}/*/name 2>/dev/null) + subsys_dev_path=${find_out%/*} + [[ -z ${subsys_dev_path} ]] || return 0 + + find_out=$(grep -l ${subsys_dev} ${subsys_path}/*/id 2>/dev/null) + subsys_dev_path=${find_out%/*} + [[ -z ${subsys_dev_path} ]] && return 22 || return 0 +} |