1#!/usr/bin/expect -f
2#
3# This scripts starts QEMU, loads and boots Linux/OP-TEE, then runs
4# tests in the guest. The return code is 0 for success, >0 for error.
5#
6# Options:
7#   -q        Suppress output to stdout (quiet)
8#   --tests   Type of tests to run, values: all, xtest and trusted-keys
9#   --timeout Timeout for each test (sub)case, in seconds [480]
10#   --xtest-args Optional arguments to xtest
11
12set bios "../out/bios-qemu/bios.bin"
13set cmd1 "cd /mnt/host/build/qemu_v8/xen"
14if {[info exists ::env(XEN_FFA)] && $::env(XEN_FFA) == "y"} {
15	set cmd2 "xl create guest_ffa.cfg"
16} else {
17	set cmd2 "xl create guest.cfg"
18}
19set cmd3 "xl console domu"
20set quiet 0
21set xtest_args ""
22if {[info exists ::env(RUST_ENABLE)] && $::env(RUST_ENABLE) == "y"} {
23	set rust_enable 1
24} else {
25	set rust_enable 0
26}
27
28# The time required to run some tests (e.g., key generation tests [4007.*])
29# can be significant and vary widely -- typically, from about one minute to
30# several minutes depending on the host machine.
31# The value here should be sufficient to run the whole optee_test suite
32# ('xtest') with all testsuites enabled (regression+gp+pkcs11).
33set timeout 900
34set tests "all"
35set basedir [file dirname $argv0]
36
37# Parse command line
38set myargs $argv
39while {[llength $myargs]} {
40	set myargs [lassign $myargs arg]
41	switch -exact -- $arg {
42		"--tests"	{set myargs [lassign $myargs ::tests]}
43		"--timeout"	{set myargs [lassign $myargs ::timeout]}
44		"-q"		{set ::quiet 1}
45		"--xtest-args"  {set myargs [lassign $myargs ::xtest_args]}
46	}
47}
48
49set cmd "xtest $xtest_args"
50
51proc info arg {
52	if {$::quiet==1} { return }
53	puts -nonewline $arg
54	flush stdout
55}
56
57proc check_test_result arg {
58	set casenum "none"
59	expect {
60		# Exit with error status as soon as a test fails
61		-re {  ([^ ]+) FAIL} {
62			info " $expect_out(1,string) FAIL\n"
63			exit 1
64		}
65		-re {rcu.*detected stalls} {
66			info " Kernel error: '$expect_out(0,string)'\n"
67			exit 1
68		}
69		# Crude progress indicator: print one # when each test [sub]case starts
70		-re {([\*o]) ([^ ]+) } {
71			set casenum $expect_out(2,string)
72			if {$expect_out(1,string) == "o"} {
73				if {$star == 1} {
74					# Do not count first subcase ('o') since start
75					# of test ('*') was counted already
76					set star 0
77					exp_continue
78				}
79			} else {
80				set star 1
81			}
82			info "#"
83			incr ncases
84			if {$ncases % 50 == 0} { info "\n" }
85			exp_continue
86		}
87		# Exit when result separator is seen
88		"+-----------------------------------------------------\r\r" {}
89		# Handle errors in TEE core output
90		-i $arg -re {(..TC:[^\n]*assertion[^\n]*failed at[^\n]*)} {
91			info "!!! $expect_out(1,string)\n"
92			exit 1
93		}
94		-i $arg -re {(..TC:[^\n]*Panic at[^\n]*)} {
95			info "!!! $expect_out(1,string)\n"
96			exit 1
97		}
98		timeout {
99			info "!!! Timeout\n"
100			info "TIMEOUT - test case too long or hung? (last test started: $casenum)\n"
101			exit 2
102		}
103	}
104	info "\nStatus: PASS ($ncases test cases)\n"
105}
106
107# Disable echoing of guest output
108log_user 0
109# Save guest console output to a file
110log_file -a -noappend "serial0.log"
111info "Starting QEMU..."
112open "serial1.log" "w+"
113spawn -open [open "|tail -f serial1.log"]
114set teecore $spawn_id
115spawn sh -c "$::env(QEMU) $::env(QEMU_CHECK_ARGS)"
116expect {
117	"Kernel panic" {
118		info "!!! Kernel panic\n"
119		exit 1
120	}
121	timeout {
122		info "!!! Timeout\n"
123		exit 1
124	}
125	"ogin:"
126}
127send -- "root\r\r"
128expect "# "
129info " done, guest is booted"
130if {$::env(XEN_BOOT) == "y"} {
131        info " (Xen Dom0)"
132}
133info ".\n"
134# Toolchain libraries might be here or there
135send -- "export LD_LIBRARY_PATH=/lib:/lib/arm-linux-gnueabihf\r"
136if {$tests == "all" || $tests == "xtest"} {
137	info "Running: $cmd...\n"
138	expect "# "
139	send -- "$cmd\r"
140	check_test_result $teecore
141}
142if {$::env(XEN_BOOT) == "y"} {
143	info " Booting DomU.\n"
144	expect "# "
145	info "Running: $cmd1...\n"
146	send -- "$cmd1\r"
147	expect "# "
148	info "Running: $cmd2...\n"
149	send -- "$cmd2\r"
150	expect "# "
151	info "Running: $cmd3...\n"
152	send -- "$cmd3\r"
153	expect {
154		"Kernel panic" {
155			info "!!! Kernel panic\n"
156			exit 1
157		}
158		timeout {
159			info "!!! Timeout\n"
160			exit 1
161		}
162		"login:"
163	}
164	send -- "root\r\r"
165	expect "# "
166	info " done, DomU is booted.\n"
167	# Toolchain libraries might be here or there
168	send -- "export LD_LIBRARY_PATH=/lib:/lib/arm-linux-gnueabihf\r"
169	expect "# "
170	if {$tests == "all" || $tests == "xtest"} {
171		info "Running: $cmd...\n"
172		send -- "$cmd\r"
173		check_test_result $teecore
174	}
175}
176if {$tests == "all" || $tests == "trusted-keys"} {
177	# Invoke Trusted Keys tests
178	source $basedir/trusted-keys.exp
179}
180if {($tests == "all" || $tests == "rust") && $::rust_enable == 1} {
181	# Invoke Rust tests
182	source $basedir/rust.exp
183}
184