1 /* 2 * Copyright 2007 Ryan Lortie 3 * 4 * This program is free software: you can redistribute it and/or modify 5 * it under the terms of the GNU Lesser General Public License as 6 * published by the Free Software Foundation; either version 2 of the 7 * License, or (at your option) any later version. 8 * 9 * See the included COPYING file for more information. 10 */ 11 12 #include <string.h> 13 #include <glib.h> 14 15 static void 16 start (GMarkupParseContext *context, 17 const char *element_name, 18 const char **attribute_names, 19 const char **attribute_values, 20 gpointer user_data, 21 GError **error) 22 { 23 GString *string = user_data; 24 gboolean result; 25 26 #define collect(...) \ 27 g_markup_collect_attributes (element_name, attribute_names, \ 28 attribute_values, error, __VA_ARGS__, \ 29 G_MARKUP_COLLECT_INVALID) 30 #define BOOL G_MARKUP_COLLECT_BOOLEAN 31 #define OPTBOOL G_MARKUP_COLLECT_BOOLEAN | G_MARKUP_COLLECT_OPTIONAL 32 #define TRI G_MARKUP_COLLECT_TRISTATE 33 #define STR G_MARKUP_COLLECT_STRING 34 #define STRDUP G_MARKUP_COLLECT_STRDUP 35 #define OPTSTR G_MARKUP_COLLECT_STRING | G_MARKUP_COLLECT_OPTIONAL 36 #define OPTDUP G_MARKUP_COLLECT_STRDUP | G_MARKUP_COLLECT_OPTIONAL 37 #define n(x) ((x)?(x):"(null)") 38 39 if (strcmp (element_name, "bool") == 0) 40 { 41 gboolean mb = 2, ob = 2, tri = 2; 42 43 result = collect (BOOL, "mb", &mb, 44 OPTBOOL, "ob", &ob, 45 TRI, "tri", &tri); 46 47 g_assert (result || 48 (mb == FALSE && ob == FALSE && tri != TRUE && tri != FALSE)); 49 50 if (tri != FALSE && tri != TRUE) 51 tri = -1; 52 53 g_string_append_printf (string, "<bool(%d) %d %d %d>", 54 result, mb, ob, tri); 55 } 56 57 else if (strcmp (element_name, "str") == 0) 58 { 59 const char *cm, *co; 60 char *am, *ao; 61 62 result = collect (STR, "cm", &cm, 63 STRDUP, "am", &am, 64 OPTDUP, "ao", &ao, 65 OPTSTR, "co", &co); 66 67 g_assert (result || 68 (cm == NULL && am == NULL && ao == NULL && co == NULL)); 69 70 g_string_append_printf (string, "<str(%d) %s %s %s %s>", 71 result, n (cm), n (am), n (ao), n (co)); 72 73 g_free (am); 74 g_free (ao); 75 } 76 } 77 78 static GMarkupParser parser = { start }; 79 80 struct test 81 { 82 const char *document; 83 const char *result; 84 GMarkupError error_code; 85 const char *error_info; 86 }; 87 88 static struct test tests[] = 89 { 90 { "<bool mb='y'>", "<bool(1) 1 0 -1>", 91 G_MARKUP_ERROR_PARSE, "'bool'" }, 92 93 { "<bool mb='false'/>", "<bool(1) 0 0 -1>" }, 94 { "<bool mb='true'/>", "<bool(1) 1 0 -1>" }, 95 { "<bool mb='t' ob='f' tri='1'/>", "<bool(1) 1 0 1>" }, 96 { "<bool mb='y' ob='n' tri='0'/>", "<bool(1) 1 0 0>" }, 97 98 { "<bool ob='y'/>", "<bool(0) 0 0 -1>", 99 G_MARKUP_ERROR_MISSING_ATTRIBUTE, "'mb'" }, 100 101 { "<bool mb='y' mb='y'/>", "<bool(0) 0 0 -1>", 102 G_MARKUP_ERROR_INVALID_CONTENT, "'mb'" }, 103 104 { "<bool mb='y' tri='y' tri='n'/>", "<bool(0) 0 0 -1>", 105 G_MARKUP_ERROR_INVALID_CONTENT, "'tri'" }, 106 107 { "<str cm='x' am='y'/>", "<str(1) x y (null) (null)>" }, 108 109 { "<str am='x' co='y'/>", "<str(0) (null) (null) (null) (null)>", 110 G_MARKUP_ERROR_MISSING_ATTRIBUTE, "'cm'" }, 111 112 { "<str am='x'/>", "<str(0) (null) (null) (null) (null)>", 113 G_MARKUP_ERROR_MISSING_ATTRIBUTE, "'cm'" }, 114 115 { "<str am='x' cm='x' am='y'/>", "<str(0) (null) (null) (null) (null)>", 116 G_MARKUP_ERROR_INVALID_CONTENT, "'am'" }, 117 118 { "<str am='x' qm='y' cm='x'/>", "<str(0) (null) (null) (null) (null)>", 119 G_MARKUP_ERROR_UNKNOWN_ATTRIBUTE, "'qm'" }, 120 121 { "<str am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' cm='x'/>", "<str(0) (null) (null) (null) (null)>", 122 G_MARKUP_ERROR_INVALID_CONTENT, "'am'" }, 123 124 { "<str cm='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x'/>", "<str(0) (null) (null) (null) (null)>", 125 G_MARKUP_ERROR_INVALID_CONTENT, "'am'" }, 126 127 { "<str a='x' b='x' c='x' d='x' e='x' f='x' g='x' h='x' i='x' j='x' k='x' l='x' m='x' n='x' o='x' p='x' q='x' r='x' s='x' t='x' u='x' v='x' w='x' x='x' y='x' z='x' aa='x' bb='x' cc='x' dd='x' ee='x' ff='x' gg='x' hh='x' ii='x' jj='x' kk='x' ll='x' mm='x' nn='x' oo='x' pp='x' qq='x' rr='x' ss='x' tt='x' uu='x' vv='x' ww='x' xx='x' yy='x' zz='x' am='x' cm='x'/>", 128 "<str(0) (null) (null) (null) (null)>", 129 G_MARKUP_ERROR_UNKNOWN_ATTRIBUTE, "'a'" }, 130 131 { "<bool mb='ja'/>", "<bool(0) 0 0 -1>", 132 G_MARKUP_ERROR_INVALID_CONTENT, "'mb'" }, 133 134 { "<bool mb='nein'/>", "<bool(0) 0 0 -1>", 135 G_MARKUP_ERROR_INVALID_CONTENT, "'mb'" } 136 }; 137 138 int 139 main (int argc, char **argv) 140 { 141 gboolean verbose = FALSE; 142 int i; 143 144 if (argc > 1) 145 { 146 if (argc != 2 || strcmp (argv[1], "-v") != 0) 147 { 148 g_print ("error: call with no arguments or '-v' for verbose\n"); 149 return 1; 150 } 151 152 verbose = TRUE; 153 } 154 155 for (i = 0; i < G_N_ELEMENTS (tests); i++) 156 { 157 GMarkupParseContext *ctx; 158 GError *error = NULL; 159 GString *string; 160 gboolean result; 161 162 string = g_string_new (""); 163 ctx = g_markup_parse_context_new (&parser, 0, string, NULL); 164 result = g_markup_parse_context_parse (ctx, 165 tests[i].document, 166 -1, &error); 167 if (result) 168 result = g_markup_parse_context_end_parse (ctx, &error); 169 170 if (verbose) 171 g_print ("%d: %s:\n (error %d, \"%s\")\n %s\n\n", 172 i, tests[i].document, 173 error ? error->code : 0, 174 error ? error->message : "(no error)", 175 string->str); 176 177 if (result) 178 { 179 if (error != NULL) 180 g_error ("parser successful but error is set: " 181 "%s(%d) '%s'", g_quark_to_string (error->domain), 182 error->code, error->message); 183 184 if (tests[i].error_code != 0) 185 g_error ("parser succeeded on test %d ('%s') but " 186 "we expected a failure with code %d\n", i, 187 tests[i].document, tests[i].error_code); 188 } 189 else 190 { 191 if (error->domain != G_MARKUP_ERROR) 192 g_error ("error occured on test %d ('%s') but is not in " 193 "the GMarkupError domain, but rather '%s'", i, 194 tests[i].document, g_quark_to_string (error->domain)); 195 196 if (error->code != tests[i].error_code) 197 g_error ("failure expected with test %d ('%s') but it " 198 "has error code %d (we expected code %d)", i, 199 tests[i].document, error->code, tests[i].error_code); 200 201 if (strstr (error->message, tests[i].error_info) == NULL) 202 g_error ("failure message on test %d ('%s') fails " 203 "to mention '%s' in the error message", i, 204 tests[i].document, tests[i].error_info); 205 } 206 207 if (strcmp (tests[i].result, string->str) != 0) 208 g_error ("result on test %d ('%s') expected to be '%s' " 209 "but came out as '%s'", i, tests[i].document, 210 tests[i].result, string->str); 211 212 g_markup_parse_context_free (ctx); 213 g_string_free (string, TRUE); 214 g_clear_error (&error); 215 } 216 217 if (verbose) 218 g_print ("\n*** all tests passed ***\n\n"); 219 220 return 0; 221 } 222