chiark / gitweb /
First record and playback works.
authorian <ian>
Sun, 29 Nov 1998 17:52:32 +0000 (17:52 +0000)
committerian <ian>
Sun, 29 Nov 1998 17:52:32 +0000 (17:52 +0000)
regress/.cvsignore
regress/harness.h.m4
regress/hcommon.c.m4
regress/hmacros.i4
regress/hplayback.c.m4 [new file with mode: 0644]
regress/hrecord.c.m4
src/Makefile
src/Makefile.in

index 70857af..2b26f2c 100644 (file)
@@ -1,5 +1,7 @@
 dtest
-hrecord
 harness.h
 hcommon.c
+hrecord
 hrecord.c
+hplayback
+hplayback.c
index 7b5758e..5f0c9f4 100644 (file)
@@ -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
index 4c1af7c..5d6f471 100644 (file)
@@ -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;
-}
index ebbd682..4e5123e 100644 (file)
@@ -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 (file)
index 0000000..5431c26
--- /dev/null
@@ -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')
index 8dcf4cb..a1ac5ff 100644 (file)
@@ -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
index 9934a61..57c208a 100644 (file)
@@ -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
index 9934a61..57c208a 100644 (file)
@@ -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