2 /* $NetBSD: testlang_parse.y,v 1.14 2015/01/04 20:19:46 christos Exp $ */
5 * Copyright 2009 Brett Lymn <blymn@NetBSD.org>
9 * This code has been donated to The NetBSD Foundation by the Author.
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. The name of the author may not be used to endorse or promote products
17 * derived from this software withough specific prior written permission
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
20 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
21 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
23 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
24 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
52 extern
int cmdpipe
[2];
53 extern
int slvpipe
[2];
55 extern
struct pollfd readfd
;
56 extern
char *check_path
;
57 extern
char *cur_file
; /* from director.c */
63 static int input_delay
;
65 /* time delay between inputs chars - default to 0.1ms minimum to prevent
66 * problems with input tests
70 /* time delay after a function call - allows the slave time to
71 * run the function and output data before we do other actions.
74 #define POST_CALL_DELAY 50
76 static struct timespec delay_spec
= {0, 1000 * DELAY_MIN
};
77 static struct timespec delay_post_call
= {0, 1000 * POST_CALL_DELAY
};
79 static char *input_str
; /* string to feed in as input */
80 static bool no_input
; /* don't need more input */
85 const char *returns_enum_names
[] = {
86 "unused", "numeric", "string", "byte", "ERR", "OK", "NULL", "not NULL",
87 "variable", "reference", "returns count", "slave error"
97 static const char *args_enum_names
[] = {
98 "static", "byte", "var", "NULL"
102 args_state_t arg_type
;
110 int nrets
; /* number of returns */
111 returns_t
*returns
; /* array of expected returns */
112 int nargs
; /* number of arguments */
113 args_t
*args
; /* arguments for the call */
116 static cmd_line_t command
;
125 static size_t nvars
; /* Number of declared variables */
126 static var_t
*vars
; /* Variables defined during the test. */
128 static int check_function_table
(char *, const char *[], int);
129 static int find_var_index
(const char *);
130 static void assign_arg
(args_state_t
, void *);
131 static int assign_var
(char *);
132 void init_parse_variables
(int);
133 static void validate
(int, void *);
134 static void validate_return
(const char *, const char *, int);
135 static void validate_variable
(int, returns_enum_t
, const void *, int, int);
136 static void validate_byte
(returns_t
*, returns_t
*, int);
137 static void write_cmd_pipe
(char *);
138 static void write_cmd_pipe_args
(args_state_t
, void *);
139 static void read_cmd_pipe
(returns_t
*);
140 static void write_func_and_args
(void);
141 static void compare_streams
(char *, bool);
142 static void do_function_call
(size_t);
143 static void save_slave_output
(bool);
144 static void validate_type
(returns_enum_t
, returns_t
*, int);
145 static void set_var
(returns_enum_t
, char *, void *);
146 static void validate_reference
(int, void *);
147 static char *numeric_or
(char *, char *);
148 static char *get_numeric_var
(const char *);
149 static void perform_delay
(struct timespec
*);
151 static const char *input_functions
[] = {
152 "getch", "getnstr", "getstr", "mvgetnstr", "mvgetstr", "mvgetnstr",
153 "mvgetstr", "mvscanw", "mvwscanw", "scanw", "wgetch", "wgetnstr",
157 static const unsigned ninput_functions
=
158 sizeof
(input_functions
) / sizeof
(char *);
160 saved_data_t saved_output
;
170 %token
<string> STRING
172 %token
<string> VARNAME
173 %token
<string> FILENAME
174 %token
<string> VARIABLE
175 %token
<string> REFERENCE
176 %token
<string> NULL_RET
177 %token
<string> NON_NULL
178 %token
<string> ERR_RET
179 %token
<string> OK_RET
180 %token
<string> numeric
181 %token
<string> DELAY
182 %token
<string> INPUT
183 %token
<string> COMPARE
184 %token
<string> COMPAREND
185 %token
<string> ASSIGN
186 %token EOL CALL CHECK NOINPUT OR LHB RHB
187 %token CALL2 CALL3 CALL4 DRAIN
193 statement
: /* empty */
204 | comparend statement
208 assign
: ASSIGN VARNAME numeric
{set_var
(ret_number
, $2, $3);} eol
209 | ASSIGN VARNAME LHB expr RHB
{set_var
(ret_number
, $2, $
<string>4);} eol
210 | ASSIGN VARNAME STRING
{set_var
(ret_string
, $2, $3);} eol
211 | ASSIGN VARNAME BYTE
{set_var
(ret_byte
, $2, $3);} eol
214 call
: CALL result fn_name args eol
{
219 call2
: CALL2 result result fn_name args eol
{
224 call3
: CALL3 result result result fn_name args eol
{
229 call4
: CALL4 result result result result fn_name args eol
{
234 check
: CHECK var returns eol
{
237 if
(command.returns
[0].return_index
== -1)
238 err
(1, "Undefined variable in check statement, line %zu"
239 " of file %s", line
, cur_file
);
242 fprintf
(stderr
, "Checking contents of variable %s for %s\n",
243 vars
[command.returns
[0].return_index
].name
,
244 returns_enum_names
[command.returns
[1].return_type
]);
247 if
(((command.returns
[1].return_type
== ret_byte
) &&
248 (vars
[command.returns
[0].return_index
].type
!= ret_byte
)) ||
249 vars
[command.returns
[0].return_index
].type
!= ret_string
)
250 err
(1, "Var type %s (%d) does not match return type %s (%d)",
252 vars
[command.returns
[0].return_index
].type
],
253 vars
[command.returns
[0].return_index
].type
,
254 returns_enum_names
[command.returns
[1].return_type
],
255 command.returns
[1].return_type
);
257 switch
(command.returns
[1].return_type
) {
259 validate_variable
(0, ret_string
, "ERR",
260 command.returns
[0].return_index
, 0);
264 validate_variable
(0, ret_string
, "OK",
265 command.returns
[0].return_index
, 0);
269 validate_variable
(0, ret_string
, "NULL",
270 command.returns
[0].return_index
, 0);
274 validate_variable
(0, ret_string
, "NULL",
275 command.returns
[0].return_index
, 1);
281 fprintf
(stderr
, " %s == returned %s\n",
282 (const char *)command.returns
[1].return_value
,
284 vars
[command.returns
[0].return_index
].value
);
286 validate_variable
(0, ret_string
,
287 command.returns
[1].return_value
,
288 command.returns
[0].return_index
, 0);
292 vptr
= &vars
[command.returns
[0].return_index
];
293 retvar.return_len
= vptr
->len
;
294 retvar.return_type
= vptr
->type
;
295 retvar.return_value
= vptr
->value
;
296 validate_byte
(&retvar
, &command.returns
[1], 0);
300 err
(1, "Malformed check statement at line %zu "
301 "of file %s", line
, cur_file
);
305 init_parse_variables
(0);
309 delay
: DELAY numeric eol
{
310 /* set the inter-character delay */
311 if
(sscanf
($2, "%d", &input_delay
) == 0)
312 err
(1, "delay specification %s could not be converted to "
313 "numeric at line %zu of file %s", $2, line
, cur_file
);
315 fprintf
(stderr
, "Set input delay to %d ms\n", input_delay
);
318 if
(input_delay
< DELAY_MIN
)
319 input_delay
= DELAY_MIN
;
321 * Fill in the timespec structure now ready for use later.
322 * The delay is specified in milliseconds so convert to timespec
325 delay_spec.tv_sec
= input_delay
/ 1000;
326 delay_spec.tv_nsec
= (input_delay
- 1000 * delay_spec.tv_sec
) * 1000;
328 fprintf
(stderr
, "set delay to %jd.%jd\n",
329 (intmax_t)delay_spec.tv_sec
,
330 (intmax_t)delay_spec.tv_nsec
);
333 init_parse_variables
(0);
337 input
: INPUT STRING eol
{
338 if
(input_str
!= NULL
) {
339 warnx
("%s, %zu: Discarding unused input string",
344 if
((input_str
= malloc
(strlen
($2) + 1)) == NULL
)
345 err
(2, "Cannot allocate memory for input string");
347 strlcpy
(input_str
, $2, strlen
($2) + 1);
352 noinput
: NOINPUT eol
{
353 if
(input_str
!= NULL
) {
354 warnx
("%s, %zu: Discarding unused input string",
362 compare
: COMPARE PATH eol
363 | COMPARE FILENAME eol
365 compare_streams
($2, true
);
370 comparend
: COMPAREND PATH eol
371 | COMPAREND FILENAME eol
373 compare_streams
($2, false
);
383 returns
: numeric
{ assign_rets
(ret_number
, $1); }
384 | LHB expr RHB
{ assign_rets
(ret_number
, $
<string>2); }
385 | STRING
{ assign_rets
(ret_string
, $1); }
386 | BYTE
{ assign_rets
(ret_byte
, (void *) $1); }
387 | ERR_RET
{ assign_rets
(ret_err
, NULL
); }
388 | OK_RET
{ assign_rets
(ret_ok
, NULL
); }
389 | NULL_RET
{ assign_rets
(ret_null
, NULL
); }
390 | NON_NULL
{ assign_rets
(ret_nonnull
, NULL
); }
394 assign_rets
(ret_var
, $1);
398 reference
: VARIABLE
{
399 assign_rets
(ret_ref
, $1);
403 if
(command.function
!= NULL
)
404 free
(command.function
);
406 command.function
= malloc
(strlen
($1) + 1);
407 if
(command.function
== NULL
)
408 err
(1, "Could not allocate memory for function name");
409 strcpy
(command.function
, $1);
415 { $
<string>$
= get_numeric_var
($1); }
417 { $
<string>$
= numeric_or
($
<string>1, $
<string>3); }
421 | LHB expr RHB
{ assign_arg
(arg_static
, $
<string>2); } args
422 | numeric
{ assign_arg
(arg_static
, $1); } args
423 | STRING
{ assign_arg
(arg_static
, $1); } args
424 | BYTE
{ assign_arg
(arg_byte
, $1); } args
425 | PATH
{ assign_arg
(arg_static
, $1); } args
426 | FILENAME
{ assign_arg
(arg_static
, $1); } args
427 | VARNAME
{ assign_arg
(arg_static
, $1); } args
428 | VARIABLE
{ assign_arg
(arg_var
, $1); } args
429 | NULL_RET
{ assign_arg
(arg_null
, $1); } args
438 excess
(const char *fname
, size_t lineno
, const char *func
, const char *comment
,
439 const void *data
, size_t datalen
)
441 size_t dstlen
= datalen
* 4 + 1;
442 char *dst
= malloc
(dstlen
);
447 if
(strnvisx
(dst
, dstlen
, data
, datalen
, VIS_WHITE | VIS_OCTAL
) == -1)
450 warnx
("%s, %zu: [%s] Excess %zu bytes%s [%s]",
451 fname
, lineno
, func
, datalen
, comment
, dst
);
456 * Get the value of a variable, error if the variable has not been set or
457 * is not a numeric type.
460 get_numeric_var
(const char *var
)
464 if
((i
= find_var_index
(var
)) < 0)
465 err
(1, "Variable %s is undefined", var
);
467 if
(vars
[i
].type
!= ret_number
)
468 err
(1, "Variable %s is not a numeric type", var
);
470 return vars
[i
].value
;
474 * Perform a bitwise OR on two numbers and return the result.
477 numeric_or
(char *n1
, char *n2
)
479 unsigned long i1
, i2
, result
;
482 i1
= strtoul
(n1
, NULL
, 10);
483 i2
= strtoul
(n2
, NULL
, 10);
486 asprintf
(&ret
, "%lu", result
);
489 fprintf
(stderr
, "numeric or of 0x%lx (%s) and 0x%lx (%s)"
490 " results in 0x%lx (%s)\n",
491 i1
, n1
, i2
, n2
, result
, ret
);
498 * Sleep for the specified time, handle the sleep getting interrupted
502 perform_delay
(struct timespec
*ts
)
504 struct timespec delay_copy
, delay_remainder
;
507 while
(nanosleep
(&delay_copy
, &delay_remainder
) < 0) {
509 err
(2, "nanosleep returned error");
510 delay_copy
= delay_remainder
;
515 * Assign the value given to the named variable.
518 set_var
(returns_enum_t type
, char *name
, void *value
)
524 i
= find_var_index
(name
);
526 i
= assign_var
(name
);
529 if
((type
== ret_number
) ||
(type
== ret_string
)) {
531 vars
[i
].len
= strlen
(number
) + 1;
532 vars
[i
].value
= malloc
(vars
[i
].len
+ 1);
533 if
(vars
[i
].value
== NULL
)
534 err
(1, "Could not malloc memory for assign string");
535 strcpy
(vars
[i
].value
, number
);
537 /* can only be a byte value */
539 vars
[i
].len
= ret
->return_len
;
540 vars
[i
].value
= malloc
(vars
[i
].len
);
541 if
(vars
[i
].value
== NULL
)
542 err
(1, "Could not malloc memory to assign byte string");
543 memcpy
(vars
[i
].value
, ret
->return_value
, vars
[i
].len
);
548 * Add a new variable to the vars array, the value will be assigned later,
549 * when a test function call returns.
552 assign_var
(char *varname
)
557 if
((name
= malloc
(strlen
(varname
) + 1)) == NULL
)
558 err
(1, "Alloc of varname failed");
560 if
((temp
= realloc
(vars
, sizeof
(*temp
) * (nvars
+ 1))) == NULL
) {
562 err
(1, "Realloc of vars array failed");
565 strcpy
(name
, varname
);
567 vars
[nvars
].name
= name
;
569 vars
[nvars
].value
= NULL
;
576 * Allocate and assign a new argument of the given type.
579 assign_arg
(args_state_t arg_type
, void *arg
)
586 fprintf
(stderr
, "function is >%s<, adding arg >%s< type %s\n",
587 command.function
, str
, args_enum_names
[arg_type
]);
590 cur.arg_type
= arg_type
;
593 cur.var_index
= find_var_index
(arg
);
594 if
(cur.var_index
< 0)
595 err
(1, "Invalid variable %s at line %zu of file %s",
596 str
, line
, cur_file
);
597 cur.arg_type
= ret_string
;
602 cur.arg_len
= ret
->return_len
;
603 cur.arg_string
= malloc
(cur.arg_len
);
604 if
(cur.arg_string
== NULL
)
605 err
(1, "Could not malloc memory for arg bytes");
606 memcpy
(cur.arg_string
, ret
->return_value
, cur.arg_len
);
611 cur.arg_string
= NULL
;
615 cur.arg_len
= strlen
(str
);
616 cur.arg_string
= malloc
(cur.arg_len
+ 1);
617 if
(cur.arg_string
== NULL
)
618 err
(1, "Could not malloc memory for arg string");
619 strcpy
(cur.arg_string
, arg
);
622 temp
= realloc
(command.args
, sizeof
(*temp
) * (command.nargs
+ 1));
624 err
(1, "Failed to reallocate args");
626 memcpy
(&command.args
[command.nargs
], &cur
, sizeof
(args_t
));
631 * Allocate and assign a new return.
634 assign_rets
(returns_enum_t ret_type
, void *ret
)
636 returns_t
*temp
, cur
;
640 cur.return_type
= ret_type
;
641 if
(ret_type
!= ret_var
) {
642 if
((ret_type
== ret_number
) ||
(ret_type
== ret_string
)) {
644 cur.return_len
= strlen
(ret_str
) + 1;
645 cur.return_value
= malloc
(cur.return_len
+ 1);
646 if
(cur.return_value
== NULL
)
648 "Could not malloc memory for arg string");
649 strcpy
(cur.return_value
, ret_str
);
650 } else if
(ret_type
== ret_byte
) {
652 cur.return_len
= ret_ret
->return_len
;
653 cur.return_value
= malloc
(cur.return_len
);
654 if
(cur.return_value
== NULL
)
656 "Could not malloc memory for byte string");
657 memcpy
(cur.return_value
, ret_ret
->return_value
,
659 } else if
(ret_type
== ret_ref
) {
660 if
((cur.return_index
= find_var_index
(ret
)) < 0)
661 err
(1, "Undefined variable reference");
664 cur.return_index
= find_var_index
(ret
);
665 if
(cur.return_index
< 0)
666 cur.return_index
= assign_var
(ret
);
669 temp
= realloc
(command.returns
, sizeof
(*temp
) * (command.nrets
+ 1));
671 err
(1, "Failed to reallocate returns");
672 command.returns
= temp
;
673 memcpy
(&command.returns
[command.nrets
], &cur
, sizeof
(returns_t
));
678 * Find the given variable name in the var array and return the i
679 * return -1 if var is not found.
682 find_var_index
(const char *var_name
)
689 for
(i
= 0; i
< nvars
; i
++) {
690 if
(strcmp
(var_name
, vars
[i
].name
) == 0) {
700 * Check the given function name in the given table of names, return 1 if
703 static int check_function_table
(char *function
, const char *table
[],
708 for
(i
= 0; i
< nfunctions
; i
++) {
709 if
((strlen
(function
) == strlen
(table
[i
])) &&
710 (strcmp
(function
, table
[i
]) == 0))
718 * Compare the output from the slave against the given file and report
722 compare_streams
(char *filename
, bool discard
)
724 char check_file
[PATH_MAX
], drain
[100], ref
, data
;
725 struct pollfd fds
[2];
731 * Don't prepend check path iff check file has an absolute
734 if
(filename
[0] != '/') {
735 if
(strlcpy
(check_file
, check_path
, sizeof
(check_file
))
736 >= sizeof
(check_file
))
737 err
(2, "CHECK_PATH too long");
739 if
(strlcat
(check_file
, "/", sizeof
(check_file
))
740 >= sizeof
(check_file
))
741 err
(2, "Could not append / to check file path");
743 check_file
[0] = '\0';
746 if
(strlcat
(check_file
, filename
, sizeof
(check_file
))
747 >= sizeof
(check_file
))
748 err
(2, "Path to check file path overflowed");
750 if
((check_fd
= open
(check_file
, O_RDONLY
, 0)) < 0)
751 err
(2, "failed to open file %s line %zu of file %s",
752 check_file
, line
, cur_file
);
754 fds
[0].fd
= check_fd
;
755 fds
[0].events
= POLLIN
;
757 fds
[1].events
= POLLIN
;
761 * if we have saved output then only check for data in the
762 * reference file since the slave data may already be drained.
764 if
(saved_output.count
> 0)
768 while
(poll
(fds
, nfd
, 500) == nfd
) {
769 if
(fds
[0].revents
& POLLIN
) {
770 if
((result
= read
(check_fd
, &ref
, 1)) < 1) {
773 "Bad read on file %s", check_file
);
780 if
(saved_output.count
> 0) {
781 data
= saved_output.data
[saved_output.readp
];
782 saved_output.count
--;
783 saved_output.readp
++;
784 /* run out of saved data, switch to file */
785 if
(saved_output.count
== 0)
788 if
(fds
[0].revents
& POLLIN
) {
789 if
(read
(master
, &data
, 1) < 1)
790 err
(2, "Bad read on slave pty");
796 fprintf
(stderr
, "Comparing reference byte 0x%x (%c)"
797 " against slave byte 0x%x (%c)\n",
798 ref
, (ref
>= ' ') ? ref
: '-',
799 data
, (data
>= ' ' )? data
: '-');
803 errx
(2, "%s, %zu: refresh data from slave does "
804 "not match expected from file %s offs %zu "
805 "[reference 0x%x (%c) != slave 0x%x (%c)]",
806 cur_file
, line
, check_file
, offs
,
807 ref
, (ref
>= ' ') ? ref
: '-',
808 data
, (data
>= ' ') ? data
: '-');
815 if
(saved_output.count
> 0)
816 excess
(cur_file
, line
, __func__
, " from slave",
817 &saved_output.data
[saved_output.readp
], saved_output.count
);
819 /* discard any excess saved output if required */
821 saved_output.count
= 0;
822 saved_output.readp
= 0;
825 if
((result
= poll
(&fds
[0], 2, 0)) != 0) {
827 err
(2, "poll of file descriptors failed");
829 if
((fds
[1].revents
& POLLIN
) == POLLIN
) {
830 save_slave_output
(true
);
831 } else if
((fds
[0].revents
& POLLIN
) == POLLIN
) {
833 * handle excess in file if it exists. Poll
834 * says there is data until EOF is read.
835 * Check next read is EOF, if it is not then
836 * the file really has more data than the
837 * slave produced so flag this as a warning.
839 result
= read
(check_fd
, drain
, sizeof
(drain
));
841 err
(1, "read of data file failed");
844 excess
(check_file
, 0, __func__
, "", drain
,
854 * Pass a function call and arguments to the slave and wait for the
855 * results. The variable nresults determines how many returns we expect
856 * back from the slave. These results will be validated against the
857 * expected returns or assigned to variables.
860 do_function_call
(size_t nresults
)
862 #define MAX_RESULTS 4
866 struct pollfd fds
[3];
867 returns_t response
[MAX_RESULTS
], returns_count
;
868 assert
(nresults
<= MAX_RESULTS
);
870 do_input
= check_function_table
(command.function
, input_functions
,
873 write_func_and_args
();
876 * We should get the number of returns back here, grab it before
877 * doing input otherwise it will confuse the input poll
879 read_cmd_pipe
(&returns_count
);
880 if
(returns_count.return_type
!= ret_count
)
881 err
(2, "expected return type of ret_count but received %s",
882 returns_enum_names
[returns_count.return_type
]);
884 perform_delay
(&delay_post_call
); /* let slave catch up */
887 fprintf
(stderr
, "Expect %zu results from slave, slave "
888 "reported %zu\n", nresults
, returns_count.return_len
);
891 if
((no_input
== false
) && (do_input
== 1)) {
893 fprintf
(stderr
, "doing input with inputstr >%s<\n",
897 if
(input_str
== NULL
)
898 errx
(2, "%s, %zu: Call to input function "
899 "but no input defined", cur_file
, line
);
901 fds
[0].fd
= slvpipe
[READ_PIPE
];
902 fds
[0].events
= POLLIN
;
904 fds
[1].events
= POLLOUT
;
906 save_slave_output
(false
);
908 perform_delay
(&delay_spec
);
910 if
(poll
(fds
, 2, 0) < 0)
911 err
(2, "poll failed");
912 if
(fds
[0].revents
& POLLIN
) {
913 warnx
("%s, %zu: Slave function "
914 "returned before end of input string",
918 if
((fds
[1].revents
& POLLOUT
) == 0)
921 fprintf
(stderr
, "Writing char >%c< to slave\n",
924 if
(write
(master
, p
, 1) != 1) {
925 warn
("%s, %zu: Slave function write error",
932 save_slave_output
(false
);
935 fprintf
(stderr
, "Input done.\n");
938 /* done with the input string, free the resources */
944 fds
[0].fd
= slvpipe
[READ_PIPE
];
945 fds
[0].events
= POLLIN
;
947 fds
[1].fd
= slvpipe
[WRITE_PIPE
];
948 fds
[1].events
= POLLOUT
;
951 fds
[2].events
= POLLIN | POLLOUT
;
953 i
= poll
(&fds
[0], 3, 1000);
954 fprintf
(stderr
, "Poll returned %zu\n", i
);
955 for
(i
= 0; i
< 3; i
++) {
956 fprintf
(stderr
, "revents for fd[%zu] = 0x%x\n",
961 /* drain any trailing output */
962 save_slave_output
(false
);
964 for
(i
= 0; i
< returns_count.return_len
; i
++) {
965 read_cmd_pipe
(&response
[i
]);
969 * Check for a slave error in the first return slot, if the
970 * slave errored then we may not have the number of returns we
971 * expect but in this case we should report the slave error
972 * instead of a return count mismatch.
974 if
((returns_count.return_len
> 0) &&
975 (response
[0].return_type
== ret_slave_error
))
976 err
(2, "Slave returned error: %s",
977 (const char *)response
[0].return_value
);
979 if
(returns_count.return_len
!= nresults
)
980 err
(2, "Incorrect number of returns from slave, expected %zu "
981 "but received %zu", nresults
, returns_count.return_len
);
984 for
(i
= 0; i
< nresults
; i
++) {
985 if
((response
[i
].return_type
!= ret_byte
) &&
986 (response
[i
].return_type
!= ret_err
) &&
987 (response
[i
].return_type
!= ret_ok
))
989 "received response >%s< "
991 (const char *)response
[i
].return_value
);
993 fprintf
(stderr
, "received");
995 fprintf
(stderr
, " return_type %s\n",
996 returns_enum_names
[command.returns
[i
].return_type
]);
1000 for
(i
= 0; i
< nresults
; i
++) {
1001 if
(command.returns
[i
].return_type
!= ret_var
) {
1002 validate
(i
, &response
[i
]);
1004 vars
[command.returns
[i
].return_index
].len
=
1005 response
[i
].return_len
;
1006 vars
[command.returns
[i
].return_index
].value
=
1007 response
[i
].return_value
;
1008 vars
[command.returns
[i
].return_index
].type
=
1009 response
[i
].return_type
;
1013 if
(verbose
&& (saved_output.count
> 0))
1014 excess
(cur_file
, line
, __func__
, " from slave",
1015 &saved_output.data
[saved_output.readp
], saved_output.count
);
1017 init_parse_variables
(0);
1021 * Write the function and command arguments to the command pipe.
1024 write_func_and_args
(void)
1029 fprintf
(stderr
, "calling function >%s<\n", command.function
);
1032 write_cmd_pipe
(command.function
);
1033 for
(i
= 0; i
< command.nargs
; i
++) {
1034 if
(command.args
[i
].arg_type
== arg_var
)
1035 write_cmd_pipe_args
(command.args
[i
].arg_type
,
1036 &vars
[command.args
[i
].var_index
]);
1038 write_cmd_pipe_args
(command.args
[i
].arg_type
,
1042 write_cmd_pipe
(NULL
); /* signal end of arguments */
1046 * Initialise the command structure - if initial is non-zero then just set
1047 * everything to sane values otherwise free any memory that was allocated
1048 * when building the structure.
1051 init_parse_variables
(int initial
)
1054 struct pollfd slave_pty
;
1057 free
(command.function
);
1058 for
(i
= 0; i
< command.nrets
; i
++) {
1059 if
(command.returns
[i
].return_type
== ret_number
)
1060 free
(command.returns
[i
].return_value
);
1062 free
(command.returns
);
1064 for
(i
= 0; i
< command.nargs
; i
++) {
1065 if
(command.args
[i
].arg_type
!= arg_var
)
1066 free
(command.args
[i
].arg_string
);
1075 saved_output.allocated
= 0;
1076 saved_output.count
= 0;
1077 saved_output.readp
= 0;
1078 saved_output.data
= NULL
;
1082 command.function
= NULL
;
1084 command.args
= NULL
;
1086 command.returns
= NULL
;
1089 * Check the slave pty for stray output from the slave, at this
1090 * point we should not see any data as it should have been
1091 * consumed by the test functions. If we see data then we have
1092 * either a bug or are not handling an output generating function
1095 slave_pty.fd
= master
;
1096 slave_pty.events
= POLLIN
;
1097 result
= poll
(&slave_pty
, 1, 0);
1100 err
(2, "Poll of slave pty failed");
1101 else if
(result
> 0)
1102 warnx
("%s, %zu: Unexpected data from slave", cur_file
, line
);
1106 * Validate the response against the expected return. The variable
1107 * i is the i into the rets array in command.
1110 validate
(int i
, void *data
)
1113 returns_t
*byte_response
;
1115 byte_response
= data
;
1116 if
((command.returns
[i
].return_type
!= ret_byte
) &&
1117 (command.returns
[i
].return_type
!= ret_err
) &&
1118 (command.returns
[i
].return_type
!= ret_ok
)) {
1119 if
((byte_response
->return_type
== ret_byte
) ||
1120 (byte_response
->return_type
== ret_err
) ||
1121 (byte_response
->return_type
== ret_ok
))
1122 err
(1, "%s: expecting type %s, received type %s"
1123 " at line %zu of file %s", __func__
,
1124 returns_enum_names
[command.returns
[i
].return_type
],
1125 returns_enum_names
[byte_response
->return_type
],
1128 response
= byte_response
->return_value
;
1131 switch
(command.returns
[i
].return_type
) {
1133 validate_type
(ret_err
, byte_response
, 0);
1137 validate_type
(ret_ok
, byte_response
, 0);
1141 validate_return
("NULL", response
, 0);
1145 validate_return
("NULL", response
, 1);
1150 validate_return
(command.returns
[i
].return_value
,
1155 validate_reference
(i
, response
);
1159 validate_byte
(&command.returns
[i
], byte_response
, 0);
1163 err
(1, "Malformed statement at line %zu of file %s",
1170 * Validate the return against the contents of a variable.
1173 validate_reference
(int i
, void *data
)
1176 returns_t
*byte_response
;
1179 varp
= &vars
[command.returns
[i
].return_index
];
1181 byte_response
= data
;
1182 if
(command.returns
[i
].return_type
!= ret_byte
)
1187 "%s: return type of %s, value %s \n", __func__
,
1188 returns_enum_names
[varp
->type
],
1189 (const char *)varp
->value
);
1192 switch
(varp
->type
) {
1195 validate_return
(varp
->value
, response
, 0);
1199 validate_byte
(varp
->value
, byte_response
, 0);
1204 "Invalid return type for reference at line %zu of file %s",
1211 * Validate the return type against the expected type, throw an error
1212 * if they don't match.
1215 validate_type
(returns_enum_t expected
, returns_t
*value
, int check
)
1217 if
(((check
== 0) && (expected
!= value
->return_type
)) ||
1218 ((check
== 1) && (expected
== value
->return_type
)))
1219 err
(1, "Validate expected type %s %s %s line %zu of file %s",
1220 returns_enum_names
[expected
],
1221 (check
== 0)?
"matching" : "not matching",
1222 returns_enum_names
[value
->return_type
], line
, cur_file
);
1225 fprintf
(stderr
, "Validate expected type %s %s %s line %zu"
1227 returns_enum_names
[expected
],
1228 (check
== 0)?
"matching" : "not matching",
1229 returns_enum_names
[value
->return_type
], line
, cur_file
);
1234 * Validate the return value against the expected value, throw an error
1235 * if they don't match.
1238 validate_return
(const char *expected
, const char *value
, int check
)
1240 if
(((check
== 0) && strcmp
(expected
, value
) != 0) ||
1241 ((check
== 1) && strcmp
(expected
, value
) == 0))
1242 errx
(1, "Validate expected %s %s %s line %zu of file %s",
1244 (check
== 0)?
"matching" : "not matching", value
,
1247 fprintf
(stderr
, "Validated expected value %s %s %s "
1248 "at line %zu of file %s\n", expected
,
1249 (check
== 0)?
"matches" : "does not match",
1250 value
, line
, cur_file
);
1255 * Validate the return value against the expected value, throw an error
1256 * if they don't match expectations.
1259 validate_byte
(returns_t
*expected
, returns_t
*value
, int check
)
1265 ch
= value
->return_value
;
1266 fprintf
(stderr
, "checking returned byte stream: ");
1267 for
(i
= 0; i
< value
->return_len
; i
++)
1268 fprintf
(stderr
, "%s0x%x", (i
!= 0)?
", " : "", ch
[i
]);
1269 fprintf
(stderr
, "\n");
1271 fprintf
(stderr
, "%s byte stream: ",
1272 (check
== 0)?
"matches" : "does not match");
1273 ch
= (char *) expected
->return_value
;
1274 for
(i
= 0; i
< expected
->return_len
; i
++)
1275 fprintf
(stderr
, "%s0x%x", (i
!= 0)?
", " : "", ch
[i
]);
1276 fprintf
(stderr
, "\n");
1280 * No chance of a match if lengths differ...
1282 if
((check
== 0) && (expected
->return_len
!= value
->return_len
))
1283 errx
(1, "Byte validation failed, length mismatch, expected %zu,"
1284 "received %zu", expected
->return_len
, value
->return_len
);
1287 * If check is 0 then we want to throw an error IFF the byte streams
1288 * do not match, if check is 1 then throw an error if the byte
1291 if
(((check
== 0) && memcmp
(expected
->return_value
, value
->return_value
,
1292 value
->return_len
) != 0) ||
1293 ((check
== 1) && (expected
->return_len
== value
->return_len
) &&
1294 memcmp
(expected
->return_value
, value
->return_value
,
1295 value
->return_len
) == 0))
1296 errx
(1, "Validate expected %s byte stream at line %zu"
1298 (check
== 0)?
"matching" : "not matching", line
, cur_file
);
1300 fprintf
(stderr
, "Validated expected %s byte stream "
1301 "at line %zu of file %s\n",
1302 (check
== 0)?
"matching" : "not matching",
1308 * Validate the variable at i against the expected value, throw an
1309 * error if they don't match, if check is non-zero then the match is
1313 validate_variable
(int ret
, returns_enum_t type
, const void *value
, int i
,
1319 retval
= &command.returns
[ret
];
1320 varptr
= &vars
[command.returns
[ret
].return_index
];
1322 if
(varptr
->value
== NULL
)
1323 err
(1, "Variable %s has no value assigned to it", varptr
->name
);
1326 if
(varptr
->type
!= type
)
1327 err
(1, "Variable %s is not the expected type", varptr
->name
);
1329 if
(type
!= ret_byte
) {
1330 if
((((check
== 0) && strcmp
(value
, varptr
->value
) != 0))
1331 ||
((check
== 1) && strcmp
(value
, varptr
->value
) == 0))
1332 err
(1, "Variable %s contains %s instead of %s"
1333 " value %s at line %zu of file %s",
1334 varptr
->name
, (const char *)varptr
->value
,
1335 (check
== 0)?
"expected" : "not matching",
1336 (const char *)value
,
1339 fprintf
(stderr
, "Variable %s contains %s value "
1340 "%s at line %zu of file %s\n",
1342 (check
== 0)?
"expected" : "not matching",
1343 (const char *)varptr
->value
, line
, cur_file
);
1346 if
((check
== 0) && (retval
->return_len
!= varptr
->len
))
1347 err
(1, "Byte validation failed, length mismatch");
1350 * If check is 0 then we want to throw an error IFF
1351 * the byte streams do not match, if check is 1 then
1352 * throw an error if the byte streams match.
1354 if
(((check
== 0) && memcmp
(retval
->return_value
, varptr
->value
,
1355 varptr
->len
) != 0) ||
1356 ((check
== 1) && (retval
->return_len
== varptr
->len
) &&
1357 memcmp
(retval
->return_value
, varptr
->value
,
1359 err
(1, "Validate expected %s byte stream at line %zu"
1361 (check
== 0)?
"matching" : "not matching",
1364 fprintf
(stderr
, "Validated expected %s byte stream "
1365 "at line %zu of file %s\n",
1366 (check
== 0)?
"matching" : "not matching",
1373 * Write a string to the command pipe - we feed the number of bytes coming
1374 * down first to allow storage allocation and then follow up with the data.
1375 * If cmd is NULL then feed a -1 down the pipe to say the end of the args.
1378 write_cmd_pipe
(char *cmd
)
1388 arg.arg_type
= arg_static
;
1390 arg.arg_string
= cmd
;
1391 write_cmd_pipe_args
(arg.arg_type
, &arg
);
1396 write_cmd_pipe_args
(args_state_t type
, void *data
)
1407 len
= var_data
->len
;
1408 cmd
= var_data
->value
;
1409 if
(type
== arg_byte
)
1410 send_type
= ret_byte
;
1412 send_type
= ret_string
;
1416 send_type
= ret_null
;
1421 if
((arg_data
->arg_len
== 0) && (arg_data
->arg_string
== NULL
))
1424 len
= arg_data
->arg_len
;
1425 cmd
= arg_data
->arg_string
;
1426 if
(type
== arg_byte
)
1427 send_type
= ret_byte
;
1429 send_type
= ret_string
;
1433 fprintf
(stderr
, "Writing type %s to command pipe\n",
1434 returns_enum_names
[send_type
]);
1437 if
(write
(cmdpipe
[WRITE_PIPE
], &send_type
, sizeof
(int)) < 0)
1438 err
(1, "command pipe write for type failed");
1441 fprintf
(stderr
, "Writing length %d to command pipe\n", len
);
1444 if
(write
(cmdpipe
[WRITE_PIPE
], &len
, sizeof
(int)) < 0)
1445 err
(1, "command pipe write for length failed");
1449 fprintf
(stderr
, "Writing data >%s< to command pipe\n",
1452 if
(write
(cmdpipe
[WRITE_PIPE
], cmd
, len
) < 0)
1453 err
(1, "command pipe write of data failed");
1458 * Read a response from the command pipe, first we will receive the
1459 * length of the response then the actual data.
1462 read_cmd_pipe
(returns_t
*response
)
1465 struct pollfd rfd
[2];
1469 * Check if there is data to read - just in case slave has died, we
1470 * don't want to block on the read and just hang. We also check
1471 * output from the slave because the slave may be blocked waiting
1472 * for a flush on its stdout.
1474 rfd
[0].fd
= slvpipe
[READ_PIPE
];
1475 rfd
[0].events
= POLLIN
;
1477 rfd
[1].events
= POLLIN
;
1480 if
(poll
(rfd
, 2, 4000) == 0)
1481 errx
(2, "%s, %zu: Command pipe read timeout",
1484 if
((rfd
[1].revents
& POLLIN
) == POLLIN
) {
1487 "draining output from slave\n");
1489 save_slave_output
(false
);
1492 while
((rfd
[1].revents
& POLLIN
) == POLLIN
);
1494 if
(read
(slvpipe
[READ_PIPE
], &type
, sizeof
(int)) < 0)
1495 err
(1, "command pipe read for type failed");
1496 response
->return_type
= type
;
1498 if
((type
!= ret_ok
) && (type
!= ret_err
) && (type
!= ret_count
)) {
1499 if
(read
(slvpipe
[READ_PIPE
], &len
, sizeof
(int)) < 0)
1500 err
(1, "command pipe read for length failed");
1501 response
->return_len
= len
;
1505 "Reading %d bytes from command pipe\n", len
);
1508 if
((response
->return_value
= malloc
(len
+ 1)) == NULL
)
1509 err
(1, "Failed to alloc memory for cmd pipe read");
1511 if
(read
(slvpipe
[READ_PIPE
], response
->return_value
, len
) < 0)
1512 err
(1, "command pipe read of data failed");
1514 if
(response
->return_type
!= ret_byte
) {
1515 str
= response
->return_value
;
1519 fprintf
(stderr
, "Read data >%s< from pipe\n",
1520 (const char *)response
->return_value
);
1524 response
->return_value
= NULL
;
1525 if
(type
== ret_count
) {
1526 if
(read
(slvpipe
[READ_PIPE
], &len
, sizeof
(int)) < 0)
1527 err
(1, "command pipe read for number of "
1529 response
->return_len
= len
;
1533 fprintf
(stderr
, "Read type %s from pipe\n",
1534 returns_enum_names
[type
]);
1540 * Check for writes from the slave on the pty, save the output into a
1541 * buffer for later checking if discard is false.
1543 #define MAX_DRAIN 256
1546 save_slave_output
(bool discard
)
1548 char *new_data
, drain
[MAX_DRAIN
];
1556 err
(2, "poll of slave pty failed");
1558 if
((result
= read
(master
, drain
, result
)) < 0) {
1559 if
(errno
== EAGAIN
)
1562 err
(2, "draining slave pty failed");
1568 if
((size_t)result
>
1569 (saved_output.allocated
- saved_output.count
)) {
1570 to_allocate
= 1024 * ((result
/ 1024) + 1);
1572 if
((new_data
= realloc
(saved_output.data
,
1573 saved_output.allocated
+ to_allocate
))
1575 err
(2, "Realloc of saved_output failed");
1576 saved_output.data
= new_data
;
1577 saved_output.allocated
+= to_allocate
;
1581 fprintf
(stderr
, "count = %zu, "
1582 "allocated = %zu\n", saved_output.count
,
1583 saved_output.allocated
);
1584 for
(i
= 0; i
< (size_t)result
; i
++) {
1585 fprintf
(stderr
, "Saving slave output "
1586 "at %zu: 0x%x (%c)\n",
1587 saved_output.count
+ i
, drain
[i
],
1588 (drain
[i
] >= ' ')? drain
[i
] : '-');
1592 memcpy
(&saved_output.data
[saved_output.count
], drain
,
1594 saved_output.count
+= result
;
1597 fprintf
(stderr
, "count = %zu, "
1598 "allocated = %zu\n", saved_output.count
,
1599 saved_output.allocated
);
1603 for
(i
= 0; i
< (size_t)result
; i
++) {
1604 fprintf
(stderr
, "Discarding slave "
1605 "output 0x%x (%c)\n",
1607 (drain
[i
] >= ' ')? drain
[i
] : '-');
1615 yyerror(const char *msg
)
1617 warnx
("%s in line %zu of file %s", msg
, line
, cur_file
);