xref: /freebsd-src/contrib/libucl/tests/test_schema.c (revision d9f0ce31900a48d1a2bfc1c8c86f79d1e831451a)
197bd480fSBaptiste Daroussin /* Copyright (c) 2014, Vsevolod Stakhov
297bd480fSBaptiste Daroussin  * All rights reserved.
397bd480fSBaptiste Daroussin  *
497bd480fSBaptiste Daroussin  * Redistribution and use in source and binary forms, with or without
597bd480fSBaptiste Daroussin  * modification, are permitted provided that the following conditions are met:
697bd480fSBaptiste Daroussin  *       * Redistributions of source code must retain the above copyright
797bd480fSBaptiste Daroussin  *         notice, this list of conditions and the following disclaimer.
897bd480fSBaptiste Daroussin  *       * Redistributions in binary form must reproduce the above copyright
997bd480fSBaptiste Daroussin  *         notice, this list of conditions and the following disclaimer in the
1097bd480fSBaptiste Daroussin  *         documentation and/or other materials provided with the distribution.
1197bd480fSBaptiste Daroussin  *
1297bd480fSBaptiste Daroussin  * THIS SOFTWARE IS PROVIDED ''AS IS'' AND ANY
1397bd480fSBaptiste Daroussin  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
1497bd480fSBaptiste Daroussin  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
1597bd480fSBaptiste Daroussin  * DISCLAIMED. IN NO EVENT SHALL AUTHOR BE LIABLE FOR ANY
1697bd480fSBaptiste Daroussin  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
1797bd480fSBaptiste Daroussin  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
1897bd480fSBaptiste Daroussin  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
1997bd480fSBaptiste Daroussin  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2097bd480fSBaptiste Daroussin  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
2197bd480fSBaptiste Daroussin  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2297bd480fSBaptiste Daroussin  */
2397bd480fSBaptiste Daroussin 
2497bd480fSBaptiste Daroussin #include <stdio.h>
2597bd480fSBaptiste Daroussin #include <errno.h>
2697bd480fSBaptiste Daroussin #include <unistd.h>
2797bd480fSBaptiste Daroussin #include "ucl.h"
2897bd480fSBaptiste Daroussin 
2997bd480fSBaptiste Daroussin static int
read_stdin(char ** buf)3097bd480fSBaptiste Daroussin read_stdin (char **buf)
3197bd480fSBaptiste Daroussin {
3297bd480fSBaptiste Daroussin 	int size = BUFSIZ, remain, ret;
3397bd480fSBaptiste Daroussin 	char *p;
3497bd480fSBaptiste Daroussin 
3597bd480fSBaptiste Daroussin 	*buf = malloc (size);
3697bd480fSBaptiste Daroussin 	if (*buf == NULL) {
3797bd480fSBaptiste Daroussin 		return -1;
3897bd480fSBaptiste Daroussin 	}
3997bd480fSBaptiste Daroussin 
4097bd480fSBaptiste Daroussin 	p = *buf;
4197bd480fSBaptiste Daroussin 	remain = size;
4297bd480fSBaptiste Daroussin 
4339ee7a7aSBaptiste Daroussin 	while ((ret = read (STDIN_FILENO, p, remain - 1)) > 0) {
4497bd480fSBaptiste Daroussin 		remain -= ret;
4597bd480fSBaptiste Daroussin 		p += ret;
4639ee7a7aSBaptiste Daroussin 
4739ee7a7aSBaptiste Daroussin 		if (remain <= 1) {
4897bd480fSBaptiste Daroussin 			*buf = realloc (*buf, size * 2);
4997bd480fSBaptiste Daroussin 			if (*buf == NULL) {
5097bd480fSBaptiste Daroussin 				return -1;
5197bd480fSBaptiste Daroussin 			}
5239ee7a7aSBaptiste Daroussin 
5339ee7a7aSBaptiste Daroussin 			p = *buf + size - 1;
5439ee7a7aSBaptiste Daroussin 			remain = size + 1;
5597bd480fSBaptiste Daroussin 			size *= 2;
5697bd480fSBaptiste Daroussin 		}
5797bd480fSBaptiste Daroussin 	}
5897bd480fSBaptiste Daroussin 
5939ee7a7aSBaptiste Daroussin 	*p = '\0';
6039ee7a7aSBaptiste Daroussin 
6197bd480fSBaptiste Daroussin 	return ret;
6297bd480fSBaptiste Daroussin }
6397bd480fSBaptiste Daroussin 
6497bd480fSBaptiste Daroussin static bool
perform_test(const ucl_object_t * schema,const ucl_object_t * obj,struct ucl_schema_error * err)65b04a7a0bSBaptiste Daroussin perform_test (const ucl_object_t *schema, const ucl_object_t *obj,
6697bd480fSBaptiste Daroussin 		struct ucl_schema_error *err)
6797bd480fSBaptiste Daroussin {
684bf54857SBaptiste Daroussin 	const ucl_object_t *valid, *data, *description;
6997bd480fSBaptiste Daroussin 	bool match;
7097bd480fSBaptiste Daroussin 
71*d9f0ce31SBaptiste Daroussin 	data = ucl_object_lookup (obj, "data");
72*d9f0ce31SBaptiste Daroussin 	description = ucl_object_lookup (obj, "description");
73*d9f0ce31SBaptiste Daroussin 	valid = ucl_object_lookup (obj, "valid");
7497bd480fSBaptiste Daroussin 
7597bd480fSBaptiste Daroussin 	if (data == NULL || description == NULL || valid == NULL) {
7697bd480fSBaptiste Daroussin 		fprintf (stdout, "Bad test case\n");
7797bd480fSBaptiste Daroussin 		return false;
7897bd480fSBaptiste Daroussin 	}
7997bd480fSBaptiste Daroussin 
8097bd480fSBaptiste Daroussin 	match = ucl_object_validate (schema, data, err);
8197bd480fSBaptiste Daroussin 	if (match != ucl_object_toboolean (valid)) {
8297bd480fSBaptiste Daroussin 		fprintf (stdout, "Test case '%s' failed (expected %s): '%s'\n",
8397bd480fSBaptiste Daroussin 				ucl_object_tostring (description),
8497bd480fSBaptiste Daroussin 				ucl_object_toboolean (valid) ? "valid" : "invalid",
8597bd480fSBaptiste Daroussin 						err->msg);
868e3b1ab2SBaptiste Daroussin 		fprintf (stdout, "%s\n", ucl_object_emit (data, UCL_EMIT_CONFIG));
878e3b1ab2SBaptiste Daroussin 		fprintf (stdout, "%s\n", ucl_object_emit (schema, UCL_EMIT_CONFIG));
8897bd480fSBaptiste Daroussin 		return false;
8997bd480fSBaptiste Daroussin 	}
9097bd480fSBaptiste Daroussin 
9197bd480fSBaptiste Daroussin 	return true;
9297bd480fSBaptiste Daroussin }
9397bd480fSBaptiste Daroussin 
9497bd480fSBaptiste Daroussin static int
perform_tests(const ucl_object_t * obj)95b04a7a0bSBaptiste Daroussin perform_tests (const ucl_object_t *obj)
9697bd480fSBaptiste Daroussin {
9797bd480fSBaptiste Daroussin 	struct ucl_schema_error err;
9897bd480fSBaptiste Daroussin 	ucl_object_iter_t iter = NULL;
99b04a7a0bSBaptiste Daroussin 	const ucl_object_t *schema, *tests, *description, *test;
10097bd480fSBaptiste Daroussin 
10197bd480fSBaptiste Daroussin 	if (obj->type != UCL_OBJECT) {
10297bd480fSBaptiste Daroussin 		fprintf (stdout, "Bad test case\n");
10397bd480fSBaptiste Daroussin 		return EXIT_FAILURE;
10497bd480fSBaptiste Daroussin 	}
10597bd480fSBaptiste Daroussin 
106*d9f0ce31SBaptiste Daroussin 	schema = ucl_object_lookup (obj, "schema");
107*d9f0ce31SBaptiste Daroussin 	tests = ucl_object_lookup (obj, "tests");
108*d9f0ce31SBaptiste Daroussin 	description = ucl_object_lookup (obj, "description");
10997bd480fSBaptiste Daroussin 
11097bd480fSBaptiste Daroussin 	if (schema == NULL || tests == NULL || description == NULL) {
11197bd480fSBaptiste Daroussin 		fprintf (stdout, "Bad test case\n");
11297bd480fSBaptiste Daroussin 		return EXIT_FAILURE;
11397bd480fSBaptiste Daroussin 	}
11497bd480fSBaptiste Daroussin 
11597bd480fSBaptiste Daroussin 	memset (&err, 0, sizeof (err));
11697bd480fSBaptiste Daroussin 
117*d9f0ce31SBaptiste Daroussin 	while ((test = ucl_object_iterate (tests, &iter, true)) != NULL) {
11897bd480fSBaptiste Daroussin 		if (!perform_test (schema, test, &err)) {
11997bd480fSBaptiste Daroussin 			fprintf (stdout, "Test suite '%s' failed\n",
12097bd480fSBaptiste Daroussin 							ucl_object_tostring (description));
12197bd480fSBaptiste Daroussin 			return EXIT_FAILURE;
12297bd480fSBaptiste Daroussin 		}
12397bd480fSBaptiste Daroussin 	}
12497bd480fSBaptiste Daroussin 
12597bd480fSBaptiste Daroussin 	return 0;
12697bd480fSBaptiste Daroussin }
12797bd480fSBaptiste Daroussin 
12897bd480fSBaptiste Daroussin int
main(int argc,char ** argv)12997bd480fSBaptiste Daroussin main (int argc, char **argv)
13097bd480fSBaptiste Daroussin {
13197bd480fSBaptiste Daroussin 	char *buf = NULL;
13297bd480fSBaptiste Daroussin 	struct ucl_parser *parser;
133b04a7a0bSBaptiste Daroussin 	ucl_object_t *obj = NULL;
134b04a7a0bSBaptiste Daroussin 	const ucl_object_t *elt;
13597bd480fSBaptiste Daroussin 	ucl_object_iter_t iter = NULL;
13697bd480fSBaptiste Daroussin 	int ret = 0;
13797bd480fSBaptiste Daroussin 
13897bd480fSBaptiste Daroussin 	if (read_stdin (&buf) == -1) {
13997bd480fSBaptiste Daroussin 		exit (EXIT_FAILURE);
14097bd480fSBaptiste Daroussin 	}
14197bd480fSBaptiste Daroussin 
14297bd480fSBaptiste Daroussin 	parser = ucl_parser_new (0);
14397bd480fSBaptiste Daroussin 
14497bd480fSBaptiste Daroussin 	ucl_parser_add_string (parser, buf, 0);
14597bd480fSBaptiste Daroussin 
14697bd480fSBaptiste Daroussin 	if (ucl_parser_get_error (parser) != NULL) {
14797bd480fSBaptiste Daroussin 		fprintf (stdout, "Error occurred: %s\n", ucl_parser_get_error (parser));
14897bd480fSBaptiste Daroussin 		ret = 1;
14997bd480fSBaptiste Daroussin 		return EXIT_FAILURE;
15097bd480fSBaptiste Daroussin 	}
15197bd480fSBaptiste Daroussin 	obj = ucl_parser_get_object (parser);
15297bd480fSBaptiste Daroussin 	ucl_parser_free (parser);
15397bd480fSBaptiste Daroussin 
154*d9f0ce31SBaptiste Daroussin 	while ((elt = ucl_object_iterate (obj, &iter, true)) != NULL) {
15597bd480fSBaptiste Daroussin 		ret = perform_tests (elt);
15697bd480fSBaptiste Daroussin 		if (ret != 0) {
15797bd480fSBaptiste Daroussin 			break;
15897bd480fSBaptiste Daroussin 		}
15997bd480fSBaptiste Daroussin 	}
16097bd480fSBaptiste Daroussin 
16197bd480fSBaptiste Daroussin 	ucl_object_unref (obj);
16297bd480fSBaptiste Daroussin 
16397bd480fSBaptiste Daroussin 	return ret;
16497bd480fSBaptiste Daroussin }
165