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