xref: /freebsd-src/contrib/netbsd-tests/lib/libcurses/testframe.txt (revision 9268022b74279434ed6300244e3f977e56a8ceb5)
1*57718be8SEnji Cooper
2*57718be8SEnji CooperCURSES TESTFRAME
3*57718be8SEnji Cooper----------------
4*57718be8SEnji Cooper
5*57718be8SEnji Cooper1. Introduction
6*57718be8SEnji Cooper
7*57718be8SEnji CooperThe curses library is a complex piece of software and, often, changes
8*57718be8SEnji Coopermade to the library may introduce subtle bugs that are hidden by other
9*57718be8SEnji Cooperactions so a visual check of the curses output may look correct in
10*57718be8SEnji Coopersome circumstances and the bug only show itself after a certain
11*57718be8SEnji Coopersequence of actions.  To assist with validating that changes made to
12*57718be8SEnji Cooperthe curses library have no undesired effects an automated test is
13*57718be8SEnji Cooperneeded to detect and highlight any changes in the curses application
14*57718be8SEnji Cooperoutput stream.  The programmer can then analyse the output changes and
15*57718be8SEnji Coopereither correct a bug or update the automated test to accept the new
16*57718be8SEnji Cooperoutput as valid.
17*57718be8SEnji Cooper
18*57718be8SEnji Cooper2. Architecture
19*57718be8SEnji Cooper
20*57718be8SEnji CooperThe curses testframe consists of two separate programs connected by a
21*57718be8SEnji Coopernumber of pipes and a pseudo-tty (pty).  The programs are called the
22*57718be8SEnji Cooperdirector and the slave.  The director reads a configuration file of
23*57718be8SEnji Coopertests to perform, passes these commands to the slave over a pipe and
24*57718be8SEnji Cooperreads the pty for any output from the slave.  Data from the slave is
25*57718be8SEnji Coopercompared against expected output held in a file and any differences
26*57718be8SEnji Cooperare highlighted to the tester.  The slave is a curses application that
27*57718be8SEnji Cooperis forked by the director on start up.  It reads commands from the
28*57718be8SEnji Cooperdirector over a pipe, these commands are calls to curses routines
29*57718be8SEnji Cooperalong with the parameters required for the call.  The slave takes the
30*57718be8SEnji Cooperparameters and uses them as arguments for the requested curses routine
31*57718be8SEnji Coopercall.  The return value from the curses routine is passed back to the
32*57718be8SEnji Cooperdirector over another pipe, if the curses routine updates any passed
33*57718be8SEnji Cooperby reference arguments then these are also passed back to the director
34*57718be8SEnji Cooperfor analysis.
35*57718be8SEnji Cooper
36*57718be8SEnji Cooper3. Director
37*57718be8SEnji Cooper
38*57718be8SEnji CooperThe director has the following optional command line options:
39*57718be8SEnji Cooper
40*57718be8SEnji Cooper    -v	     	     enables verbose output to assist debugging
41*57718be8SEnji Cooper    -s slave_path    the director will execute slave_path as the slave
42*57718be8SEnji Cooper       		     process.  The default is ./slave
43*57718be8SEnji Cooper    -t term	     Sets the TERM environment variable to term when
44*57718be8SEnji Cooper       		     executing the slave.  The default is atf
45*57718be8SEnji Cooper
46*57718be8SEnji CooperThere is one mandatory command line parameter, that is a file name
47*57718be8SEnji Cooperthat contains the test command file.  The test command file holds the
48*57718be8SEnji Coopercalls required to exercise a particular curses routine and validate
49*57718be8SEnji Cooperboth the return codes from the routines and the output from the
50*57718be8SEnji Cooperslave.  The test language has a small number of commands, they are:
51*57718be8SEnji Cooper
52*57718be8SEnji Cooperassign:
53*57718be8SEnji Cooper      Assign a value to a variable.  The syntax is:
54*57718be8SEnji Cooper
55*57718be8SEnji Cooper      	     assign var_name value
56*57718be8SEnji Cooper
57*57718be8SEnji Cooper      Where var_name is the name of the variable.  Variable names are
58*57718be8SEnji Cooper      an arbitrary sequence of alphanumeric characters, the variable
59*57718be8SEnji Cooper      name must start with an alphabetic character. Value is the value
60*57718be8SEnji Cooper      to be assigned.  The value can either be a numeric or a string
61*57718be8SEnji Cooper      type.  Variables are created on first use and will be
62*57718be8SEnji Cooper      overwritten on each subsequent use.
63*57718be8SEnji Cooper
64*57718be8SEnji Coopercall, call2, call3, call4:
65*57718be8SEnji Cooper      All these are used to call curses routines, the only difference
66*57718be8SEnji Cooper      between then is the number of expected return values.  Call
67*57718be8SEnji Cooper      expects one return value, call2 expects 2, call3 expects 3 and
68*57718be8SEnji Cooper      call4 expects four.  Any parameters that are passed by reference
69*57718be8SEnji Cooper      and updated by the call are treated like returns.  So, for
70*57718be8SEnji Cooper      example, calling the function getyx() which has three
71*57718be8SEnji Cooper      parameters, the window, a pointer to storage for y and a pointer
72*57718be8SEnji Cooper      to storage for x would be called like this:
73*57718be8SEnji Cooper
74*57718be8SEnji Cooper      	 	 call3 OK 4 5 getyx $win1
75*57718be8SEnji Cooper
76*57718be8SEnji Cooper      Which calls getyx, the first (and possibly only) return is the
77*57718be8SEnji Cooper      return status of the function call, in this case we expect "OK"
78*57718be8SEnji Cooper      indicating that the call succeeded.  The next two returns are
79*57718be8SEnji Cooper      the values of y and x respectively, the parameter $win1 is a
80*57718be8SEnji Cooper      variable that was assigned by a previous call.  Any return can
81*57718be8SEnji Cooper      be assigned to a variable by including the variable name in a
82*57718be8SEnji Cooper      call return list.  Variables are referenced in a call parameter
83*57718be8SEnji Cooper      list by prefixing the name with a $ character.  All returns are
84*57718be8SEnji Cooper      validated against the expected values and an error raised if
85*57718be8SEnji Cooper      there is a mismatch.  The only exception to this is when the
86*57718be8SEnji Cooper      return is assigned to a variable.  Valid values for the returns
87*57718be8SEnji Cooper      list are:
88*57718be8SEnji Cooper
89*57718be8SEnji Cooper      	  	  variable - assign the return to the given variable
90*57718be8SEnji Cooper		             name.
91*57718be8SEnji Cooper      	  	  numeric  - the value of the return must match the
92*57718be8SEnji Cooper      	  	  	     number given.
93*57718be8SEnji Cooper		  string   - an arbitrary sequence of characters
94*57718be8SEnji Cooper      	  	  	     enclosed in double quotes.
95*57718be8SEnji Cooper		  ERR      - expect an ERR return
96*57718be8SEnji Cooper		  OK	   - expect an OK return
97*57718be8SEnji Cooper		  NULL	   - expect a NULL pointer return
98*57718be8SEnji Cooper		  NON_NULL - expect a pointer that is not NULL valued
99*57718be8SEnji Cooper
100*57718be8SEnji Cooper      There is one special parameter that can be passed to a call,
101*57718be8SEnji Cooper      that is the label STDSCR.  This parameter will be substituted by
102*57718be8SEnji Cooper      the value of stdscr when the function call is made.
103*57718be8SEnji Cooper
104*57718be8SEnji Coopercheck:
105*57718be8SEnji Cooper      Validate the value of a variable.  This allows a variable to be
106*57718be8SEnji Cooper      checked for an expected return after it has been assigned in a
107*57718be8SEnji Cooper      previous call.  The syntax is:
108*57718be8SEnji Cooper
109*57718be8SEnji Cooper      	       check var_name expected_result
110*57718be8SEnji Cooper
111*57718be8SEnji Cooper      Where var_name is a variable previously assigned and
112*57718be8SEnji Cooper      expected_result is one of the valid return values listed in the
113*57718be8SEnji Cooper      above call section.
114*57718be8SEnji Cooper
115*57718be8SEnji Coopercompare:
116*57718be8SEnji Cooper      Compares the output stream from the slave against the contents
117*57718be8SEnji Cooper      of a file that contains the expected
118*57718be8SEnji Cooper      output.  The syntax is:
119*57718be8SEnji Cooper
120*57718be8SEnji Cooper      	       compare filename
121*57718be8SEnji Cooper
122*57718be8SEnji Cooper      Where filename is the name of the file containing the expected
123*57718be8SEnji Cooper      output.  The file can either be an absolute path or relative
124*57718be8SEnji Cooper      path.  In the latter case the value of the environment variable
125*57718be8SEnji Cooper      CHECK_PATH will be prepended to the argument to provide the path
126*57718be8SEnji Cooper      to the file.  The contents of this file will be compared byte by
127*57718be8SEnji Cooper      byte against the output from the slave, any differences in the
128*57718be8SEnji Cooper      output will be flagged.  If the director is not in verbose mode
129*57718be8SEnji Cooper      then the first mismatch in the byte stream will cause the
130*57718be8SEnji Cooper      director to exit.
131*57718be8SEnji Cooper
132*57718be8SEnji Coopercomparend:
133*57718be8SEnji Cooper      Performs the same function as the above compare except that
134*57718be8SEnji Cooper      excess output from the slave is not discarded if there is more
135*57718be8SEnji Cooper      data from the slave than there is in the check file.  This
136*57718be8SEnji Cooper      allows chaining of multiple check files.
137*57718be8SEnji Cooper
138*57718be8SEnji Cooperdelay:
139*57718be8SEnji Cooper      Defines an inter-character delay to be inserted between
140*57718be8SEnji Cooper      characters being fed into the input of the slave.  The syntax
141*57718be8SEnji Cooper      is:
142*57718be8SEnji Cooper
143*57718be8SEnji Cooper		delay time
144*57718be8SEnji Cooper
145*57718be8SEnji Cooper      Where time is the amount of time to delay in milliseconds.
146*57718be8SEnji Cooper
147*57718be8SEnji Cooperinclude:
148*57718be8SEnji Cooper      Include the contents of another test file, the parser will
149*57718be8SEnji Cooper      suspend reading the current file and read commands from the
150*57718be8SEnji Cooper      include file until the end of file of the include file is
151*57718be8SEnji Cooper      reached at which point it will continue reading the original
152*57718be8SEnji Cooper      file.  Include files may be nested.  The syntax is:
153*57718be8SEnji Cooper
154*57718be8SEnji Cooper      	     	include filename
155*57718be8SEnji Cooper
156*57718be8SEnji Cooper      Where filename is the name of the file to include.  If the
157*57718be8SEnji Cooper      filename is not an absolute path then the contents of the
158*57718be8SEnji Cooper      environment variable INCLUDE_PATH are prepended to the file
159*57718be8SEnji Cooper      name.
160*57718be8SEnji Cooper
161*57718be8SEnji Cooperinput:
162*57718be8SEnji Cooper      Defines a string of characters that will be fed to the slave
163*57718be8SEnji Cooper      when a call requires input.  Any unused input will be discarded
164*57718be8SEnji Cooper      after the call that required the input is called.  The syntax
165*57718be8SEnji Cooper      is:
166*57718be8SEnji Cooper
167*57718be8SEnji Cooper		input "string to pass"
168*57718be8SEnji Cooper
169*57718be8SEnji Coopernoinput:
170*57718be8SEnji Cooper      Normally the director will error if an input function is called
171*57718be8SEnji Cooper      without input being previously defined, this is to prevent input
172*57718be8SEnji Cooper      functions causing the test to hang waiting for input that never
173*57718be8SEnji Cooper      comes.  If it is known that there is pending input for the slave
174*57718be8SEnji Cooper      then the noinput keyword can be used to flag that the input
175*57718be8SEnji Cooper      function has data available for it to read.  The noinput command
176*57718be8SEnji Cooper      only applies to the next function call then behaviour reverts to
177*57718be8SEnji Cooper      the default.
178*57718be8SEnji Cooper
179*57718be8SEnji CooperThe testframe can define different types of strings, the type of string
180*57718be8SEnji Cooperdepends on the type of enclosing quotes.  A null terminated string is
181*57718be8SEnji Cooperindicated by enclosing double (") quotes.  A byte string, one that is
182*57718be8SEnji Coopernot null terminated and may contain the nul character within it is
183*57718be8SEnji Cooperindicated by enclosing single (') quotes.  A string of chtype
184*57718be8SEnji Coopercharacter which are a combined attribute and character value is
185*57718be8SEnji Cooperindicated by enclosing backticks (`), for this type of string pairs of
186*57718be8SEnji Cooperbytes between the backticks are converted to an array of chtype, the
187*57718be8SEnji Cooperfirst byte is the attribute and the second is the character.
188*57718be8SEnji Cooper
189*57718be8SEnji CooperAll strings defined will have a simple set of character substitutions
190*57718be8SEnji Cooperperformed on them when they are parsed.  This allows the tester to
191*57718be8SEnji Cooperembed some control characters into the string.  Valid substitutions
192*57718be8SEnji Cooperare:
193*57718be8SEnji Cooper
194*57718be8SEnji Cooper	\e	escape
195*57718be8SEnji Cooper	\n	new line
196*57718be8SEnji Cooper	\r	carriage return
197*57718be8SEnji Cooper	\t	tab
198*57718be8SEnji Cooper	\\	\ character
199*57718be8SEnji Cooper	\nnn	Where nnn is three octal digits, the character
200*57718be8SEnji Cooper		represented by the octal number will be inserted into
201*57718be8SEnji Cooper		the string.
202*57718be8SEnji Cooper
203*57718be8SEnji CooperAny other invalid conversions will have the \ stripped and the
204*57718be8SEnji Coopersubsequent characters inserted into the string.
205*57718be8SEnji Cooper
206*57718be8SEnji CooperIntegers may be specified by either a plain numeric (e.g. 12345) or by
207*57718be8SEnji Cooperhexadecimal notation by prefixing the number with 0x (e.g. 0x3039).
208*57718be8SEnji CooperInternally, no distinction is made between the two formats and they
209*57718be8SEnji Coopercan be freely intermixed.
210*57718be8SEnji Cooper
211*57718be8SEnji CooperIntegers and variables containing integers can have operations
212*57718be8SEnji Cooperperformed on them.  Currently only bitwise ORing numbers together is
213*57718be8SEnji Coopersupported.  This can be done by separating a list of integers and
214*57718be8SEnji Coopervariables with the pipe (|) symbol and enclosing the entire list in
215*57718be8SEnji Cooperround brackets "()" like this:
216*57718be8SEnji Cooper
217*57718be8SEnji Cooper      ( $var1 | 0x0100 | $var2 | 512 )
218*57718be8SEnji Cooper
219*57718be8SEnji CooperVariables and integer constants may be freely intermixed.  The result
220*57718be8SEnji Cooperof the operation can either be used as an argument for a call or can
221*57718be8SEnji Cooperbe used as an expected result for a call.
222*57718be8SEnji Cooper
223*57718be8SEnji CooperIn addition to all the curses calls being supported by the slave,
224*57718be8SEnji Cooperthere is one more special call called "drain".  This call repeatedly
225*57718be8SEnji Coopercalled getch() until there are no more characters in stdin.  The call
226*57718be8SEnji Cooperassumes that the curses input is either in no delay or timed input
227*57718be8SEnji Coopermode otherwise the test will time out and fail.  This call can be used
228*57718be8SEnji Cooperto clear any pending input when testing testing a timed read to
229*57718be8SEnji Cooperprevent the input being used in a later test.
230*57718be8SEnji Cooper
231*57718be8SEnji Cooper4. Slave
232*57718be8SEnji Cooper
233*57718be8SEnji CooperThe user has no direct interaction with the slave process.  The slave
234*57718be8SEnji Cooperis forked off by the director communicates to the director over a set
235*57718be8SEnji Cooperof pipes and a pseudo-tty connected to its standard i/o file
236*57718be8SEnji Cooperdescriptors.  The slave executes the passed curses calls and passes
237*57718be8SEnji Cooperback return values to the director.  The slave automatically calls
238*57718be8SEnji Cooperinitscr() on start up.
239*57718be8SEnji Cooper
240*57718be8SEnji Cooper
241*57718be8SEnji Cooper
242