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 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 return false; 83 } 84 85 return true; 86 } 87 88 static int 89 perform_tests (const ucl_object_t *obj) 90 { 91 struct ucl_schema_error err; 92 ucl_object_iter_t iter = NULL; 93 const ucl_object_t *schema, *tests, *description, *test; 94 95 if (obj->type != UCL_OBJECT) { 96 fprintf (stdout, "Bad test case\n"); 97 return EXIT_FAILURE; 98 } 99 100 schema = ucl_object_find_key (obj, "schema"); 101 tests = ucl_object_find_key (obj, "tests"); 102 description = ucl_object_find_key (obj, "description"); 103 104 if (schema == NULL || tests == NULL || description == NULL) { 105 fprintf (stdout, "Bad test case\n"); 106 return EXIT_FAILURE; 107 } 108 109 memset (&err, 0, sizeof (err)); 110 111 while ((test = ucl_iterate_object (tests, &iter, true)) != NULL) { 112 if (!perform_test (schema, test, &err)) { 113 fprintf (stdout, "Test suite '%s' failed\n", 114 ucl_object_tostring (description)); 115 return EXIT_FAILURE; 116 } 117 } 118 119 return 0; 120 } 121 122 int 123 main (int argc, char **argv) 124 { 125 char *buf = NULL; 126 struct ucl_parser *parser; 127 ucl_object_t *obj = NULL; 128 const ucl_object_t *elt; 129 ucl_object_iter_t iter = NULL; 130 int ret = 0; 131 132 if (read_stdin (&buf) == -1) { 133 exit (EXIT_FAILURE); 134 } 135 136 parser = ucl_parser_new (0); 137 138 ucl_parser_add_string (parser, buf, 0); 139 140 if (ucl_parser_get_error (parser) != NULL) { 141 fprintf (stdout, "Error occurred: %s\n", ucl_parser_get_error (parser)); 142 ret = 1; 143 return EXIT_FAILURE; 144 } 145 obj = ucl_parser_get_object (parser); 146 ucl_parser_free (parser); 147 148 while ((elt = ucl_iterate_object (obj, &iter, true)) != NULL) { 149 ret = perform_tests (elt); 150 if (ret != 0) { 151 break; 152 } 153 } 154 155 ucl_object_unref (obj); 156 157 return ret; 158 } 159