chiark / gitweb /
Fix typo in changelog entry for 1.6.1
[adns.git] / regress / hcommon.c.m4
1 m4_dnl hcommon.c
2 m4_dnl (part of complex test harness, not of the library)
3 m4_dnl - routines used for both record and playback
4
5 m4_dnl  This file is part of adns, which is Copyright Ian Jackson
6 m4_dnl  and contributors (see the file INSTALL for full details).
7 m4_dnl  
8 m4_dnl  This program is free software; you can redistribute it and/or modify
9 m4_dnl  it under the terms of the GNU General Public License as published by
10 m4_dnl  the Free Software Foundation; either version 3, or (at your option)
11 m4_dnl  any later version.
12 m4_dnl  
13 m4_dnl  This program is distributed in the hope that it will be useful,
14 m4_dnl  but WITHOUT ANY WARRANTY; without even the implied warranty of
15 m4_dnl  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 m4_dnl  GNU General Public License for more details.
17 m4_dnl  
18 m4_dnl  You should have received a copy of the GNU General Public License
19 m4_dnl  along with this program; if not, write to the Free Software Foundation.
20
21 m4_include(hmacros.i4)
22
23 #include <string.h>
24 #include <errno.h>
25 #include <stdlib.h>
26 #include <stdarg.h>
27
28 #include <sys/types.h>
29 #include <sys/socket.h>
30 #include <netinet/in.h>
31 #include <arpa/inet.h>
32
33 #include <unistd.h>
34 #include <fcntl.h>
35 #include <time.h>
36
37 #include "harness.h"
38 #include "internal.h"
39
40 vbuf vb;
41 FILE *Toutputfile= 0;
42 struct timeval currenttime;
43
44 const struct Terrno Terrnos[]= {
45   { "EBADF",                     EBADF                        },
46   { "EAGAIN",                    EAGAIN                       },
47   { "EINPROGRESS",               EINPROGRESS                  },
48   { "EINTR",                     EINTR                        },
49   { "EINVAL",                    EINVAL                       },
50   { "EMSGSIZE",                  EMSGSIZE                     },
51   { "ENOBUFS",                   ENOBUFS                      },
52   { "ENOENT",                    ENOENT                       },
53   { "ENOPROTOOPT",               ENOPROTOOPT                  },
54   { "ENOSPC",                    ENOSPC                       },
55   { "EWOULDBLOCK",               EWOULDBLOCK                  },
56   { "EHOSTUNREACH",              EHOSTUNREACH                 },
57   { "ECONNRESET",                ECONNRESET                   },
58   { "ECONNREFUSED",              ECONNREFUSED                 },
59   { "EPIPE",                     EPIPE                        },
60   { "ENOTSOCK",                  ENOTSOCK                     },
61   {  0,                          0                            }
62 };
63
64 const int Tnerrnos= sizeof(Terrnos)/sizeof(Terrnos[0]) - 1;
65
66 static vbuf vbw;
67
68 int Hgettimeofday(struct timeval *tv, struct timezone *tz) {
69   Tensuresetup();
70   Tmust("gettimeofday","tz",!tz);
71   T_gettimeofday_hook();
72   *tv= currenttime;
73   return 0;
74 }
75 int Hclock_gettime(clockid_t clk, struct timespec *ts) {
76   Tensuresetup();
77   ts->tv_sec =  currenttime.tv_sec;
78   ts->tv_nsec = currenttime.tv_usec * 1000 + 666;
79   switch (clk) {
80   case CLOCK_MONOTONIC: ts->tv_sec -= 1500000000; break;
81   case CLOCK_REALTIME:                            break;
82   default: Tmust("clock_gettime","clk",0);
83   }
84   return 0;
85 }
86
87 int Hwritev(int fd, const struct iovec *vector, size_t count) {
88   size_t i;
89   
90   vbw.used= 0;
91   for (i=0; i<count; i++, vector++) {
92     if (!adns__vbuf_append(&vbw,vector->iov_base,vector->iov_len)) Tnomem();
93   }
94   return Hwrite(fd,vbw.buf,vbw.used);
95 }
96
97 m4_define(`hm_syscall', `
98  hm_create_proto_q
99 void Q$1(hm_args_massage($3,void)) {
100
101  vb.used= 0;
102  Tvba("$1");
103  m4_define(`hm_na',`')
104  m4_define(`hm_arg_nullptr',`')
105  m4_define(`hm_arg_int', `Tvbf(" $'`1=%d",$'`1);')
106  m4_define(`hm_arg_fdset_io', `Tvbf(" $'`1="); Tvbfdset($'`2,$'`1);')
107  m4_define(`hm_arg_pollfds_io', `Tvbf(" $'`1="); Tvbpollfds($'`1,$'`2);')
108  m4_define(`hm_arg_timeval_in_rel_null', `
109   if ($'`1) Tvbf(" $'`1=%ld.%06ld",(long)$'`1->tv_sec,(long)$'`1->tv_usec);
110   else Tvba(" $'`1=null");')
111  m4_define(`hm_arg_must', `')
112  m4_define(`hm_arg_socktype', `
113   Tvbf($'`1==SOCK_STREAM ? " $'`1=SOCK_STREAM" : " $'`1=SOCK_DGRAM");')
114  m4_define(`hm_arg_addrfam', `
115   Tvbf($'`1==AF_INET ? " $'`1=AF_INET" :
116           $'`1==AF_INET6 ? " $'`1=AF_INET6" :
117           " $'`1=AF_???");')
118  m4_define(`hm_arg_ign', `')
119  m4_define(`hm_arg_fd', `Tvbf(" $'`1=%d",$'`1);')
120  m4_define(`hm_arg_fcntl_cmd_arg', `
121   if ($'`1 == F_SETFL) {
122    Tvbf(" $'`1=F_SETFL %s",arg & O_NONBLOCK ? "O_NONBLOCK|..." : "~O_NONBLOCK&...");
123   } else if ($'`1 == F_GETFL) {
124    Tvba(" $'`1=F_GETFL");
125   } else {
126    Tmust("$'`1","F_GETFL/F_SETFL",0);
127   }')
128  m4_define(`hm_arg_addr_in', `Tvba(" $'`1="); Tvbaddr($'`1,$'`2);')
129  m4_define(`hm_arg_bytes_in', `')
130  m4_define(`hm_arg_bytes_out', `Tvbf(" $'`4=%lu",(unsigned long)$'`4);')
131  m4_define(`hm_arg_addr_out', `')
132   $3
133
134  hm_create_nothing
135  m4_define(`hm_arg_bytes_in', `Tvbbytes($'`2,$'`4);')
136   $3
137
138   Q_vb();
139 }
140 ')
141
142 m4_define(`hm_specsyscall', `')
143
144 m4_include(`hsyscalls.i4')
145
146 hm_stdsyscall_close
147
148 void Tvbaddr(const struct sockaddr *addr, int len) {
149   char buf[ADNS_ADDR2TEXT_BUFLEN];
150   int err, port;
151   int sz= sizeof(buf);
152
153   err= adns_addr2text(addr, 0, buf,&sz, &port);
154   assert(!err);
155
156   Tvbf(strchr(buf, ':') ? "[%s]:%d" : "%s:%d", buf,port);
157 }
158
159 void Tvbbytes(const void *buf, int len) {
160   const byte *bp;
161   int i;
162
163   if (!len) { Tvba("\n     ."); return; }
164   for (i=0, bp=buf; i<len; i++, bp++) {
165     if (!(i&31)) Tvba("\n     ");
166     else if (!(i&3)) Tvba(" ");
167     Tvbf("%02x",*bp);
168   }
169   Tvba(".");
170 }
171
172 void Tvbfdset(int max, const fd_set *fds) {
173   int i;
174   const char *comma= "";
175   
176   if (!fds) {
177     Tvba("null");
178     return;
179   }
180
181   Tvba("[");
182   for (i=0; i<max; i++) {
183     if (!FD_ISSET(i,fds)) continue;
184     Tvba(comma);
185     Tvbf("%d",i);
186     comma= ",";
187   }
188   Tvba("]");
189 }
190
191 static void Tvbpollevents(int events) {
192   const char *delim= "";
193
194   events &= (POLLIN|POLLOUT|POLLPRI);
195   if (!events) { Tvba("0"); return; }
196   if (events & POLLIN) { Tvba("POLLIN"); delim= "|"; }
197   if (events & POLLOUT) { Tvba(delim); Tvba("POLLOUT"); delim= "|"; }
198   if (events & POLLPRI) { Tvba(delim); Tvba("POLLPRI"); }
199 }
200
201 void Tvbpollfds(const struct pollfd *fds, int nfds) {
202   const char *comma= "";
203   
204   Tvba("[");
205   while (nfds>0) {
206     Tvba(comma);
207     Tvbf("{fd=%d, events=",fds->fd);
208     Tvbpollevents(fds->events);
209     Tvba(", revents=");
210     Tvbpollevents(fds->revents);
211     Tvba("}");
212     comma= ", ";
213     nfds--; fds++;
214   }
215   Tvba("]");
216 }
217
218 void Tvberrno(int e) {
219   const struct Terrno *te;
220
221   for (te= Terrnos; te->n && te->v != e; te++);
222   assert(te->n);
223   Tvba(te->n);
224 }
225
226 void Tvba(const char *str) {
227   if (!adns__vbuf_appendstr(&vb,str)) Tnomem();
228 }
229
230 void Tvbvf(const char *fmt, va_list al) {
231   char buf[1000];
232   buf[sizeof(buf)-2]= '\t';
233   vsnprintf(buf,sizeof(buf),fmt,al);
234   assert(buf[sizeof(buf)-2] == '\t');
235
236   Tvba(buf);
237 }
238
239 void Tvbf(const char *fmt, ...) {
240   va_list al;
241   va_start(al,fmt);
242   Tvbvf(fmt,al);
243   va_end(al);
244 }
245
246
247 void Tmust(const char *call, const char *arg, int cond) {
248   if (cond) return;
249   fprintf(stderr,"adns test harness: case not handled: system call %s, arg %s",call,arg);
250   exit(-1);
251 }
252
253 void Tfailed(const char *why) {
254   fprintf(stderr,"adns test harness: failure: %s: %s\n",why,strerror(errno));
255   exit(-1);
256 }
257
258 void Tnomem(void) {
259   Tfailed("unable to malloc/realloc");
260 }
261
262 void Toutputerr(void) {
263   Tfailed("write error on test harness output");
264 }
265
266 void Hexit(int rv) {
267   Tensuresetup();
268   vb.used= 0;
269   Tvbf("exit %d", rv);
270   Q_vb();
271   Texit(0);
272 }
273
274 pid_t Hgetpid(void) {
275   return 2264; /* just some number */
276 }
277
278 void Tcommonshutdown(void) {
279   Tshutdown();
280   adns__vbuf_free(&vb);
281   adns__vbuf_free(&vbw);
282   Tmallocshutdown();
283 }