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