summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYorhel <git@yorhel.nl>2012-11-10 15:44:04 +0100
committerYorhel <git@yorhel.nl>2012-11-10 15:44:04 +0100
commit23c0b118800623174cbbef73a9ea43a574dded09 (patch)
treee3e44964c361c1c828d3b339295bb0bf05102c4d
parentd0618b33d654c714c620cc6a8849594c1adf6706 (diff)
Added test suite for ecbuf
-rw-r--r--test/Makefile10
-rw-r--r--test/ecbuf.c181
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: */