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 "ucl.h" 25 #include "ucl_internal.h" 26 27 #include <stdio.h> 28 #include <errno.h> 29 30 #ifndef _WIN32 31 #include <unistd.h> 32 #endif 33 34 static int 35 read_stdin (char **buf) 36 { 37 int size = BUFSIZ, remain, ret; 38 char *p; 39 40 *buf = malloc (size); 41 if (*buf == NULL) { 42 return -1; 43 } 44 45 p = *buf; 46 remain = size; 47 48 while ((ret = read (STDIN_FILENO, p, remain - 1)) > 0) { 49 remain -= ret; 50 p += ret; 51 52 if (remain <= 1) { 53 *buf = realloc (*buf, size * 2); 54 if (*buf == NULL) { 55 return -1; 56 } 57 58 p = *buf + size - 1; 59 remain = size + 1; 60 size *= 2; 61 } 62 } 63 64 *p = '\0'; 65 66 return ret; 67 } 68 69 static bool 70 perform_test (const ucl_object_t *schema, const ucl_object_t *obj, 71 struct ucl_schema_error *err) 72 { 73 const ucl_object_t *valid, *data, *description; 74 bool match; 75 76 data = ucl_object_lookup (obj, "data"); 77 description = ucl_object_lookup (obj, "description"); 78 valid = ucl_object_lookup (obj, "valid"); 79 80 if (data == NULL || description == NULL || valid == NULL) { 81 fprintf (stdout, "Bad test case\n"); 82 return false; 83 } 84 85 match = ucl_object_validate (schema, data, err); 86 if (match != ucl_object_toboolean (valid)) { 87 fprintf (stdout, "Test case '%s' failed (expected %s): '%s'\n", 88 ucl_object_tostring (description), 89 ucl_object_toboolean (valid) ? "valid" : "invalid", 90 err->msg); 91 fprintf (stdout, "%s\n", ucl_object_emit (data, UCL_EMIT_CONFIG)); 92 fprintf (stdout, "%s\n", ucl_object_emit (schema, UCL_EMIT_CONFIG)); 93 return false; 94 } 95 96 return true; 97 } 98 99 static int 100 perform_tests (const ucl_object_t *obj) 101 { 102 struct ucl_schema_error err; 103 ucl_object_iter_t iter = NULL; 104 const ucl_object_t *schema, *tests, *description, *test; 105 106 if (obj->type != UCL_OBJECT) { 107 fprintf (stdout, "Bad test case\n"); 108 return EXIT_FAILURE; 109 } 110 111 schema = ucl_object_lookup (obj, "schema"); 112 tests = ucl_object_lookup (obj, "tests"); 113 description = ucl_object_lookup (obj, "description"); 114 115 if (schema == NULL || tests == NULL || description == NULL) { 116 fprintf (stdout, "Bad test case\n"); 117 return EXIT_FAILURE; 118 } 119 120 memset (&err, 0, sizeof (err)); 121 122 while ((test = ucl_object_iterate (tests, &iter, true)) != NULL) { 123 if (!perform_test (schema, test, &err)) { 124 fprintf (stdout, "Test suite '%s' failed\n", 125 ucl_object_tostring (description)); 126 return EXIT_FAILURE; 127 } 128 } 129 130 return 0; 131 } 132 133 int 134 main (int argc, char **argv) 135 { 136 char *buf = NULL; 137 struct ucl_parser *parser; 138 ucl_object_t *obj = NULL; 139 const ucl_object_t *elt; 140 ucl_object_iter_t iter = NULL; 141 int ret = 0; 142 143 if (read_stdin (&buf) == -1) { 144 exit (EXIT_FAILURE); 145 } 146 147 parser = ucl_parser_new (0); 148 149 ucl_parser_add_string (parser, buf, 0); 150 151 if (ucl_parser_get_error (parser) != NULL) { 152 fprintf (stdout, "Error occurred: %s\n", ucl_parser_get_error (parser)); 153 ret = 1; 154 return EXIT_FAILURE; 155 } 156 obj = ucl_parser_get_object (parser); 157 ucl_parser_free (parser); 158 159 while ((elt = ucl_object_iterate (obj, &iter, true)) != NULL) { 160 ret = perform_tests (elt); 161 if (ret != 0) { 162 break; 163 } 164 } 165 166 ucl_object_unref (obj); 167 168 return ret; 169 } 170