6 #include <sys/socket.h>
7 #include <netinet/in.h>
14 static FILE *Tinputfile
, *Treportfile
;
16 extern void Tshutdown(void) {
17 adns__vbuf_free(&vb2
);
19 static void Tensurereportfile(void) {
22 if (Treportfile
) return;
24 fdstr
= getenv("ADNS_TEST_REPORT_FD"); if (!fdstr
) return;
26 Treportfile
= fdopen(fd
,"a"); if (!Treportfile
) Tfailed("fdopen ADNS_TEST_REPORT_FD");
28 static void Psyntax(const char *where
) {
29 fprintf(stderr
,"adns test harness: syntax error in test log input file: %s\n",where
);
32 static void Pcheckinput(void) {
33 if (ferror(Tinputfile
)) Tfailed("read test log input file");
34 if (feof(Tinputfile
)) Psyntax("eof at syscall reply");
36 void Tensurerecordfile(void) {
40 unsigned long sec
, usec
;
41 if (Tinputfile
) return;
43 fdstr
= getenv("ADNS_TEST_IN_FD");
46 Tinputfile
= fdopen(fd
,"r"); if (!Tinputfile
) Tfailed("fdopen ADNS_TEST_IN_FD");
48 setvbuf(Tinputfile
,0,_IONBF
,0);
49 if (!adns__vbuf_ensure(&vb2
,1000)) Tnomem();
50 fgets(vb2
.buf
,vb2
.avail
,Tinputfile
); Pcheckinput();
52 sscanf(vb2
.buf
," start %lu.%lu%n",&sec
,&usec
,&chars
);
53 if (chars
==-1) Psyntax("start time invalid");
54 currenttime
.tv_sec
= sec
;
55 currenttime
.tv_usec
= usec
;
56 if (vb2
.buf
[chars
] != '\n') Psyntax("not newline after start time");
58 static void Parg(const char *argname
) {
60 if (vb2
.buf
[vb2
.used
++] != ' ') Psyntax("not a space before argument");
62 if (memcmp(vb2
.buf
+vb2
.used
,argname
,l
)) Psyntax("argument name wrong");
64 if (vb2
.buf
[vb2
.used
++] != '=') Psyntax("not = after argument name");
66 static int Pstring_maybe(const char *string
) {
69 if (memcmp(vb2
.buf
+vb2
.used
,string
,l
)) return 0;
73 static void Pstring(const char *string
, const char *emsg
) {
74 if (Pstring_maybe(string
)) return;
77 static int Perrno(const char *stuff
) {
78 const struct Terrno
*te
;
81 for (te
= Terrnos
; te
->n
&& strcmp(te
->n
,stuff
); te
++);
82 if (te
->n
) return te
->v
;
83 r
= strtoul(stuff
+2,&ep
,10);
84 if (*ep
) Psyntax("errno value not recognised, not numeric");
87 static void P_updatetime(void) {
89 unsigned long sec
, usec
;
90 if (!adns__vbuf_ensure(&vb2
,1000)) Tnomem();
91 fgets(vb2
.buf
,vb2
.avail
,Tinputfile
); Pcheckinput();
93 sscanf(vb2
.buf
," +%lu.%lu%n",&sec
,&usec
,&chars
);
94 if (chars
==-1) Psyntax("update time invalid");
95 currenttime
.tv_sec
+= sec
;
96 currenttime
.tv_usec
+= usec
;
97 if (currenttime
.tv_usec
> 1000000) {
99 currenttime
.tv_usec
-= 1000000;
101 if (vb2
.buf
[chars
] != '\n') Psyntax("not newline after update time");
103 static void Pfdset(fd_set
*set
, int max
) {
106 if (vb2
.buf
[vb2
.used
++] != '[') Psyntax("fd set start not [");
108 if (vb2
.buf
[vb2
.used
] == ']') { vb2
.used
++; return; }
110 r
= strtoul(vb2
.buf
+vb2
.used
,&ep
,10);
111 if (r
>=max
) Psyntax("fd set member > max");
112 if (ep
== (char*)vb2
.buf
+vb2
.used
) Psyntax("empty entry in fd set");
114 vb2
.used
= ep
- (char*)vb2
.buf
;
115 c
= vb2
.buf
[vb2
.used
++];
117 if (c
!= ',') Psyntax("fd set separator not ,");
121 static int Ppollfdevents(void) {
123 if (Pstring_maybe("0")) return 0;
125 if (Pstring_maybe("POLLIN")) {
127 if (!Pstring_maybe("|")) return events
;
129 if (Pstring_maybe("POLLOUT")) {
131 if (!Pstring_maybe("|")) return events
;
133 Pstring("POLLPRI","pollfdevents PRI?");
136 static void Ppollfds(struct pollfd
*fds
, int nfds
) {
139 const char *comma
= "";
140 if (vb2
.buf
[vb2
.used
++] != '[') Psyntax("pollfds start not [");
141 for (i
=0; i
<nfds
; i
++) {
142 Pstring("{fd=","{fd= in pollfds");
143 fds
->fd
= strtoul(vb2
.buf
+vb2
.used
,&ep
,10);
144 vb2
.used
= ep
- (char*)vb2
.buf
;
145 Pstring(", events=",", events= in pollfds");
146 fds
->events
= Ppollfdevents();
147 Pstring(", revents=",", revents= in pollfds");
148 fds
->revents
= Ppollfdevents();
149 Pstring("}","} in pollfds");
150 Pstring(comma
,"separator in pollfds");
153 if (vb2
.buf
[vb2
.used
++] != ']') Psyntax("pollfds end not ]");
156 static void Paddr(struct sockaddr
*addr
, int *lenr
) {
157 struct addrinfo
*ai
, hint
= { 0 };
163 if (!q
) Psyntax("missing :");
168 if (!q
) Psyntax("missing ]");
170 if (*q
!=':') Psyntax("expected : after ]");
173 for (ep
=q
; ctype_digit(*ep
); ep
++);
174 if (ep
==q
|| (*ep
&& *ep
!=' ')) Psyntax("invalid port number");
176 hint
.ai_socktype
= SOCK_DGRAM
;
177 hint
.ai_family
= AF_UNSPEC
;
178 hint
.ai_flags
= AI_NUMERICHOST
| AI_NUMERICSERV
;
179 err
= getaddrinfo(p
, q
, &hint
, &ai
);
180 if (err
) Psyntax("invalid address");
181 assert(*lenr
>= ai
->ai_addrlen
);
182 memcpy(addr
, ai
->ai_addr
, ai
->ai_addrlen
);
183 *lenr
= ai
->ai_addrlen
;
185 vb2
.used
= ep
- (char*)vb2
.buf
;
187 static int Pbytes(byte
*buf
, int maxlen
) {
188 static const char hexdigits
[]= "0123456789abcdef";
193 c
= getc(Tinputfile
); Pcheckinput();
194 if (c
=='\n' || c
==' ' || c
=='\t') continue;
196 pf
= strchr(hexdigits
,c
); if (!pf
) Psyntax("invalid first hex digit");
197 v
= (pf
-hexdigits
)<<4;
198 c
= getc(Tinputfile
); Pcheckinput();
199 pf
= strchr(hexdigits
,c
); if (!pf
) Psyntax("invalid second hex digit");
201 if (maxlen
<=0) Psyntax("buffer overflow in bytes");
206 c
= getc(Tinputfile
); Pcheckinput();
207 if (c
=='\n') return done
;
213 if (!adns__vbuf_ensure(&vb2
,vb
.used
+2)) Tnomem();
214 fread(vb2
.buf
,1,vb
.used
+2,Tinputfile
);
215 if (feof(Tinputfile
)) {
216 fprintf(stderr
,"adns test harness: input ends prematurely; program did:\n %.*s\n",
221 if (vb2
.buf
[0] != ' ') Psyntax("not space before call");
222 if (memcmp(vb
.buf
,vb2
.buf
+1,vb
.used
) ||
223 vb2
.buf
[vb
.used
+1] != '\n') {
225 "adns test harness: program did unexpected:\n %.*s\n"
226 "was expecting:\n %.*s\n",
227 vb
.used
,vb
.buf
, vb
.used
,vb2
.buf
+1);
231 nl
= memchr(vb
.buf
,'\n',vb
.used
);
232 fprintf(Treportfile
," %.*s\n", (int)(nl ? nl
- (const char*)vb
.buf
: vb
.used
), vb
.buf
);
234 int Hselect( int max
, fd_set
*rfds
, fd_set
*wfds
, fd_set
*efds
, struct timeval
*to
) {
237 Qselect( max
, rfds
, wfds
, efds
, to
);
238 if (!adns__vbuf_ensure(&vb2
,1000)) Tnomem();
239 fgets(vb2
.buf
,vb2
.avail
,Tinputfile
); Pcheckinput();
241 fprintf(Treportfile
,"%s",vb2
.buf
);
242 amtread
= strlen(vb2
.buf
);
243 if (amtread
<=0 || vb2
.buf
[--amtread
]!='\n')
244 Psyntax("badly formed line");
246 if (memcmp(vb2
.buf
," select=",8)) Psyntax("syscall reply mismatch");
247 if (vb2
.buf
[8] == 'E') {
249 e
= Perrno(vb2
.buf
+8);
254 r
= strtoul(vb2
.buf
+8,&ep
,10);
255 if (*ep
&& *ep
!=' ') Psyntax("return value not E* or positive number");
256 vb2
.used
= ep
- (char*)vb2
.buf
;
257 Parg("rfds"); Pfdset(rfds
,max
);
258 Parg("wfds"); Pfdset(wfds
,max
);
259 Parg("efds"); Pfdset(efds
,max
);
260 assert(vb2
.used
<= amtread
);
261 if (vb2
.used
!= amtread
) Psyntax("junk at end of line");
266 int Hpoll( struct pollfd
*fds
, int nfds
, int timeout
) {
269 Qpoll( fds
, nfds
, timeout
);
270 if (!adns__vbuf_ensure(&vb2
,1000)) Tnomem();
271 fgets(vb2
.buf
,vb2
.avail
,Tinputfile
); Pcheckinput();
273 fprintf(Treportfile
,"%s",vb2
.buf
);
274 amtread
= strlen(vb2
.buf
);
275 if (amtread
<=0 || vb2
.buf
[--amtread
]!='\n')
276 Psyntax("badly formed line");
278 if (memcmp(vb2
.buf
," poll=",6)) Psyntax("syscall reply mismatch");
279 if (vb2
.buf
[6] == 'E') {
281 e
= Perrno(vb2
.buf
+6);
286 r
= strtoul(vb2
.buf
+6,&ep
,10);
287 if (*ep
&& *ep
!=' ') Psyntax("return value not E* or positive number");
288 vb2
.used
= ep
- (char*)vb2
.buf
;
289 Parg("fds"); Ppollfds(fds
,nfds
);
290 assert(vb2
.used
<= amtread
);
291 if (vb2
.used
!= amtread
) Psyntax("junk at end of line");
296 int Hsocket( int domain
, int type
, int protocol
) {
299 Tmust("socket","domain",domain
==AF_INET
);
300 Tmust("socket","type",type
==SOCK_STREAM
|| type
==SOCK_DGRAM
);
302 if (!adns__vbuf_ensure(&vb2
,1000)) Tnomem();
303 fgets(vb2
.buf
,vb2
.avail
,Tinputfile
); Pcheckinput();
305 fprintf(Treportfile
,"%s",vb2
.buf
);
306 amtread
= strlen(vb2
.buf
);
307 if (amtread
<=0 || vb2
.buf
[--amtread
]!='\n')
308 Psyntax("badly formed line");
310 if (memcmp(vb2
.buf
," socket=",8)) Psyntax("syscall reply mismatch");
311 if (vb2
.buf
[8] == 'E') {
313 e
= Perrno(vb2
.buf
+8);
318 r
= strtoul(vb2
.buf
+8,&ep
,10);
319 if (*ep
&& *ep
!=' ') Psyntax("return value not E* or positive number");
320 vb2
.used
= ep
- (char*)vb2
.buf
;
321 assert(vb2
.used
<= amtread
);
322 if (vb2
.used
!= amtread
) Psyntax("junk at end of line");
326 int Hfcntl( int fd
, int cmd
, ... ) {
328 va_list al
; long arg
;
329 Tmust("fcntl","cmd",cmd
==F_SETFL
|| cmd
==F_GETFL
);
330 if (cmd
== F_SETFL
) {
331 va_start(al
,cmd
); arg
= va_arg(al
,long); va_end(al
);
335 Qfcntl( fd
, cmd
, arg
);
336 if (!adns__vbuf_ensure(&vb2
,1000)) Tnomem();
337 fgets(vb2
.buf
,vb2
.avail
,Tinputfile
); Pcheckinput();
339 fprintf(Treportfile
,"%s",vb2
.buf
);
340 amtread
= strlen(vb2
.buf
);
341 if (amtread
<=0 || vb2
.buf
[--amtread
]!='\n')
342 Psyntax("badly formed line");
344 if (memcmp(vb2
.buf
," fcntl=",7)) Psyntax("syscall reply mismatch");
345 if (vb2
.buf
[7] == 'E') {
347 e
= Perrno(vb2
.buf
+7);
353 if (cmd
== F_GETFL
) {
354 if (!memcmp(vb2
.buf
+7,"O_NONBLOCK|...",14)) {
357 } else if (!memcmp(vb2
.buf
+7,"~O_NONBLOCK&...",15)) {
360 Psyntax("fcntl flags not O_NONBLOCK|... or ~O_NONBLOCK&...");
362 } else if (cmd
== F_SETFL
) {
363 if (memcmp(vb2
.buf
+7,"OK",2)) Psyntax("success/fail not E* or OK");
367 Psyntax("fcntl not F_GETFL or F_SETFL");
369 assert(vb2
.used
<= amtread
);
370 if (vb2
.used
!= amtread
) Psyntax("junk at end of line");
374 int Hconnect( int fd
, const struct sockaddr
*addr
, int addrlen
) {
376 Qconnect( fd
, addr
, addrlen
);
377 if (!adns__vbuf_ensure(&vb2
,1000)) Tnomem();
378 fgets(vb2
.buf
,vb2
.avail
,Tinputfile
); Pcheckinput();
380 fprintf(Treportfile
,"%s",vb2
.buf
);
381 amtread
= strlen(vb2
.buf
);
382 if (amtread
<=0 || vb2
.buf
[--amtread
]!='\n')
383 Psyntax("badly formed line");
385 if (memcmp(vb2
.buf
," connect=",9)) Psyntax("syscall reply mismatch");
386 if (vb2
.buf
[9] == 'E') {
388 e
= Perrno(vb2
.buf
+9);
393 if (memcmp(vb2
.buf
+9,"OK",2)) Psyntax("success/fail not E* or OK");
396 assert(vb2
.used
<= amtread
);
397 if (vb2
.used
!= amtread
) Psyntax("junk at end of line");
401 int Hbind( int fd
, const struct sockaddr
*addr
, int addrlen
) {
403 Qbind( fd
, addr
, addrlen
);
404 if (!adns__vbuf_ensure(&vb2
,1000)) Tnomem();
405 fgets(vb2
.buf
,vb2
.avail
,Tinputfile
); Pcheckinput();
407 fprintf(Treportfile
,"%s",vb2
.buf
);
408 amtread
= strlen(vb2
.buf
);
409 if (amtread
<=0 || vb2
.buf
[--amtread
]!='\n')
410 Psyntax("badly formed line");
412 if (memcmp(vb2
.buf
," bind=",6)) Psyntax("syscall reply mismatch");
413 if (vb2
.buf
[6] == 'E') {
415 e
= Perrno(vb2
.buf
+6);
420 if (memcmp(vb2
.buf
+6,"OK",2)) Psyntax("success/fail not E* or OK");
423 assert(vb2
.used
<= amtread
);
424 if (vb2
.used
!= amtread
) Psyntax("junk at end of line");
428 int Hlisten( int fd
, int backlog
) {
430 Qlisten( fd
, backlog
);
431 if (!adns__vbuf_ensure(&vb2
,1000)) Tnomem();
432 fgets(vb2
.buf
,vb2
.avail
,Tinputfile
); Pcheckinput();
434 fprintf(Treportfile
,"%s",vb2
.buf
);
435 amtread
= strlen(vb2
.buf
);
436 if (amtread
<=0 || vb2
.buf
[--amtread
]!='\n')
437 Psyntax("badly formed line");
439 if (memcmp(vb2
.buf
," listen=",8)) Psyntax("syscall reply mismatch");
440 if (vb2
.buf
[8] == 'E') {
442 e
= Perrno(vb2
.buf
+8);
447 if (memcmp(vb2
.buf
+8,"OK",2)) Psyntax("success/fail not E* or OK");
450 assert(vb2
.used
<= amtread
);
451 if (vb2
.used
!= amtread
) Psyntax("junk at end of line");
455 int Hclose( int fd
) {
458 if (!adns__vbuf_ensure(&vb2
,1000)) Tnomem();
459 fgets(vb2
.buf
,vb2
.avail
,Tinputfile
); Pcheckinput();
461 fprintf(Treportfile
,"%s",vb2
.buf
);
462 amtread
= strlen(vb2
.buf
);
463 if (amtread
<=0 || vb2
.buf
[--amtread
]!='\n')
464 Psyntax("badly formed line");
466 if (memcmp(vb2
.buf
," close=",7)) Psyntax("syscall reply mismatch");
467 if (vb2
.buf
[7] == 'E') {
469 e
= Perrno(vb2
.buf
+7);
474 if (memcmp(vb2
.buf
+7,"OK",2)) Psyntax("success/fail not E* or OK");
477 assert(vb2
.used
<= amtread
);
478 if (vb2
.used
!= amtread
) Psyntax("junk at end of line");
482 int Hsendto( int fd
, const void *msg
, int msglen
, unsigned int flags
, const struct sockaddr
*addr
, int addrlen
) {
485 Tmust("sendto","flags",flags
==0);
486 Qsendto( fd
, msg
, msglen
, addr
, addrlen
);
487 if (!adns__vbuf_ensure(&vb2
,1000)) Tnomem();
488 fgets(vb2
.buf
,vb2
.avail
,Tinputfile
); Pcheckinput();
490 fprintf(Treportfile
,"%s",vb2
.buf
);
491 amtread
= strlen(vb2
.buf
);
492 if (amtread
<=0 || vb2
.buf
[--amtread
]!='\n')
493 Psyntax("badly formed line");
495 if (memcmp(vb2
.buf
," sendto=",8)) Psyntax("syscall reply mismatch");
496 if (vb2
.buf
[8] == 'E') {
498 e
= Perrno(vb2
.buf
+8);
503 r
= strtoul(vb2
.buf
+8,&ep
,10);
504 if (*ep
&& *ep
!=' ') Psyntax("return value not E* or positive number");
505 vb2
.used
= ep
- (char*)vb2
.buf
;
506 assert(vb2
.used
<= amtread
);
507 if (vb2
.used
!= amtread
) Psyntax("junk at end of line");
511 int Hrecvfrom( int fd
, void *buf
, int buflen
, unsigned int flags
, struct sockaddr
*addr
, int *addrlen
) {
513 Tmust("recvfrom","flags",flags
==0);
514 Tmust("recvfrom","*addrlen",*addrlen
>=sizeof(struct sockaddr_in
));
515 Qrecvfrom( fd
, buflen
, *addrlen
);
516 if (!adns__vbuf_ensure(&vb2
,1000)) Tnomem();
517 fgets(vb2
.buf
,vb2
.avail
,Tinputfile
); Pcheckinput();
519 fprintf(Treportfile
,"%s",vb2
.buf
);
520 amtread
= strlen(vb2
.buf
);
521 if (amtread
<=0 || vb2
.buf
[--amtread
]!='\n')
522 Psyntax("badly formed line");
524 if (memcmp(vb2
.buf
," recvfrom=",10)) Psyntax("syscall reply mismatch");
525 if (vb2
.buf
[10] == 'E') {
527 e
= Perrno(vb2
.buf
+10);
532 if (memcmp(vb2
.buf
+10,"OK",2)) Psyntax("success/fail not E* or OK");
535 Parg("addr"); Paddr(addr
,addrlen
);
536 assert(vb2
.used
<= amtread
);
537 if (vb2
.used
!= amtread
) Psyntax("junk at end of line");
538 r
= Pbytes(buf
,buflen
);
542 int Hread( int fd
, void *buf
, size_t buflen
) {
544 Qread( fd
, buflen
);
545 if (!adns__vbuf_ensure(&vb2
,1000)) Tnomem();
546 fgets(vb2
.buf
,vb2
.avail
,Tinputfile
); Pcheckinput();
548 fprintf(Treportfile
,"%s",vb2
.buf
);
549 amtread
= strlen(vb2
.buf
);
550 if (amtread
<=0 || vb2
.buf
[--amtread
]!='\n')
551 Psyntax("badly formed line");
553 if (memcmp(vb2
.buf
," read=",6)) Psyntax("syscall reply mismatch");
554 if (vb2
.buf
[6] == 'E') {
556 e
= Perrno(vb2
.buf
+6);
561 if (memcmp(vb2
.buf
+6,"OK",2)) Psyntax("success/fail not E* or OK");
564 assert(vb2
.used
<= amtread
);
565 if (vb2
.used
!= amtread
) Psyntax("junk at end of line");
566 r
= Pbytes(buf
,buflen
);
570 int Hwrite( int fd
, const void *buf
, size_t len
) {
573 Qwrite( fd
, buf
, len
);
574 if (!adns__vbuf_ensure(&vb2
,1000)) Tnomem();
575 fgets(vb2
.buf
,vb2
.avail
,Tinputfile
); Pcheckinput();
577 fprintf(Treportfile
,"%s",vb2
.buf
);
578 amtread
= strlen(vb2
.buf
);
579 if (amtread
<=0 || vb2
.buf
[--amtread
]!='\n')
580 Psyntax("badly formed line");
582 if (memcmp(vb2
.buf
," write=",7)) Psyntax("syscall reply mismatch");
583 if (vb2
.buf
[7] == 'E') {
585 e
= Perrno(vb2
.buf
+7);
590 r
= strtoul(vb2
.buf
+7,&ep
,10);
591 if (*ep
&& *ep
!=' ') Psyntax("return value not E* or positive number");
592 vb2
.used
= ep
- (char*)vb2
.buf
;
593 assert(vb2
.used
<= amtread
);
594 if (vb2
.used
!= amtread
) Psyntax("junk at end of line");