summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorian <ian>1998-11-29 17:52:32 +0000
committerian <ian>1998-11-29 17:52:32 +0000
commit70a778e57fbc29a2d2bc8976745a18f4edd1a03a (patch)
tree11dd3a1fd27d631eb9faa6b968f12be49ca44b55
parentc28c61993f654bd4b225537ea04effa5c4a5337f (diff)
First record and playback works.
-rw-r--r--regress/.cvsignore4
-rw-r--r--regress/harness.h.m45
-rw-r--r--regress/hcommon.c.m425
-rw-r--r--regress/hmacros.i41
-rw-r--r--regress/hplayback.c.m4263
-rw-r--r--regress/hrecord.c.m416
-rw-r--r--src/Makefile17
-rw-r--r--src/Makefile.in17
8 files changed, 321 insertions, 27 deletions
diff --git a/regress/.cvsignore b/regress/.cvsignore
index 70857af..2b26f2c 100644
--- a/regress/.cvsignore
+++ b/regress/.cvsignore
@@ -1,5 +1,7 @@
dtest
-hrecord
harness.h
hcommon.c
+hrecord
hrecord.c
+hplayback
+hplayback.c
diff --git a/regress/harness.h.m4 b/regress/harness.h.m4
index 7b5758e..5f0c9f4 100644
--- a/regress/harness.h.m4
+++ b/regress/harness.h.m4
@@ -25,6 +25,7 @@ m4_include(hmacros.i4)
#include <sys/time.h>
#include <sys/socket.h>
+#include <sys/uio.h>
#include <unistd.h>
#include "internal.h"
@@ -35,6 +36,8 @@ hm_create_proto_h
m4_define(`hm_syscall', `int H$1(hm_args_massage($3,void));')
m4_include(`hsyscalls.i4')
+int Hwritev(int fd, const struct iovec *vector, size_t count);
+
/* There is a Q function (Q for Question) for each such syscall;
* it constructs a string representing the call, and calls Q_str
* on it, or constructs it in vb and calls Q_vb;
@@ -66,8 +69,6 @@ void Tvba(const char *str);
/* Shared globals */
extern vbuf vb;
-extern FILE *Toutputfile;
-
extern const struct Terrno { const char *n; int v; } Terrnos[];
#endif
diff --git a/regress/hcommon.c.m4 b/regress/hcommon.c.m4
index 4c1af7c..5d6f471 100644
--- a/regress/hcommon.c.m4
+++ b/regress/hcommon.c.m4
@@ -48,8 +48,17 @@ const struct Terrno Terrnos[]= {
{ 0, 0 }
};
+static vbuf vbw;
-
+int Hwritev(int fd, const struct iovec *vector, size_t count) {
+ size_t i;
+
+ vbw.used= 0;
+ for (i=0; i<count; i++, vector++) {
+ if (!adns__vbuf_append(&vbw,vector->iov_base,vector->iov_len)) Tnomem();
+ }
+ return Hwrite(fd,vbw.buf,vbw.used);
+}
m4_define(`hm_syscall', `
hm_create_proto_q
@@ -75,12 +84,16 @@ void Q$1(hm_args_massage($3,void)) {
} else {
Tvba(" $'`1=F_GETFL");
}')
- m4_define(`hm_arg_addr_in', `Tvbaddr($'`1,$'`2);')
- m4_define(`hm_arg_bytes_in', `Tvbbytes($'`2,$'`4);')
+ m4_define(`hm_arg_addr_in', `Tvba(" $'`1="); Tvbaddr($'`1,$'`2);')
+ m4_define(`hm_arg_bytes_in', `')
m4_define(`hm_arg_bytes_out', `Tvbf(" $'`4=%lu",(unsigned long)$'`4);')
m4_define(`hm_arg_addr_out', `Tvbf(" *$'`2=%d",$'`2);')
$3
+ hm_create_nothing
+ m4_define(`hm_arg_bytes_in', `Tvbbytes($'`2,$'`4);')
+ $3
+
Q_vb();
}
')
@@ -106,6 +119,7 @@ void Tvbbytes(const void *buf, int len) {
else if (!(i&3)) Tvba(" ");
Tvbf("%02x",*bp);
}
+ Tvba(".");
}
void Tvbfdset(int max, const fd_set *fds) {
@@ -169,8 +183,3 @@ void Tnomem(void) {
void Toutputerr(void) {
Tfailed("write error on test harness output");
}
-
-void Tensureoutputfile(void) {
- /* fixme: allow sending it elsewhere */
- Toutputfile= stdout;
-}
diff --git a/regress/hmacros.i4 b/regress/hmacros.i4
index ebbd682..4e5123e 100644
--- a/regress/hmacros.i4
+++ b/regress/hmacros.i4
@@ -99,6 +99,7 @@ m4_define(`hm_create_hqcall_init',`
} else {
$'`2= 0;
}')
+ m4_define(`hm_arg_addr_out',`Tmust("$1","*$'`2",*$'`2>=sizeof(struct sockaddr_in));')
')
m4_define(`hm_create_realcall_args',`
diff --git a/regress/hplayback.c.m4 b/regress/hplayback.c.m4
new file mode 100644
index 0000000..5431c26
--- /dev/null
+++ b/regress/hplayback.c.m4
@@ -0,0 +1,263 @@
+m4_dnl hplayback.c.m4
+m4_dnl (part of complex test harness, not of the library)
+m4_dnl - playback routines
+
+m4_dnl This file is part of adns, which is Copyright (C) 1997, 1998 Ian Jackson
+m4_dnl
+m4_dnl This program is free software; you can redistribute it and/or modify
+m4_dnl it under the terms of the GNU General Public License as published by
+m4_dnl the Free Software Foundation; either version 2, or (at your option)
+m4_dnl any later version.
+m4_dnl
+m4_dnl This program is distributed in the hope that it will be useful,
+m4_dnl but WITHOUT ANY WARRANTY; without even the implied warranty of
+m4_dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+m4_dnl GNU General Public License for more details.
+m4_dnl
+m4_dnl You should have received a copy of the GNU General Public License
+m4_dnl along with this program; if not, write to the Free Software Foundation,
+m4_dnl Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+m4_include(hmacros.i4)
+
+#include <assert.h>
+#include <string.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <stdlib.h>
+
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#include "harness.h"
+
+static FILE *Tinputfile;
+static vbuf vb2;
+
+static void Tensureinputfile(void) {
+ const char *fdstr;
+ int fd;
+
+ Tinputfile= stdin;
+ fdstr= getenv("ADNS_TEST_IN_FD"); if (!fdstr) return;
+ fd= atoi(fdstr);
+ Tinputfile= fdopen(fd,"r"); if (!Tinputfile) Tfailed("fdopen ADNS_TEST_IN_FD");
+}
+
+static void Psyntax(const char *where) {
+ fprintf(stderr,"adns test harness: syntax error in test log input file: %s\n",where);
+ exit(-1);
+}
+
+static void Pcheckinput(void) {
+ if (ferror(Tinputfile)) Tfailed("read test log input file");
+ if (feof(Tinputfile)) Psyntax("eof at syscall reply");
+}
+
+static void Parg(const char *argname) {
+ int l;
+
+ if (vb2.buf[vb2.used++] != hm_squote hm_squote) Psyntax("not a space before argument");
+ l= strlen(argname);
+ if (memcmp(vb2.buf+vb2.used,argname,l)) Psyntax("argument name wrong");
+ vb2.used+= l;
+ if (vb2.buf[vb2.used++] != hm_squote=hm_squote) Psyntax("not = after argument name");
+}
+
+static int Perrno(const char *stuff) {
+ const struct Terrno *te;
+ int r;
+ char *ep;
+
+ for (te= Terrnos; te->n && strcmp(te->n,stuff); te++);
+ if (te->n) return te->v;
+ r= strtoul(stuff+1,&ep,10);
+ if (ep) Psyntax("errno value not recognised, not numeric");
+ return r;
+}
+
+static struct timeval begin;
+
+static void Ptimevalabs(struct timeval *tvr) {
+ int store, chars;
+ unsigned long sec, usec;
+ struct timeval rv;
+
+ if (vb2.buf[vb2.used]==hm_squote+hm_squote) {
+ vb2.used++;
+ rv= begin;
+ store= 0;
+ } else {
+ rv.tv_sec= 0;
+ rv.tv_usec= 0;
+ store= 1;
+ }
+ chars= -1;
+ sscanf(vb2.buf+vb2.used,"%lu.%lu%n",&sec,&usec,&chars);
+ if (chars==-1) Psyntax("timeval syntax error");
+ rv.tv_sec += sec;
+ rv.tv_usec += usec;
+ if (begin.tv_usec > 1000000) {
+ rv.tv_sec++;
+ rv.tv_usec -= 1000000;
+ }
+ *tvr= rv;
+ if (store) begin= rv;
+
+ vb2.used += chars;
+}
+
+static void Pfdset(fd_set *set, int max) {
+ int r, c;
+ char *ep;
+
+ if (vb2.buf[vb2.used++] != hm_squote[hm_squote) Psyntax("fd set start not [");
+ FD_ZERO(set);
+ for (;;) {
+ r= strtoul(vb2.buf+vb2.used,&ep,10);
+ if (r>=max) Psyntax("fd set member > max");
+ FD_SET(r,set);
+ vb2.used= ep - (char*)vb2.buf;
+ c= vb2.buf[vb2.used++];
+ if (c == hm_squote]hm_squote) break;
+ if (c != hm_squote,hm_squote) Psyntax("fd set separator not ,");
+ }
+}
+
+static void Paddr(struct sockaddr *addr, int *lenr) {
+ struct sockaddr_in *sa= (struct sockaddr_in*)addr;
+ char *p, *ep;
+ long ul;
+
+ assert(*lenr >= sizeof(*sa));
+ p= strchr(vb2.buf+vb2.used,':');
+ if (!p) Psyntax("no port on address");
+ *p++= 0;
+ memset(sa,0,sizeof(*sa));
+ sa->sin_family= AF_INET;
+ if (!inet_aton(vb2.buf+vb2.used,&sa->sin_addr)) Psyntax("invalid address");
+ ul= strtoul(p,&ep,10);
+ if (*ep && *ep != hm_squote hm_squote) Psyntax("invalid port (bad syntax)");
+ if (ul >= 65536) Psyntax("port too large");
+ sa->sin_port= htons(ul);
+ *lenr= sizeof(*sa);
+
+ vb2.used= ep - (char*)vb2.buf;
+}
+
+static int Pbytes(byte *buf, int maxlen) {
+ static const char hexdigits[]= "0123456789abcdef";
+
+ int c, v, done;
+ const char *pf;
+
+ done= 0;
+ for (;;) {
+ c= getc(Tinputfile); Pcheckinput();
+ if (c=='\n' || c==' ' || c=='\t') continue;
+ if (c=='.') break;
+ pf= strchr(hexdigits,c); if (!pf) Psyntax("invalid first hex digit");
+ v= (pf-hexdigits)<<4;
+ c= getc(Tinputfile); Pcheckinput();
+ pf= strchr(hexdigits,c); if (!pf) Psyntax("invalid second hex digit");
+ v |= (pf-hexdigits);
+ if (maxlen<=0) Psyntax("buffer overflow in bytes");
+ *buf++= v;
+ maxlen--; done++;
+ }
+ for (;;) {
+ c= getc(Tinputfile); Pcheckinput();
+ if (c=='\n') return done;
+ }
+}
+
+void Q_vb(void) {
+ int r;
+
+ Tensureinputfile();
+ if (!adns__vbuf_ensure(&vb2,vb.used+2)) Tnomem();
+ r= fread(vb2.buf,1,vb.used+2,Tinputfile);
+ if (feof(Tinputfile)) {
+ fprintf(stderr,"adns test harness: input ends prematurely; program did:\n %.*s\n",
+ vb.used,vb.buf);
+ exit(-1);
+ }
+ Pcheckinput();
+ if (vb2.buf[0] != hm_squote hm_squote) Psyntax("not space before call");
+ if (memcmp(vb.buf,vb2.buf+1,vb.used) ||
+ vb2.buf[vb.used+1] != hm_squote\nhm_squote) {
+ fprintf(stderr,
+ "adns test harness: program did unexpected:\n %.*s\n"
+ "was expecting:\n %.*s\n",
+ vb.used,vb.buf, vb.used,vb2.buf+1);
+ exit(1);
+ }
+}
+
+m4_define(`hm_syscall', `
+ hm_create_proto_h
+int H$1(hm_args_massage($3,void)) {
+ int r;
+ m4_define(`hm_rv_fd',`char *ep;')
+ m4_define(`hm_rv_any',`char *ep;')
+ m4_define(`hm_rv_len',`')
+ m4_define(`hm_rv_must',`')
+ m4_define(`hm_rv_succfail',`')
+ $2
+
+ hm_create_hqcall_vars
+ $3
+
+ hm_create_hqcall_init($1)
+ $3
+
+ hm_create_hqcall_args
+ Q$1(hm_args_massage($3));
+
+ m4_define(`hm_r_offset',`m4_len(` $1=')')
+ if (!adns__vbuf_ensure(&vb2,1000)) Tnomem();
+ fgets(vb2.buf,vb2.avail,Tinputfile); Pcheckinput();
+fprintf(stderr,"syscallr %s",vb2.buf);
+ vb2.avail= strlen(vb2.buf);
+ if (vb.avail<=0 || vb2.buf[--vb2.avail]!=hm_squote\nhm_squote)
+ Psyntax("badly formed line");
+ vb2.buf[vb2.avail]= 0;
+ if (memcmp(vb2.buf," $1=",hm_r_offset)) Psyntax("syscall reply mismatch");
+
+ if (vb2.buf[hm_r_offset] == hm_squoteEhm_squote) {
+ errno= Perrno(vb2.buf+hm_r_offset);
+ return -1;
+ }
+
+ m4_define(`hm_rv_succfail',`
+ if (memcmp(vb2.buf+hm_r_offset,"OK",2)) Psyntax("success/fail not E* or OK");
+ vb2.used= hm_r_offset+2;
+ r= 0;
+ ')
+ m4_define(`hm_rv_len',`hm_rv_succfail')
+ m4_define(`hm_rv_must',`hm_rv_succfail')
+ m4_define(`hm_rv_any',`
+ r= strtoul(vb2.buf+hm_r_offset,&ep,10);
+ if (*ep && *ep!=hm_squote hm_squote) Psyntax("return value not E* or positive number");
+ vb2.used= ep - (char*)vb2.buf;
+ ')
+ m4_define(`hm_rv_fd',`hm_rv_any')
+ $2
+
+ hm_create_nothing
+ m4_define(`hm_arg_fdset_io',`Parg("$'`1"); Pfdset($'`1,$'`2);')
+ m4_define(`hm_arg_addr_out',`Parg("$'`1"); Paddr($'`1,$'`2);')
+ m4_define(`hm_arg_timeval_out_abs',`Parg("$'`1"); Ptimevalabs($'`1);')
+ $3
+ if (vb2.used != vb2.avail) Psyntax("junk at end of line");
+
+ hm_create_nothing
+ m4_define(`hm_arg_bytes_out',`r= Pbytes($'`2,$'`4);')
+ $3
+
+ return r;
+}
+')
+
+m4_include(`hsyscalls.i4')
diff --git a/regress/hrecord.c.m4 b/regress/hrecord.c.m4
index 8dcf4cb..a1ac5ff 100644
--- a/regress/hrecord.c.m4
+++ b/regress/hrecord.c.m4
@@ -24,11 +24,23 @@ m4_include(hmacros.i4)
#include <string.h>
#include <fcntl.h>
#include <errno.h>
+#include <stdlib.h>
#include "harness.h"
static int begin_set;
static struct timeval begin;
+static FILE *Toutputfile;
+
+void Tensureoutputfile(void) {
+ const char *fdstr;
+ int fd;
+
+ Toutputfile= stdout;
+ fdstr= getenv("ADNS_TEST_OUT_FD"); if (!fdstr) return;
+ fd= atoi(fdstr);
+ Toutputfile= fdopen(fd,"a"); if (!Toutputfile) Tfailed("fdopen ADNS_TEST_OUT_FD");
+}
void Q_vb(void) {
if (!adns__vbuf_append(&vb,"",1)) Tnomem();
@@ -68,11 +80,11 @@ int H$1(hm_args_massage($3,void)) {
m4_define(`hm_rv_succfail',`
if (r) { Tvberrno(e); goto x_error; }
Tvba("OK");')
- m4_define(`hm_rv_must',`Tmust("$1","return",!r);')
+ m4_define(`hm_rv_must',`Tmust("$1","return",!r); Tvba("OK");')
m4_define(`hm_rv_len',`
if (r==-1) { Tvberrno(e); goto x_error; }
Tmust("$1","return",r<=$'`1);
- Tvbf("%d",r);')
+ Tvba("OK");')
$2
hm_create_nothing
diff --git a/src/Makefile b/src/Makefile
index 9934a61..57c208a 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -21,22 +21,23 @@ WARNS= -Wall -Wmissing-prototypes -Wwrite-strings -Wstrict-prototypes \
-Wcast-qual -Wpointer-arith
WERROR=-Werror
-HCPPFLAGS:= $(foreach F, \
- gettimeofday select \
- socket fcntl connect close \
- sendto recvfrom read write \
+HCPPFLAGS:= $(foreach F, \
+ gettimeofday select \
+ socket fcntl connect close \
+ sendto recvfrom read write writev \
, -D$F=H$F)
LIBOBJS= types.o event.o query.o reply.o general.o setup.o transmit.o parse.o
HARNLOBJS= $(addsuffix _d.o, $(basename $(LIBOBJS)))
ALLOBJS= $(LIBOBJS) $(HARNLOBJS) dtest.o hrecord.o hplayback.o hcommon.o
+AUTOCSRCS= harness.h hrecord.c hcommon.c
-TARGETS= dtest hrecord
-# hplayback
+TARGETS= dtest hplayback hrecord
all: $(TARGETS)
hrecord: dtest.o hrecord.o hcommon.o $(HARNLOBJS)
+hplayback: dtest.o hplayback.o hcommon.o $(HARNLOBJS)
dtest: dtest.o $(LIBOBJS)
@@ -48,8 +49,10 @@ dtest: dtest.o $(LIBOBJS)
sed -e 's/hm_comma/,/g; s/hm_squote/'\''/g; /^[ ]*$$/d' <$@-a.new >$@-b.new
@mv -f $@-b.new $@; rm -f $@-a.new
+.PRECIOUS: $(AUTOCSRCS)
+
clean:
- rm -f *.o harness.h hrecord.c hcommon.c
+ rm -f *.o
realclean: clean
rm -f $(TARGETS) *~ ./#*# core *.orig *.rej
diff --git a/src/Makefile.in b/src/Makefile.in
index 9934a61..57c208a 100644
--- a/src/Makefile.in
+++ b/src/Makefile.in
@@ -21,22 +21,23 @@ WARNS= -Wall -Wmissing-prototypes -Wwrite-strings -Wstrict-prototypes \
-Wcast-qual -Wpointer-arith
WERROR=-Werror
-HCPPFLAGS:= $(foreach F, \
- gettimeofday select \
- socket fcntl connect close \
- sendto recvfrom read write \
+HCPPFLAGS:= $(foreach F, \
+ gettimeofday select \
+ socket fcntl connect close \
+ sendto recvfrom read write writev \
, -D$F=H$F)
LIBOBJS= types.o event.o query.o reply.o general.o setup.o transmit.o parse.o
HARNLOBJS= $(addsuffix _d.o, $(basename $(LIBOBJS)))
ALLOBJS= $(LIBOBJS) $(HARNLOBJS) dtest.o hrecord.o hplayback.o hcommon.o
+AUTOCSRCS= harness.h hrecord.c hcommon.c
-TARGETS= dtest hrecord
-# hplayback
+TARGETS= dtest hplayback hrecord
all: $(TARGETS)
hrecord: dtest.o hrecord.o hcommon.o $(HARNLOBJS)
+hplayback: dtest.o hplayback.o hcommon.o $(HARNLOBJS)
dtest: dtest.o $(LIBOBJS)
@@ -48,8 +49,10 @@ dtest: dtest.o $(LIBOBJS)
sed -e 's/hm_comma/,/g; s/hm_squote/'\''/g; /^[ ]*$$/d' <$@-a.new >$@-b.new
@mv -f $@-b.new $@; rm -f $@-a.new
+.PRECIOUS: $(AUTOCSRCS)
+
clean:
- rm -f *.o harness.h hrecord.c hcommon.c
+ rm -f *.o
realclean: clean
rm -f $(TARGETS) *~ ./#*# core *.orig *.rej