1#!/usr/bin/ksh 2# 3# 4# This file and its contents are supplied under the terms of the 5# Common Development and Distribution License ("CDDL"), version 1.0. 6# You may only use this file in accordance with the terms of version 7# 1.0 of the CDDL. 8# 9# A full copy of the text of the CDDL should have accompanied this 10# source. A copy of the CDDL is also available via the Internet at 11# http://www.illumos.org/license/CDDL. 12# 13 14# 15# Copyright 2022 Oxide Computer Company 16# 17 18# 19# Set up the environment with a standard locale and debugging tools to 20# help us catch failures. 21# 22export LC_ALL=C.UTF-8 23export LD_PRELOAD=libumem.so 24export UMEM_DEBUG=default 25unalias -a 26set -o pipefail 27 28gt_prog=/usr/sbin/gpioadm 29gt_arg0=$(basename $0) 30gt_data="$(dirname $0)/data" 31gt_exit=0 32gt_tmpfile="/tmp/gpioadm_test.$$" 33gt_dpio0="gpioadmtestsim00" 34gt_dpio1="gpioadmtestsim10" 35gt_dpio2="gpioadmtestsim21" 36 37warn() 38{ 39 typeset msg="$*" 40 [[ -z "$msg" ]] && msg="failed" 41 echo "TEST FAILED: $msg" >&2 42 gt_exit=1 43} 44 45fatal() 46{ 47 typeset msg="$*" 48 [[ -z "$msg" ]] && msg="failed" 49 echo "$sc_arg0: $msg" >&2 50 exit 1 51} 52 53cleanup() 54{ 55 rm -f "$gt_tmpfile" 56} 57 58# 59# This is an invocation of gpioadm that we want to verify runs 60# successfully. We do not care about it's output, only that it exits 0. 61# 62expect_success() 63{ 64 if ! $gt_prog $@ >/dev/null; then 65 warn "failed to run $@" 66 fi 67} 68 69# 70# This is an invocation of gpioadm that we want to verify exits 71# non-zero. We do not care if it is a failure or due to usage. 72# 73gpioadm_err() 74{ 75 typeset reason="$1" 76 shift 77 78 if $gt_prog $@ 2>/dev/null 1>/dev/null; then 79 warn "should have failed with args "$@", but passed" 80 return 81 fi 82 83 printf "TEST PASSED: $reason: %s\n" "$*" 84} 85 86# 87# This is a case where we expect gpioadm to exit sucessfully, but we 88# want to check its exit data against a known value. 89# 90check_output() 91{ 92 typeset outfile="$gt_data/$1" 93 shift 94 95 if ! $gt_prog $@ > $gt_tmpfile 2>&1; then 96 warn "$@: exited non-zero" 97 fi 98 99 if ! diff $outfile $gt_tmpfile; then 100 warn "$@: output mismatched" 101 else 102 printf "TEST PASSED: %s\n" "$*" 103 fi 104} 105 106check_dpio_link() 107{ 108 typeset dpio="$1" 109 110 if [[ ! -L "/dev/dpio/$dpio" ]]; then 111 warn "missing /dev link for $dpio" 112 else 113 printf "TEST PASSED /dev link for %s present\n" "$dpio" 114 fi 115} 116 117# 118# This gets a specific GPIO's attribute value and confirm it's what we 119# expect. 120# 121check_attr_field() 122{ 123 typeset gpio="$1" 124 typeset attr="$2" 125 typeset exp="$3" 126 typeset field="$4" 127 typeset out= 128 129 out=$($gt_prog gpio attr get -p -o $field $gpio $attr) 130 if (( $? != 0 )); then 131 warn "failed to gpio attr get $gpio $attr" 132 return 133 fi 134 135 if [[ "$out" != "$exp" ]]; then 136 warn "$gpio $attr has $field $out, expected $exp" 137 else 138 printf "TEST PASSED: %s %s has expected %s %s\n" "$gpio" \ 139 "$attr" "$field" "$exp" 140 fi 141} 142 143check_attr_val() 144{ 145 check_attr_field $1 $2 $3 "value" 146} 147 148if [[ -n $GPIOADM ]]; then 149 gt_prog=$GPIOADM 150fi 151 152trap 'cleanup' EXIT 153 154# 155# These are a series of programs we expect to fail due to invalid 156# arguments and other variants that don't require state to be built up. 157# These are all basically bad flags, commands, or filters that don't 158# match. Other tests in the gpio test suite will go and verify the more 159# fine grained errors against libxpio directly. 160# 161gpioadm_err "bad command" foo 162gpioadm_err "bad command" foo bar 163gpioadm_err "incomplete command" controller 164gpioadm_err "bad command" controller nope 165gpioadm_err "bad command" controller wry 166gpioadm_err "bad flags" controller list -b 167gpioadm_err "parse without fields" controller list -p 168gpioadm_err "bad field" controller list -p -o itsatrap 169gpioadm_err "bad field" controller list -o itsatrap 170gpioadm_err "bad field" controller list -p -o controller,itsatrap 171gpioadm_err "unmatched filter" controller list this/doesnt/exist 172gpioadm_err "incomplete command" gpio 173gpioadm_err "bad command" gpio celes 174gpioadm_err "bad command" gpio celes terra 175gpioadm_err "bad flags" gpio list -r 176gpioadm_err "bad flags" gpio list -7 177gpioadm_err "parse without fields" gpio list -p 178gpioadm_err "bad field" gpio list -p -o 12345 179gpioadm_err "bad field" gpio list -o 12345 180gpioadm_err "bad field" gpio list -p -o name,12345 181gpioadm_err "unmatched filter" gpio list life/hopes/dreams 182gpioadm_err "unmatched filter" gpio list where do they come from 183gpioadm_err "match more than one with -1" gpio list -1 184gpioadm_err "match more than one with -1" gpio list -1 gpio_sim0 185gpioadm_err "match more than one with -1" gpio list -1 gpio_sim0 gpio_sim1 186gpioadm_err "match more than one with -1" gpio list -1 */open-drain 187gpioadm_err "match more than one with -1" gpio list -1 \ 188 gpio_sim0/periodic-500ms gpio_sim1/1v8 189gpioadm_err "incomplete command" gpio attr 190gpioadm_err "bad command" gpio attr where are they going 191gpioadm_err "missing controller/gpio" gpio attr get 192gpioadm_err "bad controller/gpio" gpio attr get null 193gpioadm_err "bad controller/gpio" gpio attr get gpio_sim/3 194gpioadm_err "bad controller/gpio" gpio attr get gpio_sim0/kefka 195gpioadm_err "parse without fields" gpio attr get gpio_sim0/3 -p 196gpioadm_err "bad flags" gpio attr get -p gpio_sim0/3 197gpioadm_err "bad flags" gpio attr get -x gpio_sim0/3 198gpioadm_err "bad fields" gpio attr get -p -o frodo gpio_sim1/2 199gpioadm_err "bad fields" gpio attr get -o sam gpio_sim1/2 200gpioadm_err "bad fields" gpio attr get -p -o sim:input,frodo gpio_sim1/2 201gpioadm_err "bad filter" gpio attr get gpio_sim0/3 dusk 202gpioadm_err "bad filter" gpio attr get gpio_sim0/3 sim:pull muysterious 203gpioadm_err "missing controller/gpio" gpio attr set 204gpioadm_err "bad controller/gpio" gpio attr set gandalf 205gpioadm_err "bad controller/gpio" gpio attr set gpio_sim/1 206gpioadm_err "bad controller/gpio" gpio attr set gpio_sim0/gimli 207gpioadm_err "missing attributes" gpio attr set gpio_sim0/1 208gpioadm_err "bad flags" gpio attr set -x gpio_sim0/4 sim:output=low 209gpioadm_err "bad attribute string" gpio attr set gpio_sim0/1 foo 210gpioadm_err "bad attribute string" gpio attr set gpio_sim0/1 foo= 211gpioadm_err "bad attribute value" gpio attr set gpio_sim0/1 sim:speed=random 212gpioadm_err "bad attribute value" gpio attr set gpio_sim0/1 sim:input=0x42 213gpioadm_err "incomplete command" dpio 214gpioadm_err "bad command" dpio alchemy 215gpioadm_err "bad flags" dpio list -m 216gpioadm_err "parse without fields" dpio list -p 217gpioadm_err "bad field" dpio list -p -o sabin 218gpioadm_err "bad field" dpio list -o edgar 219gpioadm_err "bad field" dpio list -p -o edgar,sabin,controller 220gpioadm_err "unmatched filter" dpio list locke/esper 221gpioadm_err "missing operands" dpio define 222gpioadm_err "missing dpio" dpio define cloud 223gpioadm_err "missing dpio" dpio define tifa/ 224gpioadm_err "missing dpio" dpio define sepiroth/7 225gpioadm_err "bad controller" dpio define cloud buster 226gpioadm_err "bad controller" dpio define tifa/ 7th 227gpioadm_err "bad controller" dpio define sepiroth/7 reunion 228gpioadm_err "bad controller" dpio define rufus/8 hq 229gpioadm_err "bad flags" dpio define -7 rufus/8 hq 230gpioadm_err "missing controller/gpio" dpio undefine 231gpioadm_err "bad controller/gpio" dpio undefine red13/ 232gpioadm_err "bad controller/gpio" dpio undefine cid/2 233gpioadm_err "bad dpio name" dpio define gpio_sim/1 '-trap' 234gpioadm_err "bad dpio name" dpio define gpio_sim/1 '+foobar' 235gpioadm_err "bad dpio name" dpio define gpio_sim/1 '$nope' 236gpioadm_err "bad dpio name" dpio define gpio_sim/1 '~sorry' 237gpioadm_err "bad dpio name" dpio define gpio_sim/1 \ 238 'thisisanamethatisactuallytoolongibelieve' 239gpioadm_err "bad dpio name" dpio define gpio_sim/1 'unsup()12#d' 240 241# 242# For the next set of tests we verify expected output from the various 243# listing operations with the goal of verifying that field selection, 244# parseability, omitting the header, and filtering is all working. Note, 245# we explicitly never use an unfiltered top-level list operation as we 246# have to assume that there will be something else on the system other 247# than the gpio_sim controllers that we create. 248# 249check_output "ctrl-list.out" controller list -o \ 250 controller,ngpios,ndpios,provider,path gpio_sim0 gpio_sim1 gpio_sim2 251check_output "ctrl-list-H.out" controller list -H -o \ 252 controller,ngpios,ndpios,provider,path gpio_sim0 gpio_sim1 gpio_sim2 253check_output "ctrl-list-p.out" controller list -p -o \ 254 controller,ngpios,ndpios,provider,path gpio_sim0 gpio_sim1 gpio_sim2 255check_output "ctrl-list-sim1.out" controller list -o \ 256 controller,ngpios,provider gpio_sim1 257check_output "ctrl-list-H-sim1.out" controller list -H -o \ 258 controller,ngpios,provider gpio_sim1 259check_output "ctrl-list-p-sim1.out" controller list -p -o \ 260 controller,ngpios,provider gpio_sim1 261check_output "gpio-period500.out" gpio list */periodic-500ms 262check_output "gpio-period500-H.out" gpio list -H */periodic-500ms 263check_output "gpio-period500-o.out" gpio list -o controller */periodic-500ms 264check_output "gpio-period500-p.out" gpio list -p -o controller */periodic-500ms 265check_output "gpio-sim0.out" gpio list gpio_sim0 266check_output "gpio-sim0-H.out" gpio list -H gpio_sim0 267check_output "gpio-sim0-o.out" gpio list -o controller gpio_sim0 268check_output "gpio-sim0-p.out" gpio list -p -o controller gpio_sim0 269check_output "gpio-sim01.out" gpio list gpio_sim0 gpio_sim1 270check_output "gpio-sim01-H.out" gpio list -H gpio_sim0 gpio_sim1 271check_output "gpio-sim01-o.out" gpio list -o controller gpio_sim0 gpio_sim1 272check_output "gpio-sim01-p.out" gpio list -p -o controller gpio_sim0 gpio_sim1 273check_output "attr-g0_0.out" gpio attr get gpio_sim0/0 274check_output "attr-g0_0-H.out" gpio attr get -H gpio_sim0/0 275check_output "attr-g0_0-o.out" gpio attr get -o attr,value,raw,possible \ 276 gpio_sim0/0 277check_output "attr-g0_0-Ho.out" gpio attr get -H -o attr,value,raw,possible \ 278 gpio_sim0/0 279check_output "attr-g0_0-p.out" gpio attr get -p -o attr,value,raw,possible \ 280 gpio_sim0/0 281check_output "attr-g0_0_filt.out" gpio attr get -o attr,value gpio_sim0/0 \ 282 name sim:pull sim:voltage 283check_output "attr-g0_0_filt-p.out" gpio attr get -p -o attr,value gpio_sim0/0 \ 284 name sim:pull sim:voltage 285# 286# Repeat the above with the actual GPIO name 287# 288check_output "attr-g0_0.out" gpio attr get gpio_sim0/1v8 289check_output "attr-g0_0-H.out" gpio attr get -H gpio_sim0/1v8 290check_output "attr-g0_0-o.out" gpio attr get -o attr,value,raw,possible \ 291 gpio_sim0/1v8 292check_output "attr-g0_0-Ho.out" gpio attr get -H -o attr,value,raw,possible \ 293 gpio_sim0/1v8 294check_output "attr-g0_0-p.out" gpio attr get -p -o attr,value,raw,possible \ 295 gpio_sim0/1v8 296check_output "attr-g0_0_filt.out" gpio attr get -o attr,value gpio_sim0/1v8 \ 297 name sim:pull sim:voltage 298check_output "attr-g0_0_filt-p.out" gpio attr get -p -o attr,value \ 299 gpio_sim0/1v8 name sim:pull sim:voltage 300 301# 302# To test DPIOs listing we need to actually go through and create a few 303# DPIOs. However, we also need to make sure that we leave the test with 304# these destroyed so we don't interfere with any other tests. 305# 306expect_success dpio define gpio_sim0/0 "$gt_dpio0" 307expect_success dpio define -r -w gpio_sim1/0 "$gt_dpio1" 308expect_success dpio define -r -K gpio_sim2/3v3 "$gt_dpio2" 309 310check_output "ctrl-list-dpio-p.out" controller list -p -o controller,ndpios \ 311 gpio_sim0 gpio_sim1 gpio_sim2 312 313check_output "dpio.out" dpio list "$gt_dpio0" "$gt_dpio1" "$gt_dpio2" 314check_output "dpio-H.out" dpio list -H "$gt_dpio0" "$gt_dpio1" "$gt_dpio2" 315check_output "dpio-o.out" dpio list -o dpio,caps,flags,controller,gpionum \ 316 "$gt_dpio0" "$gt_dpio1" "$gt_dpio2" 317check_output "dpio-Ho.out" dpio list -H -o dpio,caps,flags,controller,gpionum \ 318 "$gt_dpio0" "$gt_dpio1" "$gt_dpio2" 319check_output "dpio-p.out" dpio list -p -o dpio,caps,flags,controller,gpionum \ 320 "$gt_dpio0" "$gt_dpio1" "$gt_dpio2" 321 322# 323# Make sure the symlinks are installed correctly 324# 325check_dpio_link "$gt_dpio0" 326check_dpio_link "$gt_dpio1" 327check_dpio_link "$gt_dpio2" 328 329expect_success dpio undefine gpio_sim0/0 330expect_success dpio undefine gpio_sim1/0 331expect_success dpio undefine gpio_sim2/3v3 332 333# 334# Different gpio_sim gpios have different possible values and different 335# defaults. Make sure that we actually see different possible values for 336# the same attribute on different gpios and that it's not all the same. 337# Mix up the use of IDs and names. 338# 339check_attr_val gpio_sim1/1 name 3v3 340check_attr_val gpio_sim1/5 name open-drain 341check_attr_field gpio_sim1/3v3 sim:voltage 3.3V possible 342check_attr_field gpio_sim1/2 sim:voltage 12.0V possible 343check_attr_field gpio_sim1/open-drain sim:voltage 1.8V possible 344check_attr_field gpio_sim1/3 sim:pull disabled,23k-down,5k-up,40k-up possible 345check_attr_field gpio_sim1/0 sim:output disabled,low,high possible 346check_attr_field gpio_sim1/5 sim:output disabled,low possible 347check_attr_field gpio_sim1/5 sim:pull "disabled,down,up,up|down" possible 348 349# 350# Change around a few gpio sim attributes to make sure basic attribute 351# maniuplation works and then change them back. 352# 353check_attr_val gpio_sim0/3 sim:output low 354check_attr_val gpio_sim0/3 sim:pull 23k-down 355check_attr_val gpio_sim0/3 sim:input low 356expect_success gpio attr set gpio_sim0/3 sim:output=disabled sim:pull=40k-up 357check_attr_val gpio_sim0/3 sim:output disabled 358check_attr_val gpio_sim0/3 sim:pull 40k-up 359check_attr_val gpio_sim0/3 sim:input high 360expect_success gpio attr set gpio_sim0/3 sim:output=low sim:pull=23k-down 361check_attr_val gpio_sim0/3 sim:output low 362check_attr_val gpio_sim0/3 sim:pull 23k-down 363check_attr_val gpio_sim0/3 sim:input low 364 365# 366# Repeat with the name instead of the ID. 367# 368check_attr_val gpio_sim0/54V sim:output low 369check_attr_val gpio_sim0/54V sim:pull 23k-down 370check_attr_val gpio_sim0/54V sim:input low 371expect_success gpio attr set gpio_sim0/54V sim:output=disabled sim:pull=40k-up 372check_attr_val gpio_sim0/54V sim:output disabled 373check_attr_val gpio_sim0/54V sim:pull 40k-up 374check_attr_val gpio_sim0/54V sim:input high 375expect_success gpio attr set gpio_sim0/54V sim:output=low sim:pull=23k-down 376check_attr_val gpio_sim0/54V sim:output low 377check_attr_val gpio_sim0/54V sim:pull 23k-down 378check_attr_val gpio_sim0/54V sim:input low 379 380if (( gt_exit == 0 )); then 381 printf "All tests passed successfully!\n" 382fi 383