Commit | Line | Data |
---|---|---|
f9476535 | 1 | #include <string.h> |
2 | #include <errno.h> | |
3 | #include <stdlib.h> | |
4e25ff4e | 4 | #include <stdarg.h> |
f9476535 | 5 | #include <sys/types.h> |
6 | #include <sys/socket.h> | |
7 | #include <netinet/in.h> | |
8 | #include <arpa/inet.h> | |
9 | #include <unistd.h> | |
10 | #include <fcntl.h> | |
11 | #include "harness.h" | |
12 | #include "internal.h" | |
13 | vbuf vb; | |
14 | FILE *Toutputfile= 0; | |
15 | struct timeval currenttime; | |
16 | const struct Terrno Terrnos[]= { | |
17 | { "EBADF", EBADF }, | |
18 | { "EAGAIN", EAGAIN }, | |
19 | { "EINPROGRESS", EINPROGRESS }, | |
20 | { "EINTR", EINTR }, | |
21 | { "EINVAL", EINVAL }, | |
22 | { "EMSGSIZE", EMSGSIZE }, | |
23 | { "ENOBUFS", ENOBUFS }, | |
24 | { "ENOENT", ENOENT }, | |
25 | { "ENOPROTOOPT", ENOPROTOOPT }, | |
26 | { "ENOSPC", ENOSPC }, | |
27 | { "EWOULDBLOCK", EWOULDBLOCK }, | |
28 | { "EHOSTUNREACH", EHOSTUNREACH }, | |
29 | { "ECONNRESET", ECONNRESET }, | |
30 | { "ECONNREFUSED", ECONNREFUSED }, | |
31 | { "EPIPE", EPIPE }, | |
237ce710 | 32 | { "ENOTSOCK", ENOTSOCK }, |
f9476535 | 33 | { 0, 0 } |
34 | }; | |
35 | static vbuf vbw; | |
36 | int Hgettimeofday(struct timeval *tv, struct timezone *tz) { | |
87dd6345 | 37 | Tensurerecordfile(); |
f9476535 | 38 | Tmust("gettimeofday","tz",!tz); |
39 | *tv= currenttime; | |
40 | return 0; | |
41 | } | |
42 | int Hwritev(int fd, const struct iovec *vector, size_t count) { | |
43 | size_t i; | |
44 | vbw.used= 0; | |
45 | for (i=0; i<count; i++, vector++) { | |
46 | if (!adns__vbuf_append(&vbw,vector->iov_base,vector->iov_len)) Tnomem(); | |
47 | } | |
48 | return Hwrite(fd,vbw.buf,vbw.used); | |
49 | } | |
50 | void Qselect( int max , const fd_set *rfds , const fd_set *wfds , const fd_set *efds , struct timeval *to ) { | |
51 | vb.used= 0; | |
52 | Tvba("select"); | |
53 | Tvbf(" max=%d",max); | |
54 | Tvbf(" rfds="); Tvbfdset(max,rfds); | |
55 | Tvbf(" wfds="); Tvbfdset(max,wfds); | |
56 | Tvbf(" efds="); Tvbfdset(max,efds); | |
57 | if (to) Tvbf(" to=%ld.%06ld",(long)to->tv_sec,(long)to->tv_usec); | |
58 | else Tvba(" to=null"); | |
59 | Q_vb(); | |
60 | } | |
61 | #ifdef HAVE_POLL | |
62 | void Qpoll( const struct pollfd *fds , int nfds , int timeout ) { | |
63 | vb.used= 0; | |
64 | Tvba("poll"); | |
65 | Tvbf(" fds="); Tvbpollfds(fds,nfds); | |
66 | Tvbf(" timeout=%d",timeout); | |
67 | Q_vb(); | |
68 | } | |
69 | #endif | |
5c6cd9e0 | 70 | void Qsocket( int domain , int type ) { |
f9476535 | 71 | vb.used= 0; |
72 | Tvba("socket"); | |
9ec92889 IJ |
73 | Tvbf(domain==AF_INET ? " domain=AF_INET" : |
74 | domain==AF_INET6 ? " domain=AF_INET6" : | |
5c6cd9e0 | 75 | " domain=AF_???"); |
f9476535 | 76 | Tvbf(type==SOCK_STREAM ? " type=SOCK_STREAM" : " type=SOCK_DGRAM"); |
77 | Q_vb(); | |
78 | } | |
79 | void Qfcntl( int fd , int cmd , long arg ) { | |
80 | vb.used= 0; | |
81 | Tvba("fcntl"); | |
82 | Tvbf(" fd=%d",fd); | |
83 | if (cmd == F_SETFL) { | |
84 | Tvbf(" cmd=F_SETFL %s",arg & O_NONBLOCK ? "O_NONBLOCK|..." : "~O_NONBLOCK&..."); | |
85 | } else if (cmd == F_GETFL) { | |
86 | Tvba(" cmd=F_GETFL"); | |
87 | } else { | |
88 | Tmust("cmd","F_GETFL/F_SETFL",0); | |
89 | } | |
90 | Q_vb(); | |
91 | } | |
92 | void Qconnect( int fd , const struct sockaddr *addr , int addrlen ) { | |
93 | vb.used= 0; | |
94 | Tvba("connect"); | |
95 | Tvbf(" fd=%d",fd); | |
96 | Tvba(" addr="); Tvbaddr(addr,addrlen); | |
97 | Q_vb(); | |
98 | } | |
87dd6345 | 99 | void Qbind( int fd , const struct sockaddr *addr , int addrlen ) { |
100 | vb.used= 0; | |
101 | Tvba("bind"); | |
102 | Tvbf(" fd=%d",fd); | |
103 | Tvba(" addr="); Tvbaddr(addr,addrlen); | |
104 | Q_vb(); | |
105 | } | |
106 | void Qlisten( int fd , int backlog ) { | |
107 | vb.used= 0; | |
108 | Tvba("listen"); | |
109 | Tvbf(" fd=%d",fd); | |
110 | Tvbf(" backlog=%d",backlog); | |
111 | Q_vb(); | |
112 | } | |
f9476535 | 113 | void Qclose( int fd ) { |
114 | vb.used= 0; | |
115 | Tvba("close"); | |
116 | Tvbf(" fd=%d",fd); | |
117 | Q_vb(); | |
118 | } | |
119 | void Qsendto( int fd , const void *msg , int msglen , const struct sockaddr *addr , int addrlen ) { | |
120 | vb.used= 0; | |
121 | Tvba("sendto"); | |
122 | Tvbf(" fd=%d",fd); | |
123 | Tvba(" addr="); Tvbaddr(addr,addrlen); | |
124 | Tvbbytes(msg,msglen); | |
125 | Q_vb(); | |
126 | } | |
127 | void Qrecvfrom( int fd , int buflen , int addrlen ) { | |
128 | vb.used= 0; | |
129 | Tvba("recvfrom"); | |
130 | Tvbf(" fd=%d",fd); | |
131 | Tvbf(" buflen=%lu",(unsigned long)buflen); | |
f9476535 | 132 | Q_vb(); |
133 | } | |
134 | void Qread( int fd , size_t buflen ) { | |
135 | vb.used= 0; | |
136 | Tvba("read"); | |
137 | Tvbf(" fd=%d",fd); | |
138 | Tvbf(" buflen=%lu",(unsigned long)buflen); | |
139 | Q_vb(); | |
140 | } | |
141 | void Qwrite( int fd , const void *buf , size_t len ) { | |
142 | vb.used= 0; | |
143 | Tvba("write"); | |
144 | Tvbf(" fd=%d",fd); | |
145 | Tvbbytes(buf,len); | |
146 | Q_vb(); | |
147 | } | |
148 | void Tvbaddr(const struct sockaddr *addr, int len) { | |
84ada014 MW |
149 | char buf[ADNS_ADDR2TEXT_BUFLEN]; |
150 | int err, port; | |
151 | int sz= sizeof(buf); | |
152 | err= adns_addr2text(addr, 0, buf,&sz, &port); | |
153 | assert(!err); | |
154 | Tvbf(strchr(buf, ':') ? "[%s]:%d" : "%s:%d", buf,port); | |
f9476535 | 155 | } |
156 | void Tvbbytes(const void *buf, int len) { | |
157 | const byte *bp; | |
158 | int i; | |
159 | if (!len) { Tvba("\n ."); return; } | |
160 | for (i=0, bp=buf; i<len; i++, bp++) { | |
161 | if (!(i&31)) Tvba("\n "); | |
162 | else if (!(i&3)) Tvba(" "); | |
163 | Tvbf("%02x",*bp); | |
164 | } | |
165 | Tvba("."); | |
166 | } | |
167 | void Tvbfdset(int max, const fd_set *fds) { | |
168 | int i; | |
169 | const char *comma= ""; | |
170 | Tvba("["); | |
171 | for (i=0; i<max; i++) { | |
172 | if (!FD_ISSET(i,fds)) continue; | |
173 | Tvba(comma); | |
174 | Tvbf("%d",i); | |
175 | comma= ","; | |
176 | } | |
177 | Tvba("]"); | |
178 | } | |
179 | static void Tvbpollevents(int events) { | |
180 | const char *delim= ""; | |
181 | events &= (POLLIN|POLLOUT|POLLPRI); | |
182 | if (!events) { Tvba("0"); return; } | |
183 | if (events & POLLIN) { Tvba("POLLIN"); delim= "|"; } | |
184 | if (events & POLLOUT) { Tvba(delim); Tvba("POLLOUT"); delim= "|"; } | |
185 | if (events & POLLPRI) { Tvba(delim); Tvba("POLLPRI"); } | |
186 | } | |
187 | void Tvbpollfds(const struct pollfd *fds, int nfds) { | |
188 | const char *comma= ""; | |
189 | Tvba("["); | |
190 | while (nfds>0) { | |
191 | Tvba(comma); | |
192 | Tvbf("{fd=%d, events=",fds->fd); | |
193 | Tvbpollevents(fds->events); | |
194 | Tvba(", revents="); | |
195 | Tvbpollevents(fds->revents); | |
196 | Tvba("}"); | |
197 | comma= ", "; | |
198 | nfds--; fds++; | |
199 | } | |
200 | Tvba("]"); | |
201 | } | |
202 | void Tvberrno(int e) { | |
203 | const struct Terrno *te; | |
204 | for (te= Terrnos; te->n && te->v != e; te++); | |
205 | assert(te->n); | |
206 | Tvba(te->n); | |
207 | } | |
208 | void Tvba(const char *str) { | |
209 | if (!adns__vbuf_appendstr(&vb,str)) Tnomem(); | |
210 | } | |
211 | void Tvbvf(const char *fmt, va_list al) { | |
212 | char buf[1000]; | |
213 | buf[sizeof(buf)-2]= '\t'; | |
214 | vsnprintf(buf,sizeof(buf),fmt,al); | |
215 | assert(buf[sizeof(buf)-2] == '\t'); | |
216 | Tvba(buf); | |
217 | } | |
218 | void Tvbf(const char *fmt, ...) { | |
219 | va_list al; | |
220 | va_start(al,fmt); | |
221 | Tvbvf(fmt,al); | |
222 | va_end(al); | |
223 | } | |
224 | void Tmust(const char *call, const char *arg, int cond) { | |
225 | if (cond) return; | |
226 | fprintf(stderr,"adns test harness: case not handled: system call %s, arg %s",call,arg); | |
227 | exit(-1); | |
228 | } | |
229 | void Tfailed(const char *why) { | |
230 | fprintf(stderr,"adns test harness: failure: %s: %s\n",why,strerror(errno)); | |
231 | exit(-1); | |
232 | } | |
233 | void Tnomem(void) { | |
234 | Tfailed("unable to malloc/realloc"); | |
235 | } | |
236 | void Toutputerr(void) { | |
237 | Tfailed("write error on test harness output"); | |
238 | } | |
239 | struct malloced { | |
240 | struct malloced *next, *back; | |
241 | size_t sz; | |
242 | unsigned long count; | |
243 | struct { double d; long ul; void *p; void (*fp)(void); } data; | |
244 | }; | |
245 | static unsigned long malloccount, mallocfailat; | |
246 | static struct { struct malloced *head, *tail; } mallocedlist; | |
247 | #define MALLOCHSZ ((char*)&mallocedlist.head->data - (char*)mallocedlist.head) | |
248 | void *Hmalloc(size_t sz) { | |
249 | struct malloced *newnode; | |
250 | const char *mfavar; | |
251 | char *ep; | |
252 | assert(sz); | |
253 | newnode= malloc(MALLOCHSZ + sz); if (!newnode) Tnomem(); | |
254 | LIST_LINK_TAIL(mallocedlist,newnode); | |
255 | newnode->sz= sz; | |
256 | newnode->count= ++malloccount; | |
257 | if (!mallocfailat) { | |
258 | mfavar= getenv("ADNS_REGRESS_MALLOCFAILAT"); | |
259 | if (mfavar) { | |
260 | mallocfailat= strtoul(mfavar,&ep,10); | |
261 | if (!mallocfailat || *ep) Tfailed("ADNS_REGRESS_MALLOCFAILAT bad value"); | |
262 | } else { | |
263 | mallocfailat= ~0UL; | |
264 | } | |
265 | } | |
266 | assert(newnode->count != mallocfailat); | |
267 | memset(&newnode->data,0xc7,sz); | |
268 | return &newnode->data; | |
269 | } | |
270 | void Hfree(void *ptr) { | |
271 | struct malloced *oldnode; | |
272 | if (!ptr) return; | |
273 | oldnode= (void*)((char*)ptr - MALLOCHSZ); | |
274 | LIST_UNLINK(mallocedlist,oldnode); | |
275 | memset(&oldnode->data,0x38,oldnode->sz); | |
276 | free(oldnode); | |
277 | } | |
278 | void *Hrealloc(void *op, size_t nsz) { | |
279 | struct malloced *oldnode; | |
280 | void *np; | |
281 | size_t osz; | |
282 | if (op) { oldnode= (void*)((char*)op - MALLOCHSZ); osz= oldnode->sz; } else { osz= 0; } | |
283 | np= Hmalloc(nsz); | |
284 | memcpy(np,op, osz>nsz ? nsz : osz); | |
285 | Hfree(op); | |
286 | return np; | |
287 | } | |
288 | void Hexit(int rv) { | |
289 | struct malloced *loopnode; | |
290 | Tshutdown(); | |
291 | adns__vbuf_free(&vb); | |
292 | adns__vbuf_free(&vbw); | |
293 | if (mallocedlist.head) { | |
294 | fprintf(stderr,"adns test harness: memory leaked:"); | |
295 | for (loopnode=mallocedlist.head; loopnode; loopnode=loopnode->next) | |
cb0a827b | 296 | fprintf(stderr," %lu",loopnode->count); |
f9476535 | 297 | putc('\n',stderr); |
298 | if (ferror(stderr)) exit(-1); | |
299 | } | |
300 | exit(rv); | |
301 | } | |
0e45654b | 302 | pid_t Hgetpid(void) { |
303 | return 2264; /* just some number */ | |
304 | } |