xref: /openbmc/openbmc-test-automation/lib/tools.exp (revision bfa16ee4f68964bd5dd20618cb3b293584b78c69)
1#!/usr/bin/expect
2
3# This file provides many valuable expect procedures like handle_timeout and
4# handle_eof.
5
6my_source [list print.tcl]
7
8
9proc handle_timeout { description } {
10
11  # Print timeout error message to stderr and exit 1.
12
13  # Description of argument(s):
14  # description                     A description of what was being expected
15  #                                 (e.g. "an SOL login prompt").
16
17  global spawn_id
18  global expect_out
19
20  set timeout [get_stack_var timeout {} 2]
21
22  if { $timeout == 1 } {
23    set seconds "second"
24  } else {
25    set seconds "seconds"
26  }
27
28  puts stderr ""
29  print_error "Did not get ${description} after $timeout ${seconds}.\n"
30  # Using uplevel to be able to access expect_out.
31  if { [ catch {uplevel { puts stderr [sprint_var expect_out]}} result ] } {
32    puts stderr [sprint_varx expect_out "<not set>"]
33  }
34  # If caller has exit_proc defined, call it.  Otherwise, just call exit.
35  if { [info procs "exit_proc"] != "" } {
36    exit_proc 1
37  }
38  exit 1
39
40}
41
42
43proc handle_eof { description } {
44
45  # Print end-of-file error message to stderr and exit 1.
46
47  # Description of argument(s):
48  # description                     A description of what was being expected
49  #                                 (e.g. "an SOL login prompt").
50
51  global spawn_id
52
53  puts stderr ""
54  print_error "Reached end of file before getting $description.\n"
55  # Using uplevel to be able to access expect_out.
56  if { [ catch {uplevel { puts stderr [sprint_var expect_out]}} result ] } {
57    puts stderr [sprint_varx expect_out "<not set>"]
58  }
59  # If caller has exit_proc defined, call it.  Otherwise, just call exit.
60  if { [info procs "exit_proc"] != "" } {
61    exit_proc 1
62  }
63  exit 1
64
65}
66
67
68proc expect_wrap {pattern_list message {timeout 15}} {
69
70  # Run the expect command for the caller and return the list index of the
71  # matching pattern.
72
73  # This function offers the following benefits over calling the expect
74  # command directly:
75  # - It makes program debug easier.  When the program is run with --debug=1,
76  # this function prints useful debug output.
77  # - It will do standardized timeout and eof handling.
78
79  # Description of argument(s):
80  # pattern_list                    A list of patterns to be matched.  If one
81  #                                 of the patterns matches, the list index of
82  #                                 the matching item will be returned.  By
83  #                                 default, each pattern is presumed to be a
84  #                                 regex.  If the caller wishes to, they may
85  #                                 precede each pattern with either of the
86  #                                 following: "-re ", "-gl " or "-ex " in
87  #                                 order to explicitly choose the kind of
88  #                                 match to be done..
89  # message                         A message explaining what is being
90  #                                 expected (e.g. "an SOL login prompt").
91  #                                 This will be included in output messages.
92  # timeout                         The expect timeout value.
93
94  # Example usage:
95  #   set result [expect_wrap\
96  #     [list $bad_user_pw_regex "sh: xauth: command not found"]\
97  #     "an SOL prompt" 10]
98  #
99  #   switch $result {
100  #     0 {
101  #       puts stderr "" ; print_error "Invalid username or password.\n"
102  #       exit_proc 1
103  #     }
104  #     1 {
105  #       dict set state ssh_logged_in 1
106  #     }
107  #   }
108
109  global spawn_id
110  global expect_out
111
112  # Recognized flags.
113  set flags [list "-re" "-ex" "-gl"]
114
115  # This helps debug efforts by removing leftover, stale entries.
116  array unset expect_out \[1-9\],string
117
118  # Prepare the expect statement.
119  append cmd_buf "global spawn_id\n"
120  append cmd_buf "global expect_out\n"
121  append cmd_buf "expect {\n"
122  set ix 0
123  foreach pattern $pattern_list {
124    # Check to see whether the caller has specified a flag (e.g. "-re",
125    # "-ex", etc.) at the beginning of the pattern.
126    set tokens [split $pattern " "]
127    if { [lsearch $flags [lindex $tokens 0]] != -1 } {
128      # Caller specified a flag.
129      set flag [lindex $tokens 0]
130      # Strip the flag from the pattern.
131      set pattern [string range $pattern 4 end]
132    } else {
133      set flag "-re"
134    }
135    append cmd_buf "  ${flag} {$pattern} {set expect_result $ix}\n"
136    incr ix
137  }
138  append cmd_buf "  timeout {handle_timeout \$message}\n"
139  append cmd_buf "  eof {handle_eof \$message}\n"
140  append cmd_buf "}\n"
141
142  dprint_timen "Expecting $message."
143  dprint_issuing "\n${cmd_buf}"
144  eval ${cmd_buf}
145
146  dprintn ; dprint_vars expect_out expect_result
147
148  return $expect_result
149
150}
151
152
153proc send_wrap {buffer {add_lf 1}} {
154
155  # Send the buffer to the spawned process.
156
157  # This function offers the following benefits over calling the send command
158  # directly:
159  # - It makes program debug easier.  When the program is run with --debug=1,
160  # this function prints useful debug output.
161
162  # Description of argument(s):
163  # buffer                          The string to be sent to the spawned
164  #                                 process.
165  # add_lf                          Send a line feed after sending the buffer.
166
167  # Example usage.
168  # Close the ssh session.
169  #   send_wrap "~."
170  #
171  #   set expect_result [expect_wrap\
172  #     [list "Connection to $host closed"]\
173  #     "a connection closed message" 5]
174
175  global spawn_id
176  global expect_out
177
178  set cmd_buf "send -- {${buffer}}"
179  dprint_issuing
180  eval ${cmd_buf}
181
182  if { $add_lf } {
183    send -- "\n"
184    set cmd_buf "send -- \"\\n\""
185    dprint_issuing
186    eval ${cmd_buf}
187  }
188
189}
190