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