1268896Sbapt/* Copyright (c) 2014, Vsevolod Stakhov 2268896Sbapt * All rights reserved. 3268896Sbapt * 4268896Sbapt * Redistribution and use in source and binary forms, with or without 5268896Sbapt * modification, are permitted provided that the following conditions are met: 6268896Sbapt * * Redistributions of source code must retain the above copyright 7268896Sbapt * notice, this list of conditions and the following disclaimer. 8268896Sbapt * * Redistributions in binary form must reproduce the above copyright 9268896Sbapt * notice, this list of conditions and the following disclaimer in the 10268896Sbapt * documentation and/or other materials provided with the distribution. 11268896Sbapt * 12268896Sbapt * THIS SOFTWARE IS PROVIDED ''AS IS'' AND ANY 13268896Sbapt * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 14268896Sbapt * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 15268896Sbapt * DISCLAIMED. IN NO EVENT SHALL AUTHOR BE LIABLE FOR ANY 16268896Sbapt * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 17268896Sbapt * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 18268896Sbapt * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 19268896Sbapt * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 20268896Sbapt * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 21268896Sbapt * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 22268896Sbapt */ 23268896Sbapt 24268896Sbapt#include <stdio.h> 25268896Sbapt#include <errno.h> 26268896Sbapt#include <unistd.h> 27268896Sbapt#include "ucl.h" 28268896Sbapt 29268896Sbaptstatic int 30268896Sbaptread_stdin (char **buf) 31268896Sbapt{ 32268896Sbapt int size = BUFSIZ, remain, ret; 33268896Sbapt char *p; 34268896Sbapt 35268896Sbapt *buf = malloc (size); 36268896Sbapt if (*buf == NULL) { 37268896Sbapt return -1; 38268896Sbapt } 39268896Sbapt 40268896Sbapt p = *buf; 41268896Sbapt remain = size; 42268896Sbapt 43268896Sbapt while ((ret = read (STDIN_FILENO, p, remain)) > 0) { 44268896Sbapt remain -= ret; 45268896Sbapt p += ret; 46268896Sbapt if (remain == 0) { 47268896Sbapt *buf = realloc (*buf, size * 2); 48268896Sbapt if (*buf == NULL) { 49268896Sbapt return -1; 50268896Sbapt } 51268896Sbapt p = *buf + size; 52268896Sbapt remain = size; 53268896Sbapt size *= 2; 54268896Sbapt } 55268896Sbapt } 56268896Sbapt 57268896Sbapt return ret; 58268896Sbapt} 59268896Sbapt 60268896Sbaptstatic bool 61268896Sbaptperform_test (const ucl_object_t *schema, const ucl_object_t *obj, 62268896Sbapt struct ucl_schema_error *err) 63268896Sbapt{ 64268896Sbapt const const ucl_object_t *valid, *data, *description; 65268896Sbapt bool match; 66268896Sbapt 67268896Sbapt data = ucl_object_find_key (obj, "data"); 68268896Sbapt description = ucl_object_find_key (obj, "description"); 69268896Sbapt valid = ucl_object_find_key (obj, "valid"); 70268896Sbapt 71268896Sbapt if (data == NULL || description == NULL || valid == NULL) { 72268896Sbapt fprintf (stdout, "Bad test case\n"); 73268896Sbapt return false; 74268896Sbapt } 75268896Sbapt 76268896Sbapt match = ucl_object_validate (schema, data, err); 77268896Sbapt if (match != ucl_object_toboolean (valid)) { 78268896Sbapt fprintf (stdout, "Test case '%s' failed (expected %s): '%s'\n", 79268896Sbapt ucl_object_tostring (description), 80268896Sbapt ucl_object_toboolean (valid) ? "valid" : "invalid", 81268896Sbapt err->msg); 82268896Sbapt return false; 83268896Sbapt } 84268896Sbapt 85268896Sbapt return true; 86268896Sbapt} 87268896Sbapt 88268896Sbaptstatic int 89268896Sbaptperform_tests (const ucl_object_t *obj) 90268896Sbapt{ 91268896Sbapt struct ucl_schema_error err; 92268896Sbapt ucl_object_iter_t iter = NULL; 93268896Sbapt const ucl_object_t *schema, *tests, *description, *test; 94268896Sbapt 95268896Sbapt if (obj->type != UCL_OBJECT) { 96268896Sbapt fprintf (stdout, "Bad test case\n"); 97268896Sbapt return EXIT_FAILURE; 98268896Sbapt } 99268896Sbapt 100268896Sbapt schema = ucl_object_find_key (obj, "schema"); 101268896Sbapt tests = ucl_object_find_key (obj, "tests"); 102268896Sbapt description = ucl_object_find_key (obj, "description"); 103268896Sbapt 104268896Sbapt if (schema == NULL || tests == NULL || description == NULL) { 105268896Sbapt fprintf (stdout, "Bad test case\n"); 106268896Sbapt return EXIT_FAILURE; 107268896Sbapt } 108268896Sbapt 109268896Sbapt memset (&err, 0, sizeof (err)); 110268896Sbapt 111268896Sbapt while ((test = ucl_iterate_object (tests, &iter, true)) != NULL) { 112268896Sbapt if (!perform_test (schema, test, &err)) { 113268896Sbapt fprintf (stdout, "Test suite '%s' failed\n", 114268896Sbapt ucl_object_tostring (description)); 115268896Sbapt return EXIT_FAILURE; 116268896Sbapt } 117268896Sbapt } 118268896Sbapt 119268896Sbapt return 0; 120268896Sbapt} 121268896Sbapt 122268896Sbaptint 123268896Sbaptmain (int argc, char **argv) 124268896Sbapt{ 125268896Sbapt char *buf = NULL; 126268896Sbapt struct ucl_parser *parser; 127268896Sbapt ucl_object_t *obj = NULL; 128268896Sbapt const ucl_object_t *elt; 129268896Sbapt ucl_object_iter_t iter = NULL; 130268896Sbapt int ret = 0; 131268896Sbapt 132268896Sbapt if (read_stdin (&buf) == -1) { 133268896Sbapt exit (EXIT_FAILURE); 134268896Sbapt } 135268896Sbapt 136268896Sbapt parser = ucl_parser_new (0); 137268896Sbapt 138268896Sbapt ucl_parser_add_string (parser, buf, 0); 139268896Sbapt 140268896Sbapt if (ucl_parser_get_error (parser) != NULL) { 141268896Sbapt fprintf (stdout, "Error occurred: %s\n", ucl_parser_get_error (parser)); 142268896Sbapt ret = 1; 143268896Sbapt return EXIT_FAILURE; 144268896Sbapt } 145268896Sbapt obj = ucl_parser_get_object (parser); 146268896Sbapt ucl_parser_free (parser); 147268896Sbapt 148268896Sbapt while ((elt = ucl_iterate_object (obj, &iter, true)) != NULL) { 149268896Sbapt ret = perform_tests (elt); 150268896Sbapt if (ret != 0) { 151268896Sbapt break; 152268896Sbapt } 153268896Sbapt } 154268896Sbapt 155268896Sbapt ucl_object_unref (obj); 156268896Sbapt 157268896Sbapt return ret; 158268896Sbapt} 159