Commit 10733b0d authored by Geoff Simmons's avatar Geoff Simmons

check in the test code (forgot), expand test for DATA_Init, and add

tests for freelist take for records and chunks
parent 56e3c543
......@@ -92,7 +92,7 @@ DATA_Clear_Logline(tx_t *tx)
int
DATA_Init(void)
{
int bufidx = 0, nrecords, nchunks, chunks_per_rec;
int bufidx = 0, chunks_per_rec;
#if 0
lines_per_tx = FMT_Get_LinesPerTx();
......@@ -166,6 +166,8 @@ DATA_Init(void)
data_open = data_done = data_occ_hi = 0;
global_nfree_tx = config.max_data;
global_nfree_line = nrecords;
global_nfree_chunk = nchunks;
atexit(data_Cleanup);
......
/*-
* Copyright (c) 2012 UPLEX Nils Goroll Systemoptimierung
* Copyright (c) 2012 Otto Gmbh & Co KG
* All rights reserved
* Use only with permission
*
* Author: Geoffrey Simmons <geoffrey.simmons@uplex.de>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
*/
#ifndef _MINUNIT_INCLUDED
#define _MINUNIT_INCLUDED
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
/*-
* Adapted from http://www.jera.com/techinfo/jtns/jtn002.html
* "MinUnit" - a minimal unit testing framework for C
*
* "You may use the code in this tech note for any purpose, with the
* understanding that it comes with NO WARRANTY."
*/
#define mu_assert(msg, test) do { if (!(test)) return msg; } while (0)
#define mu_run_test(test) do { const char *msg = test(); tests_run++; \
if (msg) return msg; } while (0)
char _mu_errmsg[BUFSIZ];
#define _massert(test, msg, ...) \
do { \
if (!(test)) { \
sprintf(_mu_errmsg, (msg), __VA_ARGS__); \
return (_mu_errmsg); \
} \
} while(0)
#define _massert0(test, msg) \
do { \
if (!(test)) { \
sprintf(_mu_errmsg, (msg)); \
return (_mu_errmsg); \
} \
} while(0)
#define VMASSERT(test, msg, ...) _massert((test),(msg),__VA_ARGS__)
#define MASSERT0(test, msg) _massert0((test),(msg))
#define MASSERT(c) \
VMASSERT((c), "%s failed in %s at %s:%d (errno %d: %s)", \
#c, __func__, __FILE__, __LINE__, errno, strerror(errno))
/* short for MU Assert Zero / Non-Zero */
#define MAZ(c) MASSERT((c) == 0)
#define MAN(c) MASSERT((c) != 0)
#define MCHECK_OBJ(ptr, type_magic) MASSERT((ptr)->magic == type_magic)
#define MCHECK_OBJ_NOTNULL(ptr, type_magic) \
do { \
MAN(ptr); \
MCHECK_OBJ(ptr, type_magic); \
} while(0)
extern int tests_run;
#define TEST_RUNNER \
int \
main(int argc, char **argv) \
{ \
(void) argc; \
\
printf("\nTEST: %s\n", argv[0]); \
const char *result = all_tests(); \
printf("%s: %d tests run\n", argv[0], tests_run); \
if (result != NULL) { \
printf("%s\n", result); \
exit(EXIT_FAILURE); \
} \
exit(EXIT_SUCCESS); \
}
#endif
/*-
* Copyright (c) 2015 UPLEX Nils Goroll Systemoptimierung
* Copyright (c) 2015 Otto Gmbh & Co KG
* All rights reserved
* Use only with permission
*
* Author: Geoffrey Simmons <geoffrey.simmons@uplex.de>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
*/
#include <string.h>
#include "minunit.h"
#include "../varnishevent.h"
int tests_run = 0;
static txhead_t local_freetx = VSTAILQ_HEAD_INITIALIZER(local_freetx);
static linehead_t local_freeline = VSTAILQ_HEAD_INITIALIZER(local_freeline);
static chunkhead_t local_freechunk = VSTAILQ_HEAD_INITIALIZER(local_freechunk);
/* N.B.: Always run this test first */
static char
*test_data_init(void)
{
int err;
printf("... testing data table initialization\n");
MAZ(LOG_Open("test_data"));
CONF_Init();
#if 0
MAZ(FMT_Init(fmterr));
#endif
VMASSERT((err = DATA_Init()) == 0, "DATA_Init: %s", strerror(err));
MAN(txn);
for (int i = 0; i < config.max_data; i++) {
MCHECK_OBJ(&txn[i], TX_MAGIC);
MASSERT(txn[i].state == TX_EMPTY);
MASSERT(txn[i].vxid == -1);
MASSERT(txn[i].type == VSL_t_unknown);
#if 0
MAZ(txn[i].t);
#endif
MASSERT(VSTAILQ_EMPTY(&txn[i].lines));
}
MASSERT(global_nfree_tx == config.max_data);
for (int i = 0; i < nrecords; i++) {
MCHECK_OBJ(&lines[i], LOGLINE_MAGIC);
MASSERT(lines[i].state == DATA_EMPTY);
MASSERT(lines[i].tag == SLT__Bogus);
MASSERT(lines[i].len == 0);
MASSERT(VSTAILQ_EMPTY(&lines[i].chunks));
}
MASSERT(global_nfree_line == nrecords);
for (int i = 0; i < nchunks; i++) {
MCHECK_OBJ(&chunks[i], CHUNK_MAGIC);
MASSERT(chunks[i].state == DATA_EMPTY);
MASSERT(chunks[i].data == (chunks[0].data + (i * config.chunk_size)));
}
MASSERT(global_nfree_chunk == nchunks);
return NULL;
}
static const char
*test_data_take_tx(void)
{
unsigned nfree, cfree = 0;
tx_t *tx;
printf("... testing tx freelist take\n");
nfree = DATA_Take_Freetx(&local_freetx);
MASSERT(nfree == config.max_data);
MASSERT(!VSTAILQ_EMPTY(&local_freetx));
VSTAILQ_FOREACH(tx, &local_freetx, freelist) {
MCHECK_OBJ_NOTNULL(tx, TX_MAGIC);
cfree++;
}
MAZ(global_nfree_tx);
MASSERT(nfree == cfree);
return NULL;
}
static const char
*test_data_take_rec(void)
{
unsigned nfree, cfree = 0;
logline_t *rec;
printf("... testing record freelist take\n");
nfree = DATA_Take_Freeline(&local_freeline);
MAZ(global_nfree_line);
MASSERT(nfree == nrecords);
MASSERT(!VSTAILQ_EMPTY(&local_freeline));
VSTAILQ_FOREACH(rec, &local_freeline, freelist) {
MCHECK_OBJ_NOTNULL(rec, LOGLINE_MAGIC);
cfree++;
}
MASSERT(nfree == cfree);
return NULL;
}
static const char
*test_data_take_chunks(void)
{
unsigned nfree, cfree = 0;
chunk_t *chunk;
printf("... testing chunk freelist take\n");
nfree = DATA_Take_Freechunk(&local_freechunk);
MAZ(global_nfree_chunk);
MASSERT(nfree == nchunks);
MASSERT(!VSTAILQ_EMPTY(&local_freechunk));
VSTAILQ_FOREACH(chunk, &local_freechunk, freelist) {
MCHECK_OBJ_NOTNULL(chunk, CHUNK_MAGIC);
cfree++;
}
MASSERT(nfree == cfree);
return NULL;
}
#if 0
static const char
*test_data_return(void)
{
logline_t *ll;
printf("... testing freelist return\n");
DATA_Return_Freelist(&local_freehead, config.max_data);
MASSERT(VSTAILQ_EMPTY(&local_freehead));
MASSERT(global_nfree == config.max_data);
MASSERT(!VSTAILQ_EMPTY(&freehead));
VSTAILQ_FOREACH(ll, &freehead, freelist)
MCHECK_OBJ_NOTNULL(ll, LOGLINE_MAGIC);
return NULL;
}
#endif
static const char
*all_tests(void)
{
mu_run_test(test_data_init);
mu_run_test(test_data_take_tx);
mu_run_test(test_data_take_rec);
mu_run_test(test_data_take_chunks);
#if 0
mu_run_test(test_data_return);
#endif
return NULL;
}
TEST_RUNNER
/*-
* Copyright (c) 2012 UPLEX Nils Goroll Systemoptimierung
* Copyright (c) 2012 Otto Gmbh & Co KG
* All rights reserved
* Use only with permission
*
* Author: Geoffrey Simmons <geoffrey.simmons@uplex.de>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
*/
#include <time.h>
#include <stdio.h>
#include <string.h>
#include <assert.h>
#include "minunit.h"
#include "../strfTIM.h"
int tests_run = 0;
static char errmsg[BUFSIZ];
static char
*test_strfTIM_strftime(void)
{
time_t now;
struct tm *tm;
char strftime_s[BUFSIZ], strfTIM_s[BUFSIZ];
const char *fmt =
"%a %A %b %B %c %C %d %D %e %F %g %G %h %H %I %J %m %M %n %p %r %R %S "\
"%t %T %u %U %V %w %W %x %X %y %Y %z %Z %% %Ec %EC %Ex %EX %Ey %Ey "\
"%Od %Oe %OH %OI %Om %OM %OS %Ou %OU %OV %Ow %OW %Oy";
size_t strftime_n, strfTIM_n;
printf("... testing strfTIM equivalence to strftime\n");
time(&now);
tm = localtime(&now);
assert(tm != NULL);
strftime_n = strftime(strftime_s, BUFSIZ, fmt, tm);
strfTIM_n = strfTIM(strfTIM_s, BUFSIZ, fmt, tm, 0);
sprintf(errmsg, "strfTIM incorrect return value %zu (expected %zu)",
strfTIM_n, strftime_n);
mu_assert(errmsg, strfTIM_n == strftime_n);
sprintf(errmsg, "strfTIM incorrect result '%s' (expected '%s')", strfTIM_s,
strftime_s);
mu_assert(errmsg, strcmp(strfTIM_s, strftime_s) == 0);
return NULL;
}
static char
*test_strfTIM_N(void)
{
size_t n;
time_t t = 1382804827;
long nsec = 112625579;
const char *exp = "2013-10-26-18:27:07.112625579";
char s[BUFSIZ];
struct tm *tm;
printf("... testing strfTIM %%N conversion specifier\n");
tm = localtime(&t);
assert(tm != NULL);
n = strfTIM(s, BUFSIZ, "%F-%T.%N", tm, nsec);
sprintf(errmsg, "strfTIM incorrect return value %zu (expected %zu)", n,
strlen(exp));
mu_assert(errmsg, n == strlen(exp));
sprintf(errmsg, "strfTIM incorrect result '%s' (expected '%s')", s, exp);
mu_assert(errmsg, strcmp(s, exp) == 0);
n = strfTIM(s, BUFSIZ, "%%N", tm, nsec);
sprintf(errmsg, "strfTIM incorrect return value %zu (expected %zu)", n,
strlen("%N"));
mu_assert(errmsg, n == strlen("%N"));
sprintf(errmsg, "strfTIM incorrect result '%s' (expected '%s')", s, "%N");
mu_assert(errmsg, strcmp(s, "%N") == 0);
n = strfTIM(s, BUFSIZ, "%%%N", tm, nsec);
sprintf(errmsg, "strfTIM incorrect return value %zu (expected %zu)", n,
strlen("%112625579"));
mu_assert(errmsg, n == strlen("%112625579"));
sprintf(errmsg, "strfTIM incorrect result '%s' (expected '%s')", s,
"%112625579");
mu_assert(errmsg, strcmp(s, "%112625579") == 0);
return NULL;
}
static char
*test_strfTIMlocal(void)
{
size_t n;
char s[BUFSIZ], exp[BUFSIZ];
printf("... testing strfTIMlocal\n");
n = strfTIMlocal(s, BUFSIZ, "%F-%T.%N", 1382804820.112625579);
sprintf(exp, "2013-10-26-18:27:0%.9f", 0.112625579);
sprintf(errmsg, "strfTIMlocal incorrect return value %zu (expected %zu)",
n, strlen(exp));
mu_assert(errmsg, n == strlen(exp));
/*
* Don't require equality into the nanosecond range, because that gets
* us into floating point precision issues. Just require equality in
* the µsec range, by terminating the result string after six decimal
* places.
*/
s[strlen(s) - 3] = '\0';
exp[strlen(exp) - 3] = '\0';
sprintf(errmsg, "strfTIMlocal incorrect result '%s' (expected '%s')", s,
exp);
mu_assert(errmsg, strcmp(s, exp) == 0);
return NULL;
}
static char
*test_strfTIMgm(void)
{
size_t n;
char s[BUFSIZ], exp[BUFSIZ];
printf("... testing strfTIMgm\n");
n = strfTIMgm(s, BUFSIZ, "%F-%T.%N", 1382804820.112625579);
sprintf(exp, "2013-10-26-16:27:0%.9f", 0.112625579);
sprintf(errmsg, "strfTIMgm incorrect return value %zu (expected %zu)",
n, strlen(exp));
mu_assert(errmsg, n == strlen(exp));
/* As above */
s[strlen(s) - 3] = '\0';
exp[strlen(exp) - 3] = '\0';
sprintf(errmsg, "strfTIMgm incorrect result '%s' (expected '%s')", s, exp);
mu_assert(errmsg, strcmp(s, exp) == 0);
return NULL;
}
static const char
*all_tests(void)
{
mu_run_test(test_strfTIM_strftime);
mu_run_test(test_strfTIM_N);
mu_run_test(test_strfTIMlocal);
mu_run_test(test_strfTIMgm);
return NULL;
}
TEST_RUNNER
......@@ -233,10 +233,10 @@ static inline tx_t
}
static inline void
take_chunks(linehead_t *lineh, unsigned nchunks)
take_chunks(linehead_t *lineh, unsigned _nchunks)
{
(void) lineh;
(void) nchunks;
(void) _nchunks;
}
static inline void
......@@ -332,10 +332,10 @@ event(struct VSL_data *_vsl, struct VSL_transaction * const pt[], void *priv)
/* Copy the payload into chunks */
assert(VSTAILQ_EMPTY(&line->chunks));
int nchunks = (len + config.chunk_size - 1) / config.chunk_size;
if (nchunks > 1)
int nchunk = (len + config.chunk_size - 1) / config.chunk_size;
if (nchunk > 1)
/* XXX: increment counter */
take_chunks(&tx->lines, nchunks);
take_chunks(&tx->lines, nchunk);
int n = len;
chunk_t *chunk = VSTAILQ_FIRST(&line->chunks);
......
......@@ -100,6 +100,7 @@ typedef struct chunk_t {
typedef VSTAILQ_HEAD(chunkhead_s, chunk_t) chunkhead_t;
chunk_t *chunks;
unsigned nchunks;
typedef struct logline_t {
unsigned magic;
......@@ -113,6 +114,7 @@ typedef struct logline_t {
} logline_t;
logline_t *lines;
unsigned nrecords;
typedef VSTAILQ_HEAD(linehead_s, logline_t) linehead_t;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment