1 /* Copyright (c) 2014, Vsevolod Stakhov 2 * All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions are met: 6 * * Redistributions of source code must retain the above copyright 7 * notice, this list of conditions and the following disclaimer. 8 * * Redistributions in binary form must reproduce the above copyright 9 * notice, this list of conditions and the following disclaimer in the 10 * documentation and/or other materials provided with the distribution. 11 * 12 * THIS SOFTWARE IS PROVIDED ''AS IS'' AND ANY 13 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 14 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 15 * DISCLAIMED. IN NO EVENT SHALL AUTHOR BE LIABLE FOR ANY 16 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 17 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 18 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 19 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 20 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 21 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 22 */ 23 24 #include <stdio.h> 25 #include <errno.h> 26 #include <unistd.h> 27 #include "ucl.h" 28 29 static int 30 read_stdin (char **buf) 31 { 32 int size = BUFSIZ, remain, ret; 33 char *p; 34 35 *buf = malloc (size); 36 if (*buf == NULL) { 37 return -1; 38 } 39 40 p = *buf; 41 remain = size; 42 43 while ((ret = read (STDIN_FILENO, p, remain)) > 0) { 44 remain -= ret; 45 p += ret; 46 if (remain == 0) { 47 *buf = realloc (*buf, size * 2); 48 if (*buf == NULL) { 49 return -1; 50 } 51 p = *buf + size; 52 remain = size; 53 size *= 2; 54 } 55 } 56 57 return ret; 58 } 59 60 static bool 61 perform_test (const ucl_object_t *schema, const ucl_object_t *obj, 62 struct ucl_schema_error *err) 63 { 64 const ucl_object_t *valid, *data, *description; 65 bool match; 66 67 data = ucl_object_find_key (obj, "data"); 68 description = ucl_object_find_key (obj, "description"); 69 valid = ucl_object_find_key (obj, "valid"); 70 71 if (data == NULL || description == NULL || valid == NULL) { 72 fprintf (stdout, "Bad test case\n"); 73 return false; 74 } 75 76 match = ucl_object_validate (schema, data, err); 77 if (match != ucl_object_toboolean (valid)) { 78 fprintf (stdout, "Test case '%s' failed (expected %s): '%s'\n", 79 ucl_object_tostring (description), 80 ucl_object_toboolean (valid) ? "valid" : "invalid", 81 err->msg); 82 fprintf (stdout, "%s\n", ucl_object_emit (data, UCL_EMIT_CONFIG)); 83 fprintf (stdout, "%s\n", ucl_object_emit (schema, UCL_EMIT_CONFIG)); 84 return false; 85 } 86 87 return true; 88 } 89 90 static int 91 perform_tests (const ucl_object_t *obj) 92 { 93 struct ucl_schema_error err; 94 ucl_object_iter_t iter = NULL; 95 const ucl_object_t *schema, *tests, *description, *test; 96 97 if (obj->type != UCL_OBJECT) { 98 fprintf (stdout, "Bad test case\n"); 99 return EXIT_FAILURE; 100 } 101 102 schema = ucl_object_find_key (obj, "schema"); 103 tests = ucl_object_find_key (obj, "tests"); 104 description = ucl_object_find_key (obj, "description"); 105 106 if (schema == NULL || tests == NULL || description == NULL) { 107 fprintf (stdout, "Bad test case\n"); 108 return EXIT_FAILURE; 109 } 110 111 memset (&err, 0, sizeof (err)); 112 113 while ((test = ucl_iterate_object (tests, &iter, true)) != NULL) { 114 if (!perform_test (schema, test, &err)) { 115 fprintf (stdout, "Test suite '%s' failed\n", 116 ucl_object_tostring (description)); 117 return EXIT_FAILURE; 118 } 119 } 120 121 return 0; 122 } 123 124 int 125 main (int argc, char **argv) 126 { 127 char *buf = NULL; 128 struct ucl_parser *parser; 129 ucl_object_t *obj = NULL; 130 const ucl_object_t *elt; 131 ucl_object_iter_t iter = NULL; 132 int ret = 0; 133 134 if (read_stdin (&buf) == -1) { 135 exit (EXIT_FAILURE); 136 } 137 138 parser = ucl_parser_new (0); 139 140 ucl_parser_add_string (parser, buf, 0); 141 142 if (ucl_parser_get_error (parser) != NULL) { 143 fprintf (stdout, "Error occurred: %s\n", ucl_parser_get_error (parser)); 144 ret = 1; 145 return EXIT_FAILURE; 146 } 147 obj = ucl_parser_get_object (parser); 148 ucl_parser_free (parser); 149 150 while ((elt = ucl_iterate_object (obj, &iter, true)) != NULL) { 151 ret = perform_tests (elt); 152 if (ret != 0) { 153 break; 154 } 155 } 156 157 ucl_object_unref (obj); 158 159 return ret; 160 } 161