From 4b5c5ed66ac35f50b6c172a712883acb5f0cc62f Mon Sep 17 00:00:00 2001 From: "Serge A. Zaitsev" Date: Wed, 1 Feb 2012 12:38:51 +0200 Subject: [PATCH] switched to C unit-tests instead of bash --- Makefile | 11 ++-- demo.c | 141 ---------------------------------------------------- jsmn_test.c | 57 +++++++++++++++++++++ test.sh | 134 ------------------------------------------------- 4 files changed, 64 insertions(+), 279 deletions(-) delete mode 100644 demo.c create mode 100644 jsmn_test.c delete mode 100644 test.sh diff --git a/Makefile b/Makefile index 35b7ac6..bb9337a 100644 --- a/Makefile +++ b/Makefile @@ -3,8 +3,8 @@ all: libjsmn.a -demo: libjsmn.a demo.o - $(CC) $(LDFLAGS) demo.o -L. -ljsmn -o $@ +#demo: libjsmn.a demo.o +# $(CC) $(LDFLAGS) demo.o -L. -ljsmn -o $@ libjsmn.a: jsmn.o $(AR) rc $@ $^ @@ -12,8 +12,11 @@ libjsmn.a: jsmn.o %.o: %.c jsmn.h $(CC) -c $(CFLAGS) $< -o $@ -test: all demo - sh test.sh +test: jsmn_test + ./jsmn_test + +jsmn_test: jsmn_test.o + $(CC) -L. -ljsmn $< -o $@ clean: rm -f jsmn.o demo.o diff --git a/demo.c b/demo.c deleted file mode 100644 index 1f6cac7..0000000 --- a/demo.c +++ /dev/null @@ -1,141 +0,0 @@ -/* This demo is not needed to be C89-compatible, so for now GCC extensions are - * used */ -#define _GNU_SOURCE - -#include -#include -#include -#include -#include -#include - -#include "jsmn.h" - -static void jsmn_dump_obj(jsmntok_t *obj, const char *js) { - size_t len; - char *s; - - if (obj->end < 0 || obj->start < 0) { - return; - } - - len = obj->end - obj->start; - - printf("[%3d,%3d - %2d] (%c) ", obj->start, obj->end, obj->size, - ({ - char c; - switch (obj->type) { - case JSMN_PRIMITIVE: c = '.'; break; - case JSMN_STRING: c = 's'; break; - case JSMN_ARRAY: c = 'A'; break; - case JSMN_OBJECT: c = 'O'; break; - default: c = '?'; - }; c; - })); - - s = strndup((const char *) &js[obj->start], len); - char *p; - for (p = s; *p; p++) { - printf("%c", *p == '\n' ? ' ' : *p); - } - printf("\n"); - free(s); -} - -void usage(void) { - fprintf(stderr, "Usage: ./demo \n"); - exit(EXIT_SUCCESS); -} - -int main(int argc, char *argv[]) { - int i; - int r; - int c; - - FILE *f; - int filesize = 0; - - jsmn_parser parser; - char *js = NULL; - jsmntok_t *tokens; - int block_size = 1024; - int num_tokens = 100; - - while ((c = getopt(argc, argv, "ht:b:")) != -1) { - switch (c) { - case 'h': - usage(); - break; - case 't': - num_tokens = atoi(optarg); - if (errno || num_tokens < 0) { - fprintf(stderr, "Invalid token number: %s!\n", optarg); - exit(EXIT_FAILURE); - } - break; - case 'b': - block_size = atoi(optarg); - if (errno || block_size < 0) { - fprintf(stderr, "Invalid block size: %s!\n", optarg); - exit(EXIT_FAILURE); - } - } - } - - if (optind >= argc) { - usage(); - } - - if (strcmp(argv[optind], "-") == 0) { - f = stdin; - } else { - f = fopen(argv[optind], "r"); - if (f == NULL) { - fprintf(stderr, "Failed to open file `%s`\n", argv[1]); - exit(EXIT_FAILURE); - } - } - - tokens = malloc(num_tokens * sizeof(jsmntok_t)); - if (tokens == NULL) { - fprintf(stderr, "Cannot allocate anough memory\n"); - exit(EXIT_FAILURE); - } - - jsmn_init_parser(&parser, js, tokens, num_tokens); - - char *buf = malloc(block_size); - while (1) { - r = fread(buf, 1, block_size, f); - if (r <= 0) { - break; - } - js = (char *) realloc(js, filesize + r + 1); - if (js == NULL) { - fprintf(stderr, "Cannot allocate anough memory\n"); - fclose(f); - exit(EXIT_FAILURE); - } - parser.js = js; - - memcpy(js + filesize, buf, r); - filesize += r; - js[filesize] = '\0'; - - r = jsmn_parse(&parser); - if (r < 0) { - printf("error %d at pos %d: %s\n", r, parser.pos, &js[parser.pos]); - } - - for (i = 0; i + +#include "jsmn.c" + +static int test_passed = 0; +static int test_failed = 0; + +/* Terminate current test with error */ +#define fail() return __LINE__ + +/* Successfull end of the test case */ +#define done() return 0 + +/* Check single condition */ +#define check(cond) do { if (!(cond)) fail(); } while (0) + +/* Test runner */ +static void test(int (*func)(void), const char *name) { + int r = func(); + if (r == 0) { + test_passed++; + } else { + test_failed++; + printf("FAILED: %s (at line %d)\n", name, r); + } +} + +#define TOKEN_EQ(t, tok_start, tok_end, tok_type) \ + ((t).start == tok_start \ + && (t).end == tok_end \ + && (t).type == (tok_type)) + +#define TOKEN_PRINT(t) \ + printf("start: %d, end: %d, type: %d\n", (t).start, (t).end, (t).type) + + + +int test_primitive() { + int r; + jsmn_parser p; + jsmntok_t tokens[10]; + + jsmn_init_parser(&p, "{\"a\": 0}", tokens, 10); + + r = jsmn_parse(&p); + check(r == JSMN_SUCCESS); + check(TOKEN_EQ(tokens[0], 0, 8, JSMN_OBJECT)); + check(TOKEN_EQ(tokens[1], 2, 3, JSMN_STRING)); + check(TOKEN_EQ(tokens[2], 6, 7, JSMN_PRIMITIVE)); + + return 0; +} + +int main() { + test(test_primitive, "test primitive values"); + return 0; +} diff --git a/test.sh b/test.sh deleted file mode 100644 index d6dbcf9..0000000 --- a/test.sh +++ /dev/null @@ -1,134 +0,0 @@ -#!/bin/bash - -# -# Test script is organized like this: -# o two variables (PASSED and FAILED) hold the total -# number of passed/faled tests -# o expect() function performs a single test. First -# argument of the function is the variable name and -# the second is an expected value. PASSED/FAILED -# values are updated automatically -# -# Most tests look like: -# | -# | expect "varName" "expectedValue" << JSON_END -# | ..json data here... -# | JSON_END -# | -# - -PASSED=0 -FAILED=0 - -function expect() { - ret=$(./demo -t 10 -b 256 - | grep -A 1 "$1" | tail -n 1 | cut -c 20-) - if [ "x$ret" = "x$2" ]; then - PASSED=$(($PASSED+1)) - else - echo "Failed: $1 != $2" - FAILED=$(($FAILED+1)) - fi -} - - -# -# TEST SET: Basic types (simple values) -# -expect 'boolVar' 'true' << JSON_END -"boolVar" : true -JSON_END - -expect 'boolVar' 'false'<< JSON_END -"boolVar" : false -JSON_END - -expect 'intVar' '12345' << JSON_END -"intVar" : 12345 -JSON_END - -expect 'floatVar' '12.345' << JSON_END -"floatVar" : 12.345 -JSON_END - -expect 'nullVar' 'null' << JSON_END -"nullVar" : null -JSON_END - -expect 'strVar' 'hello' << JSON_END -"strVar" : "hello" -JSON_END - -# -# TEST SET: Simple types (boundary values) -# - -expect 'intVar' '0' << JSON_END -"intVar" : 0 -JSON_END - -expect 'intVar' '-0' << JSON_END -"intVar" : -0 -JSON_END - -expect 'floarVar' '-0.0' << JSON_END -"floarVar" : -0.0 -JSON_END - -expect 'strVar' '\n\r\b\t \u1234' << JSON_END -"strVar" : "\n\r\b\t \u1234" -JSON_END - -expect 'strVar' '' << JSON_END -"strVar" : "" -JSON_END - -# -# TEST SET: Array types -# -expect 'arr' '[1,2,3,4,5]' << JSON_END -"arr" : [1,2,3,4,5] -JSON_END - -expect 'arr' '[1, 2.3, "4", null, true]' << JSON_END -"arr" : [1, 2.3, "4", null, true] -JSON_END - -expect 'arr' '[]' << JSON_END -"arr" : [] -JSON_END - -# -# TEST SET: Object types -# -expect 'obj' '{"a":"b"}' << JSON_END -"obj":{"a":"b"} -JSON_END - -expect 'objField' 'value' << JSON_END -{ - "foo" : "bar", - "objField" : "value" -} -JSON_END - -expect 'foo' 'bar' << JSON_END -{ - "foo" : "bar" - "a" : [ - { - "x" : "y", - "z" : "zz" - }, - 3, - false, - true, - "end" - ], -} -JSON_END - -echo -echo "Passed: $PASSED" -echo "Failed: $FAILED" -echo -