exchange

Base system with REST service to issue digital coins, run by the payment service provider
Log | Files | Refs | Submodules | README | LICENSE

test-specs.c (12272B)


      1 /*
      2  Author: José Bollo <jobol@nonadev.net>
      3 
      4  https://gitlab.com/jobol/mustach
      5 
      6  SPDX-License-Identifier: ISC
      7 */
      8 
      9 #ifndef _GNU_SOURCE
     10 #define _GNU_SOURCE
     11 #endif
     12 
     13 #include <stdlib.h>
     14 #include <stdio.h>
     15 #include <sys/stat.h>
     16 #include <unistd.h>
     17 #include <fcntl.h>
     18 #include <string.h>
     19 #include <errno.h>
     20 
     21 #include "mustach-wrap.h"
     22 
     23 #define TEST_JSON_C  1
     24 #define TEST_JANSSON 2
     25 #define TEST_CJSON   3
     26 
     27 static const char *errors[] = {
     28 	"??? unreferenced ???",
     29 	"system",
     30 	"unexpected end",
     31 	"empty tag",
     32 	"tag too long",
     33 	"bad separators",
     34 	"too depth",
     35 	"closing",
     36 	"bad unescape tag",
     37 	"invalid interface",
     38 	"item not found",
     39 	"partial not found"
     40 };
     41 
     42 const char *mustach_error_string(int status)
     43 {
     44 	return status >= 0 ? "no error"
     45 		: errors[status <= -(int)(sizeof errors / sizeof * errors) ? 0 : -status];
     46 }
     47 
     48 static const char *errmsg = 0;
     49 static int flags = 0;
     50 static FILE *output = 0;
     51 
     52 static void help(char *prog)
     53 {
     54 	char *name = basename(prog);
     55 #define STR(x) #x
     56 	printf("%s version %s\n", name, STR(VERSION));
     57 #undef STR
     58 	printf("usage: %s test-files...\n", name);
     59 	exit(0);
     60 }
     61 
     62 #if TEST == TEST_CJSON
     63 
     64 static const size_t BLOCKSIZE = 8192;
     65 
     66 static char *readfile(const char *filename, size_t *length)
     67 {
     68 	int f;
     69 	struct stat s;
     70 	char *result;
     71 	size_t size, pos;
     72 	ssize_t rc;
     73 
     74 	result = NULL;
     75 	if (filename[0] == '-' &&  filename[1] == 0)
     76 		f = dup(0);
     77 	else
     78 		f = open(filename, O_RDONLY);
     79 	if (f < 0) {
     80 		fprintf(stderr, "Can't open file: %s\n", filename);
     81 		exit(1);
     82 	}
     83 
     84 	fstat(f, &s);
     85 	switch (s.st_mode & S_IFMT) {
     86 	case S_IFREG:
     87 		size = s.st_size;
     88 		break;
     89 	case S_IFSOCK:
     90 	case S_IFIFO:
     91 		size = BLOCKSIZE;
     92 		break;
     93 	default:
     94 		fprintf(stderr, "Bad file: %s\n", filename);
     95 		exit(1);
     96 	}
     97 
     98 	pos = 0;
     99 	result = malloc(size + 1);
    100 	do {
    101 		if (result == NULL) {
    102 			fprintf(stderr, "Out of memory\n");
    103 			exit(1);
    104 		}
    105 		rc = read(f, &result[pos], (size - pos) + 1);
    106 		if (rc < 0) {
    107 			fprintf(stderr, "Error while reading %s\n", filename);
    108 			exit(1);
    109 		}
    110 		if (rc > 0) {
    111 			pos += (size_t)rc;
    112 			if (pos > size) {
    113 				size = pos + BLOCKSIZE;
    114 				result = realloc(result, size + 1);
    115 			}
    116 		}
    117 	} while(rc > 0);
    118 
    119 	close(f);
    120 	if (length != NULL)
    121 		*length = pos;
    122 	result[pos] = 0;
    123 	return result;
    124 }
    125 #endif
    126 
    127 typedef struct {
    128 	unsigned nerror;
    129 	unsigned ndiffers;
    130 	unsigned nsuccess;
    131 	unsigned ninvalid;
    132 } counters;
    133 
    134 static int load_json(const char *filename);
    135 static int process(counters *c);
    136 static void close_json();
    137 static int get_partial(const char *name, struct mustach_sbuf *sbuf);
    138 
    139 int main(int ac, char **av)
    140 {
    141 	char *f;
    142 	char *prog = *av;
    143 	int s;
    144 	counters c;
    145 
    146 	(void)ac; /* unused */
    147 	flags = Mustach_With_SingleDot | Mustach_With_IncPartial;
    148 	output = stdout;
    149 	mustach_wrap_get_partial = get_partial;
    150 
    151 	memset(&c, 0, sizeof c);
    152 	while (*++av) {
    153 		if (!strcmp(*av, "-h") || !strcmp(*av, "--help"))
    154 			help(prog);
    155 		f = (av[0][0] == '-' && !av[0][1]) ? "/dev/stdin" : av[0];
    156 		fprintf(output, "\nloading %s\n", f);
    157 		s = load_json(f);
    158 		if (s < 0) {
    159 			fprintf(stderr, "error when loading %s!\n", f);
    160 			if(errmsg)
    161 				fprintf(stderr, "   reason: %s\n", errmsg);
    162 			exit(1);
    163 		}
    164 		fprintf(output, "processing file %s\n", f);
    165 		s = process(&c);
    166 		if (s < 0) {
    167 			fprintf(stderr, "error bad test file %s!\n", f);
    168 			exit(1);
    169 		}
    170 		close_json();
    171 	}
    172 	fprintf(output, "\nsummary:\n");
    173 	if (c.ninvalid)
    174 		fprintf(output, "  invalid %u\n", c.ninvalid);
    175 	fprintf(output, "  error   %u\n", c.nerror);
    176 	fprintf(output, "  differ  %u\n", c.ndiffers);
    177 	fprintf(output, "  success %u\n", c.nsuccess);
    178 	if (c.nerror)
    179 		return 2;
    180 	if (c.ndiffers)
    181 		return 1;
    182 	return 0;
    183 }
    184 
    185 void emit(FILE *f, const char *s)
    186 {
    187 	for(;;s++) {
    188 		switch(*s) {
    189 		case 0: return;
    190 		case '\\': fprintf(f, "\\\\"); break;
    191 		case '\t': fprintf(f, "\\t"); break;
    192 		case '\n': fprintf(f, "\\n"); break;
    193 		case '\r': fprintf(f, "\\r"); break;
    194 		default: fprintf(f, "%c", *s); break;
    195 		}
    196 	}
    197 }
    198 
    199 #if TEST == TEST_JSON_C
    200 
    201 #include "mustach-json-c.h"
    202 
    203 static struct json_object *o;
    204 
    205 static struct json_object *partials;
    206 static int get_partial(const char *name, struct mustach_sbuf *sbuf)
    207 {
    208 	struct json_object *x;
    209 	if (partials == NULL || !json_object_object_get_ex(partials, name, &x))
    210 		return MUSTACH_ERROR_PARTIAL_NOT_FOUND;
    211 	sbuf->value = json_object_get_string(x);
    212 	return MUSTACH_OK;
    213 }
    214 
    215 static int load_json(const char *filename)
    216 {
    217 	o = json_object_from_file(filename);
    218 #if JSON_C_VERSION_NUM >= 0x000D00
    219 	errmsg = json_util_get_last_err();
    220 	if (errmsg != NULL)
    221 		return -1;
    222 #endif
    223 	if (o == NULL) {
    224 		errmsg = "null json";
    225 		return -1;
    226 	}
    227 	return 0;
    228 }
    229 static int process(counters *c)
    230 {
    231 	const char *t, *e;
    232 	char *got;
    233 	unsigned i, n;
    234 	size_t length;
    235 	int s;
    236 	json_object *tests, *unit, *name, *desc, *data, *template, *expected;
    237 
    238 	if (!json_object_object_get_ex(o, "tests", &tests) || json_object_get_type(tests) != json_type_array)
    239 		return -1;
    240 
    241 	i = 0;
    242 	n = (unsigned)json_object_array_length(tests);
    243 	while (i < n) {
    244 		unit = json_object_array_get_idx(tests, i);
    245 		if (json_object_get_type(unit) != json_type_object
    246 		 || !json_object_object_get_ex(unit, "name", &name)
    247 		 || !json_object_object_get_ex(unit, "desc", &desc)
    248 		 || !json_object_object_get_ex(unit, "data", &data)
    249 		 || !json_object_object_get_ex(unit, "template", &template)
    250 		 || !json_object_object_get_ex(unit, "expected", &expected)
    251 		 || json_object_get_type(name) != json_type_string
    252 		 || json_object_get_type(desc) != json_type_string
    253 		 || json_object_get_type(template) != json_type_string
    254 		 || json_object_get_type(expected) != json_type_string) {
    255 			fprintf(stderr, "invalid test %u\n", i);
    256 			c->ninvalid++;
    257 		}
    258 		else {
    259 			fprintf(output, "[%u] %s\n", i, json_object_get_string(name));
    260 			fprintf(output, "\t%s\n", json_object_get_string(desc));
    261 			if (!json_object_object_get_ex(unit, "partials", &partials))
    262 				partials = NULL;
    263 			t = json_object_get_string(template);
    264 			e = json_object_get_string(expected);
    265 			s = mustach_json_c_mem(t, 0, data, flags, &got, &length);
    266 			if (s == 0 && strcmp(got, e) == 0) {
    267 				fprintf(output, "\t=> SUCCESS\n");
    268 				c->nsuccess++;
    269 			}
    270 			else {
    271 				if (s < 0) {
    272 					fprintf(output, "\t=> ERROR %s\n", mustach_error_string(s));
    273 					c->nerror++;
    274 				}
    275 				else {
    276 					fprintf(output, "\t=> DIFFERS\n");
    277 					c->ndiffers++;
    278 				}
    279 				if (partials)
    280 					fprintf(output, "\t.. PARTIALS[%s]\n", json_object_to_json_string_ext(partials, 0));
    281 				fprintf(output, "\t..     DATA[%s]\n", json_object_to_json_string_ext(data, 0));
    282 				fprintf(output, "\t.. TEMPLATE[");
    283 				emit(output, t);
    284 				fprintf(output, "]\n");
    285 				fprintf(output, "\t.. EXPECTED[");
    286 				emit(output, e);
    287 				fprintf(output, "]\n");
    288 				if (s == 0) {
    289 					fprintf(output, "\t..      GOT[");
    290 					emit(output, got);
    291 					fprintf(output, "]\n");
    292 				}
    293 			}
    294 			free(got);
    295 		}
    296 		i++;
    297 	}
    298 	return 0;
    299 }
    300 static void close_json()
    301 {
    302 	json_object_put(o);
    303 }
    304 
    305 #elif TEST == TEST_JANSSON
    306 
    307 #include "mustach-jansson.h"
    308 
    309 static json_t *o;
    310 static json_error_t e;
    311 
    312 static json_t *partials;
    313 static int get_partial(const char *name, struct mustach_sbuf *sbuf)
    314 {
    315 	json_t *x;
    316 	if (partials == NULL || !(x = json_object_get(partials, name)))
    317 		return MUSTACH_ERROR_PARTIAL_NOT_FOUND;
    318 	sbuf->value = json_string_value(x);
    319 	return MUSTACH_OK;
    320 }
    321 
    322 static int load_json(const char *filename)
    323 {
    324 	o = json_load_file(filename, JSON_DECODE_ANY, &e);
    325 	if (o == NULL) {
    326 		errmsg = e.text;
    327 		return -1;
    328 	}
    329 	return 0;
    330 }
    331 static int process(counters *c)
    332 {
    333 	const char *t, *e;
    334 	char *got, *tmp;
    335 	int i, n;
    336 	size_t length;
    337 	int s;
    338 	json_t *tests, *unit, *name, *desc, *data, *template, *expected;
    339 
    340 	tests = json_object_get(o, "tests");
    341 	if (!tests || json_typeof(tests) != JSON_ARRAY)
    342 		return -1;
    343 
    344 	i = 0;
    345 	n = json_array_size(tests);
    346 	while (i < n) {
    347 		unit = json_array_get(tests, i);
    348 		if (!unit || json_typeof(unit) != JSON_OBJECT
    349 		 || !(name = json_object_get(unit, "name"))
    350 		 || !(desc = json_object_get(unit, "desc"))
    351 		 || !(data = json_object_get(unit, "data"))
    352 		 || !(template = json_object_get(unit, "template"))
    353 		 || !(expected = json_object_get(unit, "expected"))
    354 		 || json_typeof(name) != JSON_STRING
    355 		 || json_typeof(desc) != JSON_STRING
    356 		 || json_typeof(template) != JSON_STRING
    357 		 || json_typeof(expected) != JSON_STRING) {
    358 			fprintf(stderr, "invalid test %u\n", i);
    359 			c->ninvalid++;
    360 		}
    361 		else {
    362 			fprintf(output, "[%u] %s\n", i, json_string_value(name));
    363 			fprintf(output, "\t%s\n", json_string_value(desc));
    364 			partials = json_object_get(unit, "partials");
    365 			t = json_string_value(template);
    366 			e = json_string_value(expected);
    367 			s = mustach_jansson_mem(t, 0, data, flags, &got, &length);
    368 			if (s == 0 && strcmp(got, e) == 0) {
    369 				fprintf(output, "\t=> SUCCESS\n");
    370 				c->nsuccess++;
    371 			}
    372 			else {
    373 				if (s < 0) {
    374 					fprintf(output, "\t=> ERROR %s\n", mustach_error_string(s));
    375 					c->nerror++;
    376 				}
    377 				else {
    378 					fprintf(output, "\t=> DIFFERS\n");
    379 					c->ndiffers++;
    380 				}
    381 				if (partials) {
    382 					tmp = json_dumps(partials, JSON_ENCODE_ANY | JSON_COMPACT);
    383 					fprintf(output, "\t.. PARTIALS[%s]\n", tmp);
    384 					free(tmp);
    385 				}
    386 				tmp = json_dumps(data, JSON_ENCODE_ANY | JSON_COMPACT);
    387 				fprintf(output, "\t..     DATA[%s]\n", tmp);
    388 				free(tmp);
    389 				fprintf(output, "\t.. TEMPLATE[");
    390 				emit(output, t);
    391 				fprintf(output, "]\n");
    392 				fprintf(output, "\t.. EXPECTED[");
    393 				emit(output, e);
    394 				fprintf(output, "]\n");
    395 				if (s == 0) {
    396 					fprintf(output, "\t..      GOT[");
    397 					emit(output, got);
    398 					fprintf(output, "]\n");
    399 				}
    400 			}
    401 			free(got);
    402 		}
    403 		i++;
    404 	}
    405 	return 0;
    406 }
    407 static void close_json()
    408 {
    409 	json_decref(o);
    410 }
    411 
    412 #elif TEST == TEST_CJSON
    413 
    414 #include "mustach-cjson.h"
    415 
    416 static cJSON *o;
    417 static cJSON *partials;
    418 static int get_partial(const char *name, struct mustach_sbuf *sbuf)
    419 {
    420 	cJSON *x;
    421 	if (partials == NULL || !(x = cJSON_GetObjectItemCaseSensitive(partials, name)))
    422 		return MUSTACH_ERROR_PARTIAL_NOT_FOUND;
    423 	sbuf->value = x->valuestring;
    424 	return MUSTACH_OK;
    425 }
    426 
    427 static int load_json(const char *filename)
    428 {
    429 	char *t;
    430 	size_t length;
    431 
    432 	t = readfile(filename, &length);
    433 	o = t ? cJSON_ParseWithLength(t, length) : NULL;
    434 	free(t);
    435 	return -!o;
    436 }
    437 static int process(counters *c)
    438 {
    439 	const char *t, *e;
    440 	char *got, *tmp;
    441 	int i, n;
    442 	size_t length;
    443 	int s;
    444 	cJSON *tests, *unit, *name, *desc, *data, *template, *expected;
    445 
    446 	tests = cJSON_GetObjectItemCaseSensitive(o, "tests");
    447 	if (!tests || tests->type != cJSON_Array)
    448 		return -1;
    449 
    450 	i = 0;
    451 	n = cJSON_GetArraySize(tests);
    452 	while (i < n) {
    453 		unit = cJSON_GetArrayItem(tests, i);
    454 		if (!unit || unit->type != cJSON_Object
    455 		 || !(name = cJSON_GetObjectItemCaseSensitive(unit, "name"))
    456 		 || !(desc = cJSON_GetObjectItemCaseSensitive(unit, "desc"))
    457 		 || !(data = cJSON_GetObjectItemCaseSensitive(unit, "data"))
    458 		 || !(template = cJSON_GetObjectItemCaseSensitive(unit, "template"))
    459 		 || !(expected = cJSON_GetObjectItemCaseSensitive(unit, "expected"))
    460 		 || name->type != cJSON_String
    461 		 || desc->type != cJSON_String
    462 		 || template->type != cJSON_String
    463 		 || expected->type != cJSON_String) {
    464 			fprintf(stderr, "invalid test %u\n", i);
    465 			c->ninvalid++;
    466 		}
    467 		else {
    468 			fprintf(output, "[%u] %s\n", i, name->valuestring);
    469 			fprintf(output, "\t%s\n", desc->valuestring);
    470 			partials = cJSON_GetObjectItemCaseSensitive(unit, "partials");
    471 			t = template->valuestring;
    472 			e = expected->valuestring;
    473 			s = mustach_cJSON_mem(t, 0, data, flags, &got, &length);
    474 			if (s == 0 && strcmp(got, e) == 0) {
    475 				fprintf(output, "\t=> SUCCESS\n");
    476 				c->nsuccess++;
    477 			}
    478 			else {
    479 				if (s < 0) {
    480 					fprintf(output, "\t=> ERROR %s\n", mustach_error_string(s));
    481 					c->nerror++;
    482 				}
    483 				else {
    484 					fprintf(output, "\t=> DIFFERS\n");
    485 					c->ndiffers++;
    486 				}
    487 				if (partials) {
    488 					tmp = cJSON_PrintUnformatted(partials);
    489 					fprintf(output, "\t.. PARTIALS[%s]\n", tmp);
    490 					free(tmp);
    491 				}
    492 				tmp = cJSON_PrintUnformatted(data);
    493 				fprintf(output, "\t..     DATA[%s]\n", tmp);
    494 				free(tmp);
    495 				fprintf(output, "\t.. TEMPLATE[");
    496 				emit(output, t);
    497 				fprintf(output, "]\n");
    498 				fprintf(output, "\t.. EXPECTED[");
    499 				emit(output, e);
    500 				fprintf(output, "]\n");
    501 				if (s == 0) {
    502 					fprintf(output, "\t..      GOT[");
    503 					emit(output, got);
    504 					fprintf(output, "]\n");
    505 				}
    506 			}
    507 			free(got);
    508 		}
    509 		i++;
    510 	}
    511 	return 0;
    512 }
    513 static void close_json()
    514 {
    515 	cJSON_Delete(o);
    516 }
    517 
    518 #else
    519 #error "no defined json library"
    520 #endif