Commits

Anonymous committed a6648a7

switched to C unit-tests instead of bash

Comments (0)

Files changed (4)

 
 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 $@ $^
 %.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

demo.c

-/* This demo is not needed to be C89-compatible, so for now GCC extensions are
- * used */
-#define _GNU_SOURCE
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <unistd.h>
-#include <getopt.h>
-#include <errno.h>
-
-#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 <file.js>\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<num_tokens; i++) {
-			jsmn_dump_obj(&parser.tokens[i], js);
-		}
-	}
-
-	fclose(f);
-	free(buf);
-	free(tokens);
-	free(js);
-
-	return 0;
-}
+#include <stdio.h>
+
+#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;
+}

test.sh

-#!/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 
-