diff options
author | Yorhel <git@yorhel.nl> | 2012-11-10 15:44:04 +0100 |
---|---|---|
committer | Yorhel <git@yorhel.nl> | 2012-11-10 15:44:04 +0100 |
commit | 23c0b118800623174cbbef73a9ea43a574dded09 (patch) | |
tree | e3e44964c361c1c828d3b339295bb0bf05102c4d | |
parent | d0618b33d654c714c620cc6a8849594c1adf6706 (diff) |
Added test suite for ecbuf
-rw-r--r-- | test/Makefile | 10 | ||||
-rw-r--r-- | test/ecbuf.c | 181 |
2 files changed, 188 insertions, 3 deletions
diff --git a/test/Makefile b/test/Makefile index 4e26f9c..e9ff3ce 100644 --- a/test/Makefile +++ b/test/Makefile @@ -1,5 +1,5 @@ CC:=gcc -CFLAGS:=-Wall -Wextra -Wno-unused-parameter -O0 +CFLAGS:=-Wall -Wextra -Wno-unused-parameter -O0 -g .PHONY: all test clean @@ -8,9 +8,13 @@ all: test yuri: ../yuri.c ../yuri.h yuri.c $(CC) $(CFLAGS) -I.. yuri.c -o yuri -test: yuri +ecbuf: ../ecbuf.h ecbuf.c + $(CC) $(CFLAGS) -I.. ecbuf.c -o ecbuf + +test: yuri ecbuf ./yuri + ./ecbuf @echo All tests passed. clean: - rm -f yuri + rm -f yuri ecbuf diff --git a/test/ecbuf.c b/test/ecbuf.c new file mode 100644 index 0000000..dba0117 --- /dev/null +++ b/test/ecbuf.c @@ -0,0 +1,181 @@ +/* Copyright (c) 2012 Yoran Heling + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +#ifdef NDEBUG +#error These tests should not be compiled with -DNDEBUG! +#endif + + +#if 1 /* Select between ecbuf.h and another implementation */ +#include "ecbuf.h" + + +/* This is the original implementation provided in the article (converted to C, + * obviously). Provided here for testing, but doesn't have a _pry(). */ +#else + +#define ecbuf_t(type) struct {\ + int buflen, ringlen, bufcap, ringcap, pushi, popi;\ + type *a;\ + } +typedef ecbuf_t(void) ecbuf__t; +#define ecbuf_init(v) do {\ + (v).bufcap = (v).ringcap = 32;\ + (v).buflen = (v).ringlen = (v).pushi = (v).popi = 0;\ + (v).a = malloc((v).bufcap*sizeof(*(v).a));\ + } while(0) +#define ecbuf_destroy(v) free((v).a) +#define ecbuf_len(v) ((v).buflen) +#define ecbuf_empty(v) ((v).buflen == 0) +#define ecbuf_peek(v) ((v).a[(v).popi]) +#define ecbuf_pry(v) /* Doesn't work */ +#define ecbuf_push(v, x) do {\ + int expandbuf = 0, expandring = 0;\ + if((v).ringcap != (v).bufcap) {\ + expandbuf = (v).pushi == 0;\ + expandring = 0;\ + } else if((v).ringcap == (v).ringlen) {\ + expandbuf = 1;\ + expandring = (v).pushi == 0;\ + } else\ + expandbuf = expandring = 0;\ + if(expandbuf) {\ + (v).pushi = (v).bufcap;\ + (v).bufcap <<= 1;\ + (v).a = realloc((v).a, (v).bufcap*sizeof(*(v).a));\ + if(expandring)\ + (v).ringcap = (v).bufcap;\ + }\ + (v).a[(v).pushi] = (x);\ + (v).buflen++;\ + if((v).pushi < (v).ringcap)\ + (v).ringlen++;\ + (v).pushi = ((v).pushi + 1) % (v).bufcap;\ + } while(0) +static inline int ecbuf__pop(ecbuf__t *v) { + int l = v->popi; + v->buflen--; + v->ringlen--; + if(v->ringlen == 0 && v->buflen != 0) { + v->popi = v->ringcap; + v->ringlen = v->buflen; + v->ringcap = v->bufcap; + } else + v->popi = (v->popi + 1) % v->ringcap; + return l; +} +#define ecbuf_pop(v) ((v).a[ecbuf__pop((ecbuf__t *)&(v))]) +#endif + + +#include <assert.h> +#include <string.h> +#include <stdio.h> + + +int main(int argc, char **argv) { + ecbuf_t(int) lst; + int i, j, r, w; + + /* Handy debugging function: + printf("i = %d, li = %d, o = %d, b = %d, cm = %d, bm = %d\n", lst.i, lst.li, lst.o, lst.b, lst.cm, lst.bm); + */ + + ecbuf_init(lst); + for(i=0; i<100; i++) { + assert(ecbuf_empty(lst)); + assert(ecbuf_len(lst) == 0); + ecbuf_push(lst, i); + assert(ecbuf_len(lst) == 1); + assert(ecbuf_pop(lst) == i); + assert(ecbuf_empty(lst)); + assert(ecbuf_len(lst) == 0); + } + ecbuf_destroy(lst); + + ecbuf_init(lst); + assert(ecbuf_empty(lst)); + for(i=0; i<100; i++) { + ecbuf_push(lst, i); + assert(!ecbuf_empty(lst)); + assert(ecbuf_len(lst) == i+1); + } + for(i=0; i<100; i++) { + assert(!ecbuf_empty(lst)); + assert(ecbuf_pop(lst) == i); + assert(ecbuf_len(lst) == 99-i); + } + assert(ecbuf_empty(lst)); + ecbuf_destroy(lst); + + ecbuf_init(lst); + for(i=0; i<29; i++) { + for(j=0; j<10; j++) + ecbuf_push(lst, (i<<16) + j); + for(j=0; j<10; j++) + assert(ecbuf_pop(lst) == (i<<16) + j); + } + ecbuf_destroy(lst); + + ecbuf_init(lst); + for(i=0; i<31; i++) + ecbuf_push(lst, i); + assert(ecbuf_len(lst) == 31); /* [0..30] */ + for(i=0; i<10; i++) + assert(ecbuf_pop(lst) == i); + assert(ecbuf_len(lst) == 21); /* [10..30] */ + for(i=0; i<20; i++) + ecbuf_push(lst, 1000+i); + assert(ecbuf_len(lst) == 21+20); /* [10..30, 1000..1019] */ + for(i=10; i<31; i++) + assert(ecbuf_pop(lst) == i); + assert(ecbuf_len(lst) == 20); /* [1000..1019] */ + for(i=0; i<20; i++) + assert(ecbuf_pop(lst) == 1000+i); + assert(ecbuf_len(lst) == 0); /* [] */ + ecbuf_destroy(lst); + + ecbuf_init(lst); + r = w = 0; + for(i=0; i<100; i++) { + for(j=0; j<100; j++) { + ecbuf_push(lst, w); + assert(ecbuf_pry(lst) == w++); + assert(ecbuf_len(lst) == w-r); + } + for(j=0; j<99; j++) { + assert(ecbuf_len(lst) == w-r); + assert(ecbuf_peek(lst) == r); + assert(ecbuf_pop(lst) == r++); + } + } + assert(ecbuf_len(lst) == 100); + for(i=0; i<100; i++) + assert(ecbuf_pop(lst) == r++); + assert(ecbuf_empty(lst)); + ecbuf_destroy(lst); + + memset(&lst, 0, sizeof(lst)); /* Let valgrind detect a leak */ + return 0; +} + +/* vim: set noet sw=4 ts=4: */ |