From 58f7dbc0658b3d73816a1bc91b75c2bdac733510 Mon Sep 17 00:00:00 2001 From: Sergey Poznyakoff Date: Sun, 13 Oct 2013 13:39:50 +0300 Subject: Fix error checking, add pack tests. * src/binlog.c (vmod_init): Fix error checking after packcomp. * src/binlogcat.c (catlog): Likewise. * tests/binpack.c (main): Likewise. * src/pack.c (Z_unpacker): Fix output format. (packcomp): allow for whitespace between specifiers. On error set errno and return NULL. * tests/Makefile.am: Add pack.at * tests/testsuite.at: Likewise. * tests/pack.at: New file. * tests/test02.at: Fix name pattern. --- src/binlog.c | 8 +++++--- src/binlogcat.c | 11 ++++++++--- src/pack.c | 30 +++++++++++++++++++++++------- tests/Makefile.am | 1 + tests/binpack.c | 13 ++++++++----- tests/pack.at | 47 +++++++++++++++++++++++++++++++++++++++++++++++ tests/test02.at | 2 +- tests/testsuite.at | 2 ++ 8 files changed, 95 insertions(+), 19 deletions(-) create mode 100644 tests/pack.at diff --git a/src/binlog.c b/src/binlog.c index 7e88817..765b945 100644 --- a/src/binlog.c +++ b/src/binlog.c @@ -220,9 +220,11 @@ vmod_init(struct sess *sp, struct vmod_priv *priv, AN(conf->dir); conf->inst_head = packcomp(dataspec, &p); - AN(conf->inst_head); - if (*p) { - binlog_error("cannot compile data format near %s", p); + if (!conf->inst_head) { + if (errno == EINVAL) + binlog_error("cannot compile data format near %s", p); + else + binlog_error("%s", strerror(errno)); abort(); } conf->recsize = packsize(conf->inst_head); diff --git a/src/binlogcat.c b/src/binlogcat.c index bdeb992..505bbc2 100644 --- a/src/binlogcat.c +++ b/src/binlogcat.c @@ -92,8 +92,13 @@ catlog(const char *fname) fname, dataspec, header.recsize, header.recnum); inst = packcomp(dataspec, &p); - if (*p) { - error("%s: bad dataspec near %s", dataspec, p); + if (!inst) { + if (errno == EINVAL) { + error("%s: bad dataspec near %s", dataspec, p); + exit(1); + } + + error("%s", strerror(errno)); exit(1); } free(dataspec); @@ -101,7 +106,7 @@ catlog(const char *fname) rec = malloc(header.recsize); if (!rec) { error("not enough memory"); - abort(); + exit(1); } env = packenv_create(header.recsize - offsetof(struct binlog_record,data)); diff --git a/src/pack.c b/src/pack.c index 9c22932..82fc0f9 100644 --- a/src/pack.c +++ b/src/pack.c @@ -35,7 +35,6 @@ null padded. This letter must be followed by repeat count. c A signed char (8-bit) value. - C An unsigned char (octet) value. s A signed short (16-bit) value. S An unsigned short value. @@ -221,7 +220,7 @@ Z_packer(struct packenv *env, int rep) static void Z_unpacker(struct packenv *env, int rep) { - fprintf(env->fp, "%-*.*s", rep, rep, env->buf_base + env->buf_pos); + fprintf(env->fp, "%-*.*s", rep-1, rep-1, env->buf_base + env->buf_pos); env->buf_pos += rep; } @@ -672,18 +671,30 @@ packcomp(const char *s, char **endp) struct packinst *head = NULL, *tail = NULL, *pi; struct packspec *ps; int rep; + int ec = 0; - while (s) { + errno = 0; + while (*s) { + if (isspace(*s)) { + ++s; + continue; + } for (ps = packspec; ps->ch; ps++) if (ps->ch == *s) break; - if (!ps->ch) + if (!ps->ch) { + ec = EINVAL; break; - if (getrep(s + 1, &s, &rep)) + } + if (getrep(s + 1, &s, &rep)) { + ec = EINVAL; break; + } pi = malloc(sizeof(*pi)); - if (!pi) - return NULL; + if (!pi) { + ec = ENOMEM; + break; + } pi->next = NULL; pi->spec = ps; pi->rep = rep; @@ -693,6 +704,11 @@ packcomp(const char *s, char **endp) head = pi; tail = pi; } + if (ec) { + packfree(head); + head = NULL; + errno = ec; + } if (endp) *endp = (char*) s; return head; diff --git a/tests/Makefile.am b/tests/Makefile.am index 4e3bc7b..f8f92d6 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -40,6 +40,7 @@ $(srcdir)/package.m4: $(top_srcdir)/configure.ac ## ------------ ## TESTSUITE_AT = \ + pack.at\ test01.at\ test02.at\ testsuite.at diff --git a/tests/binpack.c b/tests/binpack.c index b54ed80..482e658 100644 --- a/tests/binpack.c +++ b/tests/binpack.c @@ -18,6 +18,8 @@ #include #include #include +#include +#include #include "pack.h" #include "err.h" @@ -52,11 +54,12 @@ main(int argc, char **argv) pi = packcomp(argv[0], &end); if (!pi) { - error("out of memory"); - abort(); - } - if (*end) { - error("compile error near %s", end); + if (errno == EINVAL) { + error("%s: bad dataspec near %s", argv[0], end); + exit(1); + } + + error("%s", strerror(errno)); exit(1); } env = packenv_create(packsize(pi)); diff --git a/tests/pack.at b/tests/pack.at new file mode 100644 index 0000000..0baf8e6 --- /dev/null +++ b/tests/pack.at @@ -0,0 +1,47 @@ +# This file is part of vmod-binlog testsuite -*- autotest -*- +# Copyright (C) 2013 Sergey Poznyakoff +# +# Vmod-binlog is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# Vmod-binlog is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with vmod-binlog. If not, see . + +m4_dnl TESTPACK(conv, args [, out]) +m4_define([TESTPACK], +[AT_SETUP($1) +AT_KEYWORDS([pack $1]) +AT_CHECK([binpack -- $1 $2 | binpack -d -- $1 | sed 's/ /_/g'],[0], +[m4_if([$3],,[m4_bpatsubst([$2],[ ],[_]) +],[$3 +])]) +AT_CLEANUP]) + +AT_BANNER(Pack conversions) + +TESTPACK(Z20, text, text_______________) +TESTPACK(c, A) +TESTPACK(s, 115) +TESTPACK(S, 115) +TESTPACK(l, 137) +TESTPACK(L, 137) +TESTPACK(q, 137) +TESTPACK(Q, 137) +TESTPACK(i, 137) +TESTPACK(i, -137) +TESTPACK(I, 137) +TESTPACK(n, 143) +TESTPACK(N, 2130706433) +TESTPACK(v, 143) +TESTPACK(V, 2130706433) +#TESTPACK(f, 1.456) +#TESTPACK(d, 1.456) +TESTPACK(L2, [24 67], 24_67) +TESTPACK(lZ5l2, [137 text -568 1025]) diff --git a/tests/test02.at b/tests/test02.at index 459a3cc..f1520a8 100644 --- a/tests/test02.at +++ b/tests/test02.at @@ -32,7 +32,7 @@ server s1 { varnish v1 -vcl+backend { import binlog from "$abs_top_builddir/src/.libs/libvmod_binlog.so"; sub vcl_init { - binlog.init("$cwd/log","LL","size=1M;interval=10;roundts=1;pattern=%S.log"); + binlog.init("$cwd/log","LL","size=1M;interval=10;roundts=1;pattern=%s.log"); } sub vcl_fini { binlog.close(); diff --git a/tests/testsuite.at b/tests/testsuite.at index 4f8b786..27a1647 100644 --- a/tests/testsuite.at +++ b/tests/testsuite.at @@ -19,6 +19,8 @@ m4_version_prereq([2.52g]) m4_define([AT_SKIP_TEST],[exit 77]) AT_INIT +m4_include([pack.at]) +AT_BANNER(Varnish) m4_include([test01.at]) m4_include([test02.at]) -- cgit v1.2.1