6 #include <sys/socket.h>
7 #include <netinet/in.h>
12 static FILE *Tinputfile
, *Treportfile
;
14 extern void Tshutdown(void) {
15 adns__vbuf_free(&vb2
);
17 static void Tensurereportfile(void) {
20 if (Treportfile
) return;
22 fdstr
= getenv("ADNS_TEST_REPORT_FD"); if (!fdstr
) return;
24 Treportfile
= fdopen(fd
,"a"); if (!Treportfile
) Tfailed("fdopen ADNS_TEST_REPORT_FD");
26 static void Psyntax(const char *where
) {
27 fprintf(stderr
,"adns test harness: syntax error in test log input file: %s\n",where
);
30 static void Pcheckinput(void) {
31 if (ferror(Tinputfile
)) Tfailed("read test log input file");
32 if (feof(Tinputfile
)) Psyntax("eof at syscall reply");
34 static void Tensureinputfile(void) {
38 unsigned long sec
, usec
;
39 if (Tinputfile
) return;
41 fdstr
= getenv("ADNS_TEST_IN_FD");
44 Tinputfile
= fdopen(fd
,"r"); if (!Tinputfile
) Tfailed("fdopen ADNS_TEST_IN_FD");
46 setvbuf(Tinputfile
,0,_IONBF
,0);
47 if (!adns__vbuf_ensure(&vb2
,1000)) Tnomem();
48 fgets(vb2
.buf
,vb2
.avail
,Tinputfile
); Pcheckinput();
50 sscanf(vb2
.buf
," start %lu.%lu%n",&sec
,&usec
,&chars
);
51 if (chars
==-1) Psyntax("start time invalid");
52 currenttime
.tv_sec
= sec
;
53 currenttime
.tv_usec
= usec
;
54 if (vb2
.buf
[chars
] != '\n') Psyntax("not newline after start time");
56 static void Parg(const char *argname
) {
58 if (vb2
.buf
[vb2
.used
++] != ' ') Psyntax("not a space before argument");
60 if (memcmp(vb2
.buf
+vb2
.used
,argname
,l
)) Psyntax("argument name wrong");
62 if (vb2
.buf
[vb2
.used
++] != '=') Psyntax("not = after argument name");
64 static int Pstring_maybe(const char *string
) {
67 if (memcmp(vb2
.buf
+vb2
.used
,string
,l
)) return 0;
71 static void Pstring(const char *string
, const char *emsg
) {
72 if (Pstring_maybe(string
)) return;
75 static int Perrno(const char *stuff
) {
76 const struct Terrno
*te
;
79 for (te
= Terrnos
; te
->n
&& strcmp(te
->n
,stuff
); te
++);
80 if (te
->n
) return te
->v
;
81 r
= strtoul(stuff
+2,&ep
,10);
82 if (*ep
) Psyntax("errno value not recognised, not numeric");
85 static void P_updatetime(void) {
87 unsigned long sec
, usec
;
88 if (!adns__vbuf_ensure(&vb2
,1000)) Tnomem();
89 fgets(vb2
.buf
,vb2
.avail
,Tinputfile
); Pcheckinput();
91 sscanf(vb2
.buf
," +%lu.%lu%n",&sec
,&usec
,&chars
);
92 if (chars
==-1) Psyntax("update time invalid");
93 currenttime
.tv_sec
+= sec
;
94 currenttime
.tv_usec
+= usec
;
95 if (currenttime
.tv_usec
> 1000000) {
97 currenttime
.tv_usec
-= 1000000;
99 if (vb2
.buf
[chars
] != '\n') Psyntax("not newline after update time");
101 static void Pfdset(fd_set
*set
, int max
) {
104 if (vb2
.buf
[vb2
.used
++] != '[') Psyntax("fd set start not [");
106 if (vb2
.buf
[vb2
.used
] == ']') { vb2
.used
++; return; }
108 r
= strtoul(vb2
.buf
+vb2
.used
,&ep
,10);
109 if (r
>=max
) Psyntax("fd set member > max");
110 if (ep
== (char*)vb2
.buf
+vb2
.used
) Psyntax("empty entry in fd set");
112 vb2
.used
= ep
- (char*)vb2
.buf
;
113 c
= vb2
.buf
[vb2
.used
++];
115 if (c
!= ',') Psyntax("fd set separator not ,");
119 static int Ppollfdevents(void) {
121 if (Pstring_maybe("0")) return 0;
123 if (Pstring_maybe("POLLIN")) {
125 if (!Pstring_maybe("|")) return events
;
127 if (Pstring_maybe("POLLOUT")) {
129 if (!Pstring_maybe("|")) return events
;
131 Pstring("POLLPRI","pollfdevents PRI?");
134 static void Ppollfds(struct pollfd
*fds
, int nfds
) {
137 const char *comma
= "";
138 if (vb2
.buf
[vb2
.used
++] != '[') Psyntax("pollfds start not [");
139 for (i
=0; i
<nfds
; i
++) {
140 Pstring("{fd=","{fd= in pollfds");
141 fds
->fd
= strtoul(vb2
.buf
+vb2
.used
,&ep
,10);
142 vb2
.used
= ep
- (char*)vb2
.buf
;
143 Pstring(", events=",", events= in pollfds");
144 fds
->events
= Ppollfdevents();
145 Pstring(", revents=",", revents= in pollfds");
146 fds
->revents
= Ppollfdevents();
147 Pstring("}","} in pollfds");
148 Pstring(comma
,"separator in pollfds");
151 if (vb2
.buf
[vb2
.used
++] != ']') Psyntax("pollfds end not ]");
154 static void Paddr(struct sockaddr
*addr
, int *lenr
) {
155 struct sockaddr_in
*sa
= (struct sockaddr_in
*)addr
;
158 assert(*lenr
>= sizeof(*sa
));
159 p
= strchr(vb2
.buf
+vb2
.used
,':');
160 if (!p
) Psyntax("no port on address");
162 memset(sa
,0,sizeof(*sa
));
163 sa
->sin_family
= AF_INET
;
164 if (!inet_aton(vb2
.buf
+vb2
.used
,&sa
->sin_addr
)) Psyntax("invalid address");
165 ul
= strtoul(p
,&ep
,10);
166 if (*ep
&& *ep
!= ' ') Psyntax("invalid port (bad syntax)");
167 if (ul
>= 65536) Psyntax("port too large");
168 sa
->sin_port
= htons(ul
);
170 vb2
.used
= ep
- (char*)vb2
.buf
;
172 static int Pbytes(byte
*buf
, int maxlen
) {
173 static const char hexdigits
[]= "0123456789abcdef";
178 c
= getc(Tinputfile
); Pcheckinput();
179 if (c
=='\n' || c
==' ' || c
=='\t') continue;
181 pf
= strchr(hexdigits
,c
); if (!pf
) Psyntax("invalid first hex digit");
182 v
= (pf
-hexdigits
)<<4;
183 c
= getc(Tinputfile
); Pcheckinput();
184 pf
= strchr(hexdigits
,c
); if (!pf
) Psyntax("invalid second hex digit");
186 if (maxlen
<=0) Psyntax("buffer overflow in bytes");
191 c
= getc(Tinputfile
); Pcheckinput();
192 if (c
=='\n') return done
;
199 if (!adns__vbuf_ensure(&vb2
,vb
.used
+2)) Tnomem();
200 r
= fread(vb2
.buf
,1,vb
.used
+2,Tinputfile
);
201 if (feof(Tinputfile
)) {
202 fprintf(stderr
,"adns test harness: input ends prematurely; program did:\n %.*s\n",
207 if (vb2
.buf
[0] != ' ') Psyntax("not space before call");
208 if (memcmp(vb
.buf
,vb2
.buf
+1,vb
.used
) ||
209 vb2
.buf
[vb
.used
+1] != '\n') {
211 "adns test harness: program did unexpected:\n %.*s\n"
212 "was expecting:\n %.*s\n",
213 vb
.used
,vb
.buf
, vb
.used
,vb2
.buf
+1);
217 nl
= memchr(vb
.buf
,'\n',vb
.used
);
218 fprintf(Treportfile
," %.*s\n", (int)(nl ? nl
- (const char*)vb
.buf
: vb
.used
), vb
.buf
);
220 int Hselect( int max
, fd_set
*rfds
, fd_set
*wfds
, fd_set
*efds
, struct timeval
*to
) {
223 Qselect( max
, rfds
, wfds
, efds
, to
);
224 if (!adns__vbuf_ensure(&vb2
,1000)) Tnomem();
225 fgets(vb2
.buf
,vb2
.avail
,Tinputfile
); Pcheckinput();
227 fprintf(Treportfile
,"%s",vb2
.buf
);
228 amtread
= strlen(vb2
.buf
);
229 if (amtread
<=0 || vb2
.buf
[--amtread
]!='\n')
230 Psyntax("badly formed line");
232 if (memcmp(vb2
.buf
," select=",8)) Psyntax("syscall reply mismatch");
233 if (vb2
.buf
[8] == 'E') {
235 e
= Perrno(vb2
.buf
+8);
240 r
= strtoul(vb2
.buf
+8,&ep
,10);
241 if (*ep
&& *ep
!=' ') Psyntax("return value not E* or positive number");
242 vb2
.used
= ep
- (char*)vb2
.buf
;
243 Parg("rfds"); Pfdset(rfds
,max
);
244 Parg("wfds"); Pfdset(wfds
,max
);
245 Parg("efds"); Pfdset(efds
,max
);
246 assert(vb2
.used
<= amtread
);
247 if (vb2
.used
!= amtread
) Psyntax("junk at end of line");
252 int Hpoll( struct pollfd
*fds
, int nfds
, int timeout
) {
255 Qpoll( fds
, nfds
, timeout
);
256 if (!adns__vbuf_ensure(&vb2
,1000)) Tnomem();
257 fgets(vb2
.buf
,vb2
.avail
,Tinputfile
); Pcheckinput();
259 fprintf(Treportfile
,"%s",vb2
.buf
);
260 amtread
= strlen(vb2
.buf
);
261 if (amtread
<=0 || vb2
.buf
[--amtread
]!='\n')
262 Psyntax("badly formed line");
264 if (memcmp(vb2
.buf
," poll=",6)) Psyntax("syscall reply mismatch");
265 if (vb2
.buf
[6] == 'E') {
267 e
= Perrno(vb2
.buf
+6);
272 r
= strtoul(vb2
.buf
+6,&ep
,10);
273 if (*ep
&& *ep
!=' ') Psyntax("return value not E* or positive number");
274 vb2
.used
= ep
- (char*)vb2
.buf
;
275 Parg("fds"); Ppollfds(fds
,nfds
);
276 assert(vb2
.used
<= amtread
);
277 if (vb2
.used
!= amtread
) Psyntax("junk at end of line");
282 int Hsocket( int domain
, int type
, int protocol
) {
285 Tmust("socket","domain",domain
==AF_INET
);
286 Tmust("socket","type",type
==SOCK_STREAM
|| type
==SOCK_DGRAM
);
288 if (!adns__vbuf_ensure(&vb2
,1000)) Tnomem();
289 fgets(vb2
.buf
,vb2
.avail
,Tinputfile
); Pcheckinput();
291 fprintf(Treportfile
,"%s",vb2
.buf
);
292 amtread
= strlen(vb2
.buf
);
293 if (amtread
<=0 || vb2
.buf
[--amtread
]!='\n')
294 Psyntax("badly formed line");
296 if (memcmp(vb2
.buf
," socket=",8)) Psyntax("syscall reply mismatch");
297 if (vb2
.buf
[8] == 'E') {
299 e
= Perrno(vb2
.buf
+8);
304 r
= strtoul(vb2
.buf
+8,&ep
,10);
305 if (*ep
&& *ep
!=' ') Psyntax("return value not E* or positive number");
306 vb2
.used
= ep
- (char*)vb2
.buf
;
307 assert(vb2
.used
<= amtread
);
308 if (vb2
.used
!= amtread
) Psyntax("junk at end of line");
312 int Hfcntl( int fd
, int cmd
, ... ) {
314 va_list al
; long arg
;
315 Tmust("fcntl","cmd",cmd
==F_SETFL
|| cmd
==F_GETFL
);
316 if (cmd
== F_SETFL
) {
317 va_start(al
,cmd
); arg
= va_arg(al
,long); va_end(al
);
321 Qfcntl( fd
, cmd
, arg
);
322 if (!adns__vbuf_ensure(&vb2
,1000)) Tnomem();
323 fgets(vb2
.buf
,vb2
.avail
,Tinputfile
); Pcheckinput();
325 fprintf(Treportfile
,"%s",vb2
.buf
);
326 amtread
= strlen(vb2
.buf
);
327 if (amtread
<=0 || vb2
.buf
[--amtread
]!='\n')
328 Psyntax("badly formed line");
330 if (memcmp(vb2
.buf
," fcntl=",7)) Psyntax("syscall reply mismatch");
331 if (vb2
.buf
[7] == 'E') {
333 e
= Perrno(vb2
.buf
+7);
339 if (cmd
== F_GETFL
) {
340 if (!memcmp(vb2
.buf
+7,"O_NONBLOCK|...",14)) {
343 } else if (!memcmp(vb2
.buf
+7,"~O_NONBLOCK&...",15)) {
346 Psyntax("fcntl flags not O_NONBLOCK|... or ~O_NONBLOCK&...");
348 } else if (cmd
== F_SETFL
) {
349 if (memcmp(vb2
.buf
+7,"OK",2)) Psyntax("success/fail not E* or OK");
353 Psyntax("fcntl not F_GETFL or F_SETFL");
355 assert(vb2
.used
<= amtread
);
356 if (vb2
.used
!= amtread
) Psyntax("junk at end of line");
360 int Hconnect( int fd
, const struct sockaddr
*addr
, int addrlen
) {
362 Qconnect( fd
, addr
, addrlen
);
363 if (!adns__vbuf_ensure(&vb2
,1000)) Tnomem();
364 fgets(vb2
.buf
,vb2
.avail
,Tinputfile
); Pcheckinput();
366 fprintf(Treportfile
,"%s",vb2
.buf
);
367 amtread
= strlen(vb2
.buf
);
368 if (amtread
<=0 || vb2
.buf
[--amtread
]!='\n')
369 Psyntax("badly formed line");
371 if (memcmp(vb2
.buf
," connect=",9)) Psyntax("syscall reply mismatch");
372 if (vb2
.buf
[9] == 'E') {
374 e
= Perrno(vb2
.buf
+9);
379 if (memcmp(vb2
.buf
+9,"OK",2)) Psyntax("success/fail not E* or OK");
382 assert(vb2
.used
<= amtread
);
383 if (vb2
.used
!= amtread
) Psyntax("junk at end of line");
387 int Hclose( int fd
) {
390 if (!adns__vbuf_ensure(&vb2
,1000)) Tnomem();
391 fgets(vb2
.buf
,vb2
.avail
,Tinputfile
); Pcheckinput();
393 fprintf(Treportfile
,"%s",vb2
.buf
);
394 amtread
= strlen(vb2
.buf
);
395 if (amtread
<=0 || vb2
.buf
[--amtread
]!='\n')
396 Psyntax("badly formed line");
398 if (memcmp(vb2
.buf
," close=",7)) Psyntax("syscall reply mismatch");
399 if (vb2
.buf
[7] == 'E') {
401 e
= Perrno(vb2
.buf
+7);
406 if (memcmp(vb2
.buf
+7,"OK",2)) Psyntax("success/fail not E* or OK");
409 assert(vb2
.used
<= amtread
);
410 if (vb2
.used
!= amtread
) Psyntax("junk at end of line");
414 int Hsendto( int fd
, const void *msg
, int msglen
, unsigned int flags
, const struct sockaddr
*addr
, int addrlen
) {
417 Tmust("sendto","flags",flags
==0);
418 Qsendto( fd
, msg
, msglen
, addr
, addrlen
);
419 if (!adns__vbuf_ensure(&vb2
,1000)) Tnomem();
420 fgets(vb2
.buf
,vb2
.avail
,Tinputfile
); Pcheckinput();
422 fprintf(Treportfile
,"%s",vb2
.buf
);
423 amtread
= strlen(vb2
.buf
);
424 if (amtread
<=0 || vb2
.buf
[--amtread
]!='\n')
425 Psyntax("badly formed line");
427 if (memcmp(vb2
.buf
," sendto=",8)) Psyntax("syscall reply mismatch");
428 if (vb2
.buf
[8] == 'E') {
430 e
= Perrno(vb2
.buf
+8);
435 r
= strtoul(vb2
.buf
+8,&ep
,10);
436 if (*ep
&& *ep
!=' ') Psyntax("return value not E* or positive number");
437 vb2
.used
= ep
- (char*)vb2
.buf
;
438 assert(vb2
.used
<= amtread
);
439 if (vb2
.used
!= amtread
) Psyntax("junk at end of line");
443 int Hrecvfrom( int fd
, void *buf
, int buflen
, unsigned int flags
, struct sockaddr
*addr
, int *addrlen
) {
445 Tmust("recvfrom","flags",flags
==0);
446 Tmust("recvfrom","*addrlen",*addrlen
>=sizeof(struct sockaddr_in
));
447 Qrecvfrom( fd
, buflen
, *addrlen
);
448 if (!adns__vbuf_ensure(&vb2
,1000)) Tnomem();
449 fgets(vb2
.buf
,vb2
.avail
,Tinputfile
); Pcheckinput();
451 fprintf(Treportfile
,"%s",vb2
.buf
);
452 amtread
= strlen(vb2
.buf
);
453 if (amtread
<=0 || vb2
.buf
[--amtread
]!='\n')
454 Psyntax("badly formed line");
456 if (memcmp(vb2
.buf
," recvfrom=",10)) Psyntax("syscall reply mismatch");
457 if (vb2
.buf
[10] == 'E') {
459 e
= Perrno(vb2
.buf
+10);
464 if (memcmp(vb2
.buf
+10,"OK",2)) Psyntax("success/fail not E* or OK");
467 Parg("addr"); Paddr(addr
,addrlen
);
468 assert(vb2
.used
<= amtread
);
469 if (vb2
.used
!= amtread
) Psyntax("junk at end of line");
470 r
= Pbytes(buf
,buflen
);
474 int Hread( int fd
, void *buf
, size_t buflen
) {
476 Qread( fd
, buflen
);
477 if (!adns__vbuf_ensure(&vb2
,1000)) Tnomem();
478 fgets(vb2
.buf
,vb2
.avail
,Tinputfile
); Pcheckinput();
480 fprintf(Treportfile
,"%s",vb2
.buf
);
481 amtread
= strlen(vb2
.buf
);
482 if (amtread
<=0 || vb2
.buf
[--amtread
]!='\n')
483 Psyntax("badly formed line");
485 if (memcmp(vb2
.buf
," read=",6)) Psyntax("syscall reply mismatch");
486 if (vb2
.buf
[6] == 'E') {
488 e
= Perrno(vb2
.buf
+6);
493 if (memcmp(vb2
.buf
+6,"OK",2)) Psyntax("success/fail not E* or OK");
496 assert(vb2
.used
<= amtread
);
497 if (vb2
.used
!= amtread
) Psyntax("junk at end of line");
498 r
= Pbytes(buf
,buflen
);
502 int Hwrite( int fd
, const void *buf
, size_t len
) {
505 Qwrite( fd
, buf
, len
);
506 if (!adns__vbuf_ensure(&vb2
,1000)) Tnomem();
507 fgets(vb2
.buf
,vb2
.avail
,Tinputfile
); Pcheckinput();
509 fprintf(Treportfile
,"%s",vb2
.buf
);
510 amtread
= strlen(vb2
.buf
);
511 if (amtread
<=0 || vb2
.buf
[--amtread
]!='\n')
512 Psyntax("badly formed line");
514 if (memcmp(vb2
.buf
," write=",7)) Psyntax("syscall reply mismatch");
515 if (vb2
.buf
[7] == 'E') {
517 e
= Perrno(vb2
.buf
+7);
522 r
= strtoul(vb2
.buf
+7,&ep
,10);
523 if (*ep
&& *ep
!=' ') Psyntax("return value not E* or positive number");
524 vb2
.used
= ep
- (char*)vb2
.buf
;
525 assert(vb2
.used
<= amtread
);
526 if (vb2
.used
!= amtread
) Psyntax("junk at end of line");