6 #include <sys/socket.h>
7 #include <netinet/in.h>
13 static FILE *Tinputfile
, *Treportfile
;
15 extern void Tshutdown(void) {
16 adns__vbuf_free(&vb2
);
18 static void Tensurereportfile(void) {
21 if (Treportfile
) return;
23 fdstr
= getenv("ADNS_TEST_REPORT_FD"); if (!fdstr
) return;
25 Treportfile
= fdopen(fd
,"a"); if (!Treportfile
) Tfailed("fdopen ADNS_TEST_REPORT_FD");
27 static void Psyntax(const char *where
) {
28 fprintf(stderr
,"adns test harness: syntax error in test log input file: %s\n",where
);
31 static void Pcheckinput(void) {
32 if (ferror(Tinputfile
)) Tfailed("read test log input file");
33 if (feof(Tinputfile
)) Psyntax("eof at syscall reply");
35 void Tensurerecordfile(void) {
39 unsigned long sec
, usec
;
40 if (Tinputfile
) return;
42 fdstr
= getenv("ADNS_TEST_IN_FD");
45 Tinputfile
= fdopen(fd
,"r"); if (!Tinputfile
) Tfailed("fdopen ADNS_TEST_IN_FD");
47 setvbuf(Tinputfile
,0,_IONBF
,0);
48 if (!adns__vbuf_ensure(&vb2
,1000)) Tnomem();
49 fgets(vb2
.buf
,vb2
.avail
,Tinputfile
); Pcheckinput();
51 sscanf(vb2
.buf
," start %lu.%lu%n",&sec
,&usec
,&chars
);
52 if (chars
==-1) Psyntax("start time invalid");
53 currenttime
.tv_sec
= sec
;
54 currenttime
.tv_usec
= usec
;
55 if (vb2
.buf
[chars
] != '\n') Psyntax("not newline after start time");
57 static void Parg(const char *argname
) {
59 if (vb2
.buf
[vb2
.used
++] != ' ') Psyntax("not a space before argument");
61 if (memcmp(vb2
.buf
+vb2
.used
,argname
,l
)) Psyntax("argument name wrong");
63 if (vb2
.buf
[vb2
.used
++] != '=') Psyntax("not = after argument name");
65 static int Pstring_maybe(const char *string
) {
68 if (memcmp(vb2
.buf
+vb2
.used
,string
,l
)) return 0;
72 static void Pstring(const char *string
, const char *emsg
) {
73 if (Pstring_maybe(string
)) return;
76 static int Perrno(const char *stuff
) {
77 const struct Terrno
*te
;
80 for (te
= Terrnos
; te
->n
&& strcmp(te
->n
,stuff
); te
++);
81 if (te
->n
) return te
->v
;
82 r
= strtoul(stuff
+2,&ep
,10);
83 if (*ep
) Psyntax("errno value not recognised, not numeric");
86 static void P_updatetime(void) {
88 unsigned long sec
, usec
;
89 if (!adns__vbuf_ensure(&vb2
,1000)) Tnomem();
90 fgets(vb2
.buf
,vb2
.avail
,Tinputfile
); Pcheckinput();
92 sscanf(vb2
.buf
," +%lu.%lu%n",&sec
,&usec
,&chars
);
93 if (chars
==-1) Psyntax("update time invalid");
94 currenttime
.tv_sec
+= sec
;
95 currenttime
.tv_usec
+= usec
;
96 if (currenttime
.tv_usec
> 1000000) {
98 currenttime
.tv_usec
-= 1000000;
100 if (vb2
.buf
[chars
] != '\n') Psyntax("not newline after update time");
102 static void Pfdset(fd_set
*set
, int max
) {
106 Pstring("null","null fdset pointer");
109 if (vb2
.buf
[vb2
.used
++] != '[') Psyntax("fd set start not [");
111 if (vb2
.buf
[vb2
.used
] == ']') { vb2
.used
++; return; }
113 r
= strtoul(vb2
.buf
+vb2
.used
,&ep
,10);
114 if (r
>=max
) Psyntax("fd set member > max");
115 if (ep
== (char*)vb2
.buf
+vb2
.used
) Psyntax("empty entry in fd set");
117 vb2
.used
= ep
- (char*)vb2
.buf
;
118 c
= vb2
.buf
[vb2
.used
++];
120 if (c
!= ',') Psyntax("fd set separator not ,");
124 static int Ppollfdevents(void) {
126 if (Pstring_maybe("0")) return 0;
128 if (Pstring_maybe("POLLIN")) {
130 if (!Pstring_maybe("|")) return events
;
132 if (Pstring_maybe("POLLOUT")) {
134 if (!Pstring_maybe("|")) return events
;
136 Pstring("POLLPRI","pollfdevents PRI?");
139 static void Ppollfds(struct pollfd
*fds
, int nfds
) {
142 const char *comma
= "";
143 if (vb2
.buf
[vb2
.used
++] != '[') Psyntax("pollfds start not [");
144 for (i
=0; i
<nfds
; i
++) {
145 Pstring("{fd=","{fd= in pollfds");
146 fds
->fd
= strtoul(vb2
.buf
+vb2
.used
,&ep
,10);
147 vb2
.used
= ep
- (char*)vb2
.buf
;
148 Pstring(", events=",", events= in pollfds");
149 fds
->events
= Ppollfdevents();
150 Pstring(", revents=",", revents= in pollfds");
151 fds
->revents
= Ppollfdevents();
152 Pstring("}","} in pollfds");
153 Pstring(comma
,"separator in pollfds");
156 if (vb2
.buf
[vb2
.used
++] != ']') Psyntax("pollfds end not ]");
159 static void Paddr(struct sockaddr
*addr
, int *lenr
) {
167 if (!q
) Psyntax("missing :");
172 if (!q
) Psyntax("missing ]");
174 if (*q
!=':') Psyntax("expected : after ]");
177 ul
= strtoul(q
,&ep
,10);
178 if (*ep
&& *ep
!= ' ') Psyntax("invalid port (bad syntax)");
179 if (ul
>= 65536) Psyntax("port too large");
180 a
.len
= sizeof(a
.addr
);
181 err
= adns_text2addr(p
, (int)ul
, 0, &a
.addr
.sa
,&a
.len
);
182 if (err
) Psyntax("invalid address");
183 assert(*lenr
>= a
.len
);
184 memcpy(addr
, &a
.addr
, a
.len
);
186 vb2
.used
= ep
- (char*)vb2
.buf
;
188 static int Pbytes(byte
*buf
, int maxlen
) {
189 static const char hexdigits
[]= "0123456789abcdef";
194 c
= getc(Tinputfile
); Pcheckinput();
195 if (c
=='\n' || c
==' ' || c
=='\t') continue;
197 pf
= strchr(hexdigits
,c
); if (!pf
) Psyntax("invalid first hex digit");
198 v
= (pf
-hexdigits
)<<4;
199 c
= getc(Tinputfile
); Pcheckinput();
200 pf
= strchr(hexdigits
,c
); if (!pf
) Psyntax("invalid second hex digit");
202 if (maxlen
<=0) Psyntax("buffer overflow in bytes");
207 c
= getc(Tinputfile
); Pcheckinput();
208 if (c
=='\n') return done
;
214 if (!adns__vbuf_ensure(&vb2
,vb
.used
+2)) Tnomem();
215 fread(vb2
.buf
,1,vb
.used
+2,Tinputfile
);
216 if (feof(Tinputfile
)) {
217 fprintf(stderr
,"adns test harness: input ends prematurely; program did:\n %.*s\n",
222 if (vb2
.buf
[0] != ' ') Psyntax("not space before call");
223 if (memcmp(vb
.buf
,vb2
.buf
+1,vb
.used
) ||
224 vb2
.buf
[vb
.used
+1] != '\n') {
226 "adns test harness: program did unexpected:\n %.*s\n"
227 "was expecting:\n %.*s\n",
228 vb
.used
,vb
.buf
, vb
.used
,vb2
.buf
+1);
232 nl
= memchr(vb
.buf
,'\n',vb
.used
);
233 fprintf(Treportfile
," %.*s\n", (int)(nl ? nl
- (const char*)vb
.buf
: vb
.used
), vb
.buf
);
235 int Hselect( int max
, fd_set
*rfds
, fd_set
*wfds
, fd_set
*efds
, struct timeval
*to
) {
238 Qselect( max
, rfds
, wfds
, efds
, to
);
239 if (!adns__vbuf_ensure(&vb2
,1000)) Tnomem();
240 fgets(vb2
.buf
,vb2
.avail
,Tinputfile
); Pcheckinput();
242 fprintf(Treportfile
,"%s",vb2
.buf
);
243 amtread
= strlen(vb2
.buf
);
244 if (amtread
<=0 || vb2
.buf
[--amtread
]!='\n')
245 Psyntax("badly formed line");
247 if (memcmp(vb2
.buf
," select=",8)) Psyntax("syscall reply mismatch");
248 if (vb2
.buf
[8] == 'E') {
250 e
= Perrno(vb2
.buf
+8);
255 r
= strtoul(vb2
.buf
+8,&ep
,10);
256 if (*ep
&& *ep
!=' ') Psyntax("return value not E* or positive number");
257 vb2
.used
= ep
- (char*)vb2
.buf
;
258 Parg("rfds"); Pfdset(rfds
,max
);
259 Parg("wfds"); Pfdset(wfds
,max
);
260 Parg("efds"); Pfdset(efds
,max
);
261 assert(vb2
.used
<= amtread
);
262 if (vb2
.used
!= amtread
) Psyntax("junk at end of line");
267 int Hpoll( struct pollfd
*fds
, int nfds
, int timeout
) {
270 Qpoll( fds
, nfds
, timeout
);
271 if (!adns__vbuf_ensure(&vb2
,1000)) Tnomem();
272 fgets(vb2
.buf
,vb2
.avail
,Tinputfile
); Pcheckinput();
274 fprintf(Treportfile
,"%s",vb2
.buf
);
275 amtread
= strlen(vb2
.buf
);
276 if (amtread
<=0 || vb2
.buf
[--amtread
]!='\n')
277 Psyntax("badly formed line");
279 if (memcmp(vb2
.buf
," poll=",6)) Psyntax("syscall reply mismatch");
280 if (vb2
.buf
[6] == 'E') {
282 e
= Perrno(vb2
.buf
+6);
287 r
= strtoul(vb2
.buf
+6,&ep
,10);
288 if (*ep
&& *ep
!=' ') Psyntax("return value not E* or positive number");
289 vb2
.used
= ep
- (char*)vb2
.buf
;
290 Parg("fds"); Ppollfds(fds
,nfds
);
291 assert(vb2
.used
<= amtread
);
292 if (vb2
.used
!= amtread
) Psyntax("junk at end of line");
297 int Hsocket( int domain
, int type
, int protocol
) {
300 Tmust("socket","domain",domain
==AF_INET
|| domain
==AF_INET6
);
301 Tmust("socket","type",type
==SOCK_STREAM
|| type
==SOCK_DGRAM
);
302 Qsocket( domain
, type
);
303 if (!adns__vbuf_ensure(&vb2
,1000)) Tnomem();
304 fgets(vb2
.buf
,vb2
.avail
,Tinputfile
); Pcheckinput();
306 fprintf(Treportfile
,"%s",vb2
.buf
);
307 amtread
= strlen(vb2
.buf
);
308 if (amtread
<=0 || vb2
.buf
[--amtread
]!='\n')
309 Psyntax("badly formed line");
311 if (memcmp(vb2
.buf
," socket=",8)) Psyntax("syscall reply mismatch");
312 if (vb2
.buf
[8] == 'E') {
314 e
= Perrno(vb2
.buf
+8);
319 r
= strtoul(vb2
.buf
+8,&ep
,10);
320 if (*ep
&& *ep
!=' ') Psyntax("return value not E* or positive number");
321 vb2
.used
= ep
- (char*)vb2
.buf
;
322 assert(vb2
.used
<= amtread
);
323 if (vb2
.used
!= amtread
) Psyntax("junk at end of line");
327 int Hfcntl( int fd
, int cmd
, ... ) {
329 va_list al
; long arg
;
330 Tmust("fcntl","cmd",cmd
==F_SETFL
|| cmd
==F_GETFL
);
331 if (cmd
== F_SETFL
) {
332 va_start(al
,cmd
); arg
= va_arg(al
,long); va_end(al
);
336 Qfcntl( fd
, cmd
, arg
);
337 if (!adns__vbuf_ensure(&vb2
,1000)) Tnomem();
338 fgets(vb2
.buf
,vb2
.avail
,Tinputfile
); Pcheckinput();
340 fprintf(Treportfile
,"%s",vb2
.buf
);
341 amtread
= strlen(vb2
.buf
);
342 if (amtread
<=0 || vb2
.buf
[--amtread
]!='\n')
343 Psyntax("badly formed line");
345 if (memcmp(vb2
.buf
," fcntl=",7)) Psyntax("syscall reply mismatch");
346 if (vb2
.buf
[7] == 'E') {
348 e
= Perrno(vb2
.buf
+7);
354 if (cmd
== F_GETFL
) {
355 if (!memcmp(vb2
.buf
+7,"O_NONBLOCK|...",14)) {
358 } else if (!memcmp(vb2
.buf
+7,"~O_NONBLOCK&...",15)) {
361 Psyntax("fcntl flags not O_NONBLOCK|... or ~O_NONBLOCK&...");
363 } else if (cmd
== F_SETFL
) {
364 if (memcmp(vb2
.buf
+7,"OK",2)) Psyntax("success/fail not E* or OK");
368 Psyntax("fcntl not F_GETFL or F_SETFL");
370 assert(vb2
.used
<= amtread
);
371 if (vb2
.used
!= amtread
) Psyntax("junk at end of line");
375 int Hconnect( int fd
, const struct sockaddr
*addr
, int addrlen
) {
377 Qconnect( fd
, addr
, addrlen
);
378 if (!adns__vbuf_ensure(&vb2
,1000)) Tnomem();
379 fgets(vb2
.buf
,vb2
.avail
,Tinputfile
); Pcheckinput();
381 fprintf(Treportfile
,"%s",vb2
.buf
);
382 amtread
= strlen(vb2
.buf
);
383 if (amtread
<=0 || vb2
.buf
[--amtread
]!='\n')
384 Psyntax("badly formed line");
386 if (memcmp(vb2
.buf
," connect=",9)) Psyntax("syscall reply mismatch");
387 if (vb2
.buf
[9] == 'E') {
389 e
= Perrno(vb2
.buf
+9);
394 if (memcmp(vb2
.buf
+9,"OK",2)) Psyntax("success/fail not E* or OK");
397 assert(vb2
.used
<= amtread
);
398 if (vb2
.used
!= amtread
) Psyntax("junk at end of line");
402 int Hbind( int fd
, const struct sockaddr
*addr
, int addrlen
) {
404 Qbind( fd
, addr
, addrlen
);
405 if (!adns__vbuf_ensure(&vb2
,1000)) Tnomem();
406 fgets(vb2
.buf
,vb2
.avail
,Tinputfile
); Pcheckinput();
408 fprintf(Treportfile
,"%s",vb2
.buf
);
409 amtread
= strlen(vb2
.buf
);
410 if (amtread
<=0 || vb2
.buf
[--amtread
]!='\n')
411 Psyntax("badly formed line");
413 if (memcmp(vb2
.buf
," bind=",6)) Psyntax("syscall reply mismatch");
414 if (vb2
.buf
[6] == 'E') {
416 e
= Perrno(vb2
.buf
+6);
421 if (memcmp(vb2
.buf
+6,"OK",2)) Psyntax("success/fail not E* or OK");
424 assert(vb2
.used
<= amtread
);
425 if (vb2
.used
!= amtread
) Psyntax("junk at end of line");
429 int Hlisten( int fd
, int backlog
) {
431 Qlisten( fd
, backlog
);
432 if (!adns__vbuf_ensure(&vb2
,1000)) Tnomem();
433 fgets(vb2
.buf
,vb2
.avail
,Tinputfile
); Pcheckinput();
435 fprintf(Treportfile
,"%s",vb2
.buf
);
436 amtread
= strlen(vb2
.buf
);
437 if (amtread
<=0 || vb2
.buf
[--amtread
]!='\n')
438 Psyntax("badly formed line");
440 if (memcmp(vb2
.buf
," listen=",8)) Psyntax("syscall reply mismatch");
441 if (vb2
.buf
[8] == 'E') {
443 e
= Perrno(vb2
.buf
+8);
448 if (memcmp(vb2
.buf
+8,"OK",2)) Psyntax("success/fail not E* or OK");
451 assert(vb2
.used
<= amtread
);
452 if (vb2
.used
!= amtread
) Psyntax("junk at end of line");
456 int Hclose( int fd
) {
459 if (!adns__vbuf_ensure(&vb2
,1000)) Tnomem();
460 fgets(vb2
.buf
,vb2
.avail
,Tinputfile
); Pcheckinput();
462 fprintf(Treportfile
,"%s",vb2
.buf
);
463 amtread
= strlen(vb2
.buf
);
464 if (amtread
<=0 || vb2
.buf
[--amtread
]!='\n')
465 Psyntax("badly formed line");
467 if (memcmp(vb2
.buf
," close=",7)) Psyntax("syscall reply mismatch");
468 if (vb2
.buf
[7] == 'E') {
470 e
= Perrno(vb2
.buf
+7);
475 if (memcmp(vb2
.buf
+7,"OK",2)) Psyntax("success/fail not E* or OK");
478 assert(vb2
.used
<= amtread
);
479 if (vb2
.used
!= amtread
) Psyntax("junk at end of line");
483 int Hsendto( int fd
, const void *msg
, int msglen
, unsigned int flags
, const struct sockaddr
*addr
, int addrlen
) {
486 Tmust("sendto","flags",flags
==0);
487 Qsendto( fd
, msg
, msglen
, addr
, addrlen
);
488 if (!adns__vbuf_ensure(&vb2
,1000)) Tnomem();
489 fgets(vb2
.buf
,vb2
.avail
,Tinputfile
); Pcheckinput();
491 fprintf(Treportfile
,"%s",vb2
.buf
);
492 amtread
= strlen(vb2
.buf
);
493 if (amtread
<=0 || vb2
.buf
[--amtread
]!='\n')
494 Psyntax("badly formed line");
496 if (memcmp(vb2
.buf
," sendto=",8)) Psyntax("syscall reply mismatch");
497 if (vb2
.buf
[8] == 'E') {
499 e
= Perrno(vb2
.buf
+8);
504 r
= strtoul(vb2
.buf
+8,&ep
,10);
505 if (*ep
&& *ep
!=' ') Psyntax("return value not E* or positive number");
506 vb2
.used
= ep
- (char*)vb2
.buf
;
507 assert(vb2
.used
<= amtread
);
508 if (vb2
.used
!= amtread
) Psyntax("junk at end of line");
512 int Hrecvfrom( int fd
, void *buf
, int buflen
, unsigned int flags
, struct sockaddr
*addr
, int *addrlen
) {
514 Tmust("recvfrom","flags",flags
==0);
515 Tmust("recvfrom","*addrlen",*addrlen
>=sizeof(struct sockaddr_in
));
516 Qrecvfrom( fd
, buflen
, *addrlen
);
517 if (!adns__vbuf_ensure(&vb2
,1000)) Tnomem();
518 fgets(vb2
.buf
,vb2
.avail
,Tinputfile
); Pcheckinput();
520 fprintf(Treportfile
,"%s",vb2
.buf
);
521 amtread
= strlen(vb2
.buf
);
522 if (amtread
<=0 || vb2
.buf
[--amtread
]!='\n')
523 Psyntax("badly formed line");
525 if (memcmp(vb2
.buf
," recvfrom=",10)) Psyntax("syscall reply mismatch");
526 if (vb2
.buf
[10] == 'E') {
528 e
= Perrno(vb2
.buf
+10);
533 if (memcmp(vb2
.buf
+10,"OK",2)) Psyntax("success/fail not E* or OK");
536 Parg("addr"); Paddr(addr
,addrlen
);
537 assert(vb2
.used
<= amtread
);
538 if (vb2
.used
!= amtread
) Psyntax("junk at end of line");
539 r
= Pbytes(buf
,buflen
);
543 int Hread( int fd
, void *buf
, size_t buflen
) {
545 Qread( fd
, buflen
);
546 if (!adns__vbuf_ensure(&vb2
,1000)) Tnomem();
547 fgets(vb2
.buf
,vb2
.avail
,Tinputfile
); Pcheckinput();
549 fprintf(Treportfile
,"%s",vb2
.buf
);
550 amtread
= strlen(vb2
.buf
);
551 if (amtread
<=0 || vb2
.buf
[--amtread
]!='\n')
552 Psyntax("badly formed line");
554 if (memcmp(vb2
.buf
," read=",6)) Psyntax("syscall reply mismatch");
555 if (vb2
.buf
[6] == 'E') {
557 e
= Perrno(vb2
.buf
+6);
562 if (memcmp(vb2
.buf
+6,"OK",2)) Psyntax("success/fail not E* or OK");
565 assert(vb2
.used
<= amtread
);
566 if (vb2
.used
!= amtread
) Psyntax("junk at end of line");
567 r
= Pbytes(buf
,buflen
);
571 int Hwrite( int fd
, const void *buf
, size_t len
) {
574 Qwrite( fd
, buf
, len
);
575 if (!adns__vbuf_ensure(&vb2
,1000)) Tnomem();
576 fgets(vb2
.buf
,vb2
.avail
,Tinputfile
); Pcheckinput();
578 fprintf(Treportfile
,"%s",vb2
.buf
);
579 amtread
= strlen(vb2
.buf
);
580 if (amtread
<=0 || vb2
.buf
[--amtread
]!='\n')
581 Psyntax("badly formed line");
583 if (memcmp(vb2
.buf
," write=",7)) Psyntax("syscall reply mismatch");
584 if (vb2
.buf
[7] == 'E') {
586 e
= Perrno(vb2
.buf
+7);
591 r
= strtoul(vb2
.buf
+7,&ep
,10);
592 if (*ep
&& *ep
!=' ') Psyntax("return value not E* or positive number");
593 vb2
.used
= ep
- (char*)vb2
.buf
;
594 assert(vb2
.used
<= amtread
);
595 if (vb2
.used
!= amtread
) Psyntax("junk at end of line");