Add support for false-positives, etc.
1.1 --- a/test/harness/Makefile.am Thu Feb 02 23:32:12 2012 +0000
1.2 +++ b/test/harness/Makefile.am Mon Feb 06 23:55:27 2012 +0000
1.3 @@ -5,5 +5,5 @@
1.4
1.5 loupe_test_SOURCES=loupe-test.c testcase.c testcase.h testcaseio.c \
1.6 testcaseio.h testcaseparser.c testcaseparser.h testcaseinput.c \
1.7 - testcaseinput.h
1.8 + testcaseinput.h warningsparser.c warningsparser.h
1.9 loupe_test_LDADD=../../bl/libbl.la
2.1 --- a/test/harness/testcase.c Thu Feb 02 23:32:12 2012 +0000
2.2 +++ b/test/harness/testcase.c Mon Feb 06 23:55:27 2012 +0000
2.3 @@ -239,6 +239,218 @@
2.4 }
2.5
2.6 /*
2.7 + * Parse a warning of the form:
2.8 + * [blank line]
2.9 + * <echoed line> (ignored)
2.10 + * " Line " <number> [" column " <number>] " - " <text> "\n"
2.11 + * If not specified, the column is returned as 0.
2.12 + * Returns: the number of bytes parsed, or -1 on error.
2.13 + */
2.14 +static ssize_t testcase_parse_warning(Testcase *testcase,const char *output,
2.15 + guint *line,guint *column,char **text)
2.16 +{
2.17 + ssize_t offset=0;
2.18 + guint64 tmp;
2.19 + char *s,*endp;
2.20 + if (output[offset]!='\n')
2.21 + {
2.22 + g_print("%s: FAIL\n",testcase->basename);
2.23 + g_print("Unexpected output from bookloupe:\n");
2.24 + print_unexpected(output,offset);
2.25 + return -1;
2.26 + }
2.27 + offset++;
2.28 + s=strchr(output+offset,'\n');
2.29 + if (!s)
2.30 + {
2.31 + g_print("%s: FAIL\n",testcase->basename);
2.32 + g_print("Missing new-line in output from bookloupe:\n");
2.33 + print_unexpected(output,offset);
2.34 + return -1;
2.35 + }
2.36 + offset=s-output+1;
2.37 + if (!g_str_has_prefix(output+offset," Line "))
2.38 + {
2.39 + g_print("%s: FAIL\n",testcase->basename);
2.40 + g_print("Unexpected output from bookloupe:\n");
2.41 + offset+=common_prefix_length(output+offset," Line ");
2.42 + print_unexpected(output,offset);
2.43 + return -1;
2.44 + }
2.45 + offset+=9;
2.46 + tmp=g_ascii_strtoull(output+offset,&endp,10);
2.47 + if (tmp<1 || tmp>G_MAXUINT || tmp==G_MAXUINT64)
2.48 + {
2.49 + g_print("%s: FAIL\n",testcase->basename);
2.50 + g_print("Unexpected output from bookloupe:\n");
2.51 + print_unexpected(output,offset);
2.52 + return -1;
2.53 + }
2.54 + *line=tmp;
2.55 + offset=endp-output;
2.56 + if (g_str_has_prefix(output+offset," column "))
2.57 + {
2.58 + offset+=8;
2.59 + tmp=g_ascii_strtoull(output+offset,&endp,10);
2.60 + if (tmp<1 || tmp>G_MAXUINT || tmp==G_MAXUINT64)
2.61 + {
2.62 + g_print("%s: FAIL\n",testcase->basename);
2.63 + g_print("Unexpected output from bookloupe:\n");
2.64 + print_unexpected(output,offset);
2.65 + return -1;
2.66 + }
2.67 + *column=tmp;
2.68 + offset=endp-output;
2.69 + }
2.70 + else
2.71 + *column=0;
2.72 + if (!g_str_has_prefix(output+offset," - "))
2.73 + {
2.74 + g_print("%s: FAIL\n",testcase->basename);
2.75 + g_print("Unexpected output from bookloupe:\n");
2.76 + offset+=common_prefix_length(output+offset," - ");
2.77 + print_unexpected(output,offset);
2.78 + return -1;
2.79 + }
2.80 + offset+=3;
2.81 + s=strchr(output+offset,'\n');
2.82 + if (!s)
2.83 + {
2.84 + g_print("%s: FAIL\n",testcase->basename);
2.85 + g_print("Missing new-line in output from bookloupe:\n");
2.86 + print_unexpected(output,offset);
2.87 + return -1;
2.88 + }
2.89 + *text=g_strndup(output+offset,s-(output+offset));
2.90 + return s-output+1;
2.91 +}
2.92 +
2.93 +/*
2.94 + * Check the warnings produced by bookloupe against either the
2.95 + * unstructured testcase->expected or the structured testcase->warnings
2.96 + * as appropriate.
2.97 + */
2.98 +static gboolean testcase_check_warnings(Testcase *testcase,const char *output,
2.99 + char **xfail)
2.100 +{
2.101 + gboolean r=TRUE;
2.102 + size_t offset;
2.103 + ssize_t off;
2.104 + int i,count_false_positive,count_false_negative;
2.105 + int total_false_positive,total_false_negative;
2.106 + char *text;
2.107 + guint *counts,line,column;
2.108 + GSList *link,*link2;
2.109 + TestcaseWarning *warning;
2.110 + TestcaseLocation *location;
2.111 + *xfail=NULL;
2.112 + if (testcase->expected)
2.113 + {
2.114 + if (strcmp(output,testcase->expected))
2.115 + {
2.116 + g_print("%s: FAIL\n",testcase->basename);
2.117 + offset=common_prefix_length(output,testcase->expected);
2.118 + if (!offset && !output[offset])
2.119 + g_print("Unexpected zero warnings from bookloupe.\n");
2.120 + else
2.121 + {
2.122 + g_print("Unexpected output from bookloupe:\n");
2.123 + print_unexpected(output,offset);
2.124 + }
2.125 + return FALSE;
2.126 + }
2.127 + return TRUE;
2.128 + }
2.129 + counts=g_new0(guint,g_slist_length(testcase->warnings));
2.130 + for(offset=0;output[offset];)
2.131 + {
2.132 + off=testcase_parse_warning(testcase,output+offset,&line,&column,&text);
2.133 + if (off<0)
2.134 + {
2.135 + r=FALSE;
2.136 + break;
2.137 + }
2.138 + offset+=off;
2.139 + for(link=testcase->warnings,i=0;link;link=link->next,i++)
2.140 + {
2.141 + warning=link->data;
2.142 + if (strcmp(warning->text,text))
2.143 + continue;
2.144 + for(link2=warning->locations;link2;link2=link2->next)
2.145 + {
2.146 + location=link2->data;
2.147 + if (location->line!=line || location->column!=column)
2.148 + continue;
2.149 + counts[i]++;
2.150 + break;
2.151 + }
2.152 + if (link2)
2.153 + break;
2.154 + }
2.155 + if (!link)
2.156 + {
2.157 + g_print("%s: FAIL\n",testcase->basename);
2.158 + g_print("Unexpected warning from bookloupe:\n");
2.159 + if (column)
2.160 + g_print(" Line %u column %u - %s\n",line,column,text);
2.161 + else
2.162 + g_print(" Line %u - %s\n",line,text);
2.163 + r=FALSE;
2.164 + g_free(text);
2.165 + break;
2.166 + }
2.167 + g_free(text);
2.168 + }
2.169 + count_false_positive=total_false_positive=0;
2.170 + count_false_negative=total_false_negative=0;
2.171 + for(link=testcase->warnings,i=0;r && link;link=link->next,i++)
2.172 + {
2.173 + warning=link->data;
2.174 + if (!counts[i] && warning->is_real && !warning->xfail)
2.175 + {
2.176 + location=warning->locations->data;
2.177 + g_print("%s: FAIL\n",testcase->basename);
2.178 + g_print("Missing warning from bookloupe:\n");
2.179 + if (location->column)
2.180 + g_print(" Line %u column %u - %s\n",location->line,
2.181 + location->column,warning->text);
2.182 + else
2.183 + g_print(" Line %u - %s\n",location->line,warning->text);
2.184 + r=FALSE;
2.185 + break;
2.186 + }
2.187 + else if (warning->xfail)
2.188 + {
2.189 + if (warning->is_real)
2.190 + {
2.191 + total_false_negative++;
2.192 + if (!counts[i])
2.193 + count_false_negative++;
2.194 + }
2.195 + else if (!warning->is_real)
2.196 + {
2.197 + total_false_positive++;
2.198 + if (counts[i])
2.199 + count_false_positive++;
2.200 + }
2.201 + }
2.202 + }
2.203 + g_free(counts);
2.204 + if (count_false_positive && count_false_negative)
2.205 + *xfail=g_strdup_printf(
2.206 + "with %d of %d false positives and %d of %d false negatives",
2.207 + count_false_positive,total_false_positive,
2.208 + count_false_negative,total_false_negative);
2.209 + else if (count_false_positive)
2.210 + *xfail=g_strdup_printf("with %d of %d false positives",
2.211 + count_false_positive,total_false_positive);
2.212 + else if (count_false_negative)
2.213 + *xfail=g_strdup_printf("with %d of %d false negatives",
2.214 + count_false_negative,total_false_negative);
2.215 + return r;
2.216 +}
2.217 +
2.218 +/*
2.219 * Run a testcase, returning FALSE on fail or error and
2.220 * TRUE on pass or expected-fail.
2.221 * Suitable message(s) will be printed in all cases.
2.222 @@ -247,8 +459,8 @@
2.223 {
2.224 gboolean r;
2.225 size_t pos,offset;
2.226 - GString *header,*expected;
2.227 - char *output,*filename,*s;
2.228 + GString *header;
2.229 + char *output,*filename,*s,*xfail=NULL;
2.230 GError *error=NULL;
2.231 if (!testcase_create_input_files(testcase,&error))
2.232 {
2.233 @@ -257,7 +469,7 @@
2.234 g_error_free(error);
2.235 return FALSE;
2.236 }
2.237 - if (testcase->expected)
2.238 + if (testcase->expected || testcase->warnings)
2.239 r=testcase_spawn_bookloupe(testcase,&output,&error);
2.240 else
2.241 {
2.242 @@ -280,17 +492,16 @@
2.243 g_error_free(error);
2.244 return FALSE;
2.245 }
2.246 - if (testcase->expected)
2.247 + if (testcase->expected || testcase->warnings)
2.248 {
2.249 header=g_string_new("\n\nFile: ");
2.250 g_string_append(header,filename);
2.251 g_string_append(header,"\n");
2.252 - expected=g_string_new(testcase->expected);
2.253 if (!g_str_has_prefix(output,header->str))
2.254 {
2.255 g_print("%s: FAIL\n",testcase->basename);
2.256 + g_print("Unexpected header from bookloupe:\n");
2.257 offset=common_prefix_length(output,header->str);
2.258 - g_print("Unexpected header from bookloupe:\n");
2.259 print_unexpected(output,offset);
2.260 r=FALSE;
2.261 }
2.262 @@ -304,36 +515,39 @@
2.263 else
2.264 {
2.265 g_print("%s: FAIL\n",testcase->basename);
2.266 - offset=common_prefix_length(output,header->str);
2.267 g_print("Unterminated summary from bookloupe:\n%s\n",
2.268 output+pos);
2.269 r=FALSE;
2.270 }
2.271 }
2.272 - if (r && strcmp(output+pos,expected->str))
2.273 - {
2.274 - g_print("%s: FAIL\n",testcase->basename);
2.275 - offset=common_prefix_length(output+pos,expected->str);
2.276 - if (!offset && !output[pos+offset])
2.277 - g_print("Unexpected zero warnings from bookloupe.\n");
2.278 - else
2.279 - {
2.280 - g_print("Unexpected output from bookloupe:\n");
2.281 - print_unexpected(output+pos,offset);
2.282 - }
2.283 - r=FALSE;
2.284 - }
2.285 g_string_free(header,TRUE);
2.286 - g_string_free(expected,TRUE);
2.287 + r=testcase_check_warnings(testcase,output+pos,&xfail);
2.288 }
2.289 g_free(filename);
2.290 g_free(output);
2.291 if (r)
2.292 - g_print("%s: PASS\n",testcase->basename);
2.293 + {
2.294 + if (xfail)
2.295 + g_print("%s: PASS (%s)\n",testcase->basename,xfail);
2.296 + else
2.297 + g_print("%s: PASS\n",testcase->basename);
2.298 + }
2.299 + g_free(xfail);
2.300 return r;
2.301 }
2.302
2.303 /*
2.304 + * Free a testcase warning.
2.305 + */
2.306 +void testcase_warning_free(TestcaseWarning *warning)
2.307 +{
2.308 + g_slist_foreach(warning->locations,(GFunc)g_free,NULL);
2.309 + g_slist_free(warning->locations);
2.310 + g_free(warning->text);
2.311 + g_free(warning);
2.312 +}
2.313 +
2.314 +/*
2.315 * Free a testcase.
2.316 */
2.317 void testcase_free(Testcase *testcase)
2.318 @@ -342,6 +556,8 @@
2.319 g_slist_foreach(testcase->inputs,(GFunc)testcase_input_free,NULL);
2.320 g_slist_free(testcase->inputs);
2.321 g_free(testcase->expected);
2.322 + g_slist_foreach(testcase->warnings,(GFunc)testcase_warning_free,NULL);
2.323 + g_slist_free(testcase->warnings);
2.324 g_free(testcase->encoding);
2.325 g_strfreev(testcase->options);
2.326 g_free(testcase);
3.1 --- a/test/harness/testcase.h Thu Feb 02 23:32:12 2012 +0000
3.2 +++ b/test/harness/testcase.h Mon Feb 06 23:55:27 2012 +0000
3.3 @@ -10,10 +10,35 @@
3.4 } TestcaseError;
3.5
3.6 typedef struct {
3.7 + guint line;
3.8 + guint column; /* or 0 for unspecified */
3.9 +} TestcaseLocation;
3.10 +
3.11 +typedef struct {
3.12 + /*
3.13 + * Does this warning relate to a real problem in the etext
3.14 + * (eg., error and false-negative).
3.15 + */
3.16 + gboolean is_real;
3.17 + /*
3.18 + * Do we "expect" BOOKLOUPE to get this wrong
3.19 + * (eg., false-negative and false-positive)
3.20 + */
3.21 + gboolean xfail;
3.22 + /*
3.23 + * For real problems, the first location should be the
3.24 + * actual location of the problem.
3.25 + */
3.26 + GSList *locations;
3.27 + char *text;
3.28 +} TestcaseWarning;
3.29 +
3.30 +typedef struct {
3.31 char *basename;
3.32 char *tmpdir;
3.33 GSList *inputs;
3.34 char *expected;
3.35 + GSList *warnings;
3.36 char *encoding; /* The character encoding to talk to BOOKLOUPE in */
3.37 char **options;
3.38 enum {
4.1 --- a/test/harness/testcaseio.c Thu Feb 02 23:32:12 2012 +0000
4.2 +++ b/test/harness/testcaseio.c Mon Feb 06 23:55:27 2012 +0000
4.3 @@ -6,6 +6,7 @@
4.4 #include "testcaseparser.h"
4.5 #include "testcaseinput.h"
4.6 #include "testcaseio.h"
4.7 +#include "warningsparser.h"
4.8
4.9 /*
4.10 * Read a testcase in from a file.
4.11 @@ -17,6 +18,8 @@
4.12 Testcase *testcase;
4.13 TestcaseParser *parser;
4.14 TestcaseInput *input=NULL;
4.15 + GMarkupParseContext *context;
4.16 + GError *err=NULL;
4.17 char *s,*arg;
4.18 const char *tag,*text;
4.19 gboolean found_tag=FALSE;
4.20 @@ -64,8 +67,25 @@
4.21 testcase->flags|=TESTCASE_TMP_DIR;
4.22 g_free(arg);
4.23 }
4.24 - else if (!testcase->expected && !strcmp(tag,"EXPECTED"))
4.25 + else if (!testcase->expected && !testcase->warnings &&
4.26 + !strcmp(tag,"EXPECTED"))
4.27 testcase->expected=g_strdup(text);
4.28 + else if (!testcase->expected && !testcase->warnings &&
4.29 + !strcmp(tag,"WARNINGS"))
4.30 + {
4.31 + context=warnings_parse_context_new(testcase);
4.32 + if (!g_markup_parse_context_parse(context,text,-1,&err) ||
4.33 + !g_markup_parse_context_end_parse(context,&err))
4.34 + {
4.35 + g_markup_parse_context_free(context);
4.36 + g_printerr("%s\n",err->message);
4.37 + g_clear_error(&err);
4.38 + testcase_free(testcase);
4.39 + testcase_parser_free(parser);
4.40 + return NULL;
4.41 + }
4.42 + g_markup_parse_context_free(context);
4.43 + }
4.44 else if (!testcase->encoding && !strcmp(tag,"ENCODING"))
4.45 testcase->encoding=g_strchomp(g_strdup(text));
4.46 else if (!testcase->encoding && !strcmp(tag,"OPTIONS"))
5.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
5.2 +++ b/test/harness/warningsparser.c Mon Feb 06 23:55:27 2012 +0000
5.3 @@ -0,0 +1,244 @@
5.4 +#include <stdlib.h>
5.5 +#include <string.h>
5.6 +#include <glib.h>
5.7 +#include "testcase.h"
5.8 +#include "warningsparser.h"
5.9 +
5.10 +/*
5.11 + * A GMarkupParser for the contents of a WARNINGS tag.
5.12 + */
5.13 +
5.14 +typedef struct {
5.15 + Testcase *testcase;
5.16 + TestcaseWarning *warning;
5.17 + TestcaseLocation *location;
5.18 + enum {
5.19 + WARNINGS_INIT,
5.20 + WARNINGS_IN_EXPECTED,
5.21 + WARNINGS_IN_WARNING,
5.22 + WARNINGS_IN_AT,
5.23 + WARNINGS_IN_TEXT,
5.24 + WARNINGS_DONE,
5.25 + } state;
5.26 +} WarningsBaton;
5.27 +
5.28 +static void warnings_parser_start_element(GMarkupParseContext *context,
5.29 + const char *element_name,const char **attribute_names,
5.30 + const char **attribute_values,void *user_data,GError **error)
5.31 +{
5.32 + int i;
5.33 + guint64 tmp;
5.34 + char *endp;
5.35 + WarningsBaton *baton=user_data;
5.36 + switch(baton->state)
5.37 + {
5.38 + case WARNINGS_INIT:
5.39 + if (strcmp(element_name,"expected"))
5.40 + g_set_error(error,G_MARKUP_ERROR,G_MARKUP_ERROR_UNKNOWN_ELEMENT,
5.41 + "Unknown root element: '%s'",element_name);
5.42 + else if (attribute_names[0])
5.43 + g_set_error(error,G_MARKUP_ERROR,
5.44 + G_MARKUP_ERROR_UNKNOWN_ATTRIBUTE,
5.45 + "Unknown attribute on element 'expected': '%s'",
5.46 + attribute_names[0]);
5.47 + else
5.48 + baton->state=WARNINGS_IN_EXPECTED;
5.49 + break;
5.50 + case WARNINGS_IN_EXPECTED:
5.51 + baton->warning=g_new0(TestcaseWarning,1);
5.52 + if (!strcmp(element_name,"error"))
5.53 + baton->warning->is_real=TRUE;
5.54 + else if (!strcmp(element_name,"false-positive"))
5.55 + baton->warning->xfail=TRUE;
5.56 + else if (!strcmp(element_name,"false-negative"))
5.57 + baton->warning->is_real=baton->warning->xfail=TRUE;
5.58 + else
5.59 + {
5.60 + g_set_error(error,G_MARKUP_ERROR,G_MARKUP_ERROR_UNKNOWN_ELEMENT,
5.61 + "Unknown element in 'expected': '%s'",element_name);
5.62 + g_free(baton->warning);
5.63 + baton->warning=NULL;
5.64 + return;
5.65 + }
5.66 + if (attribute_names[0])
5.67 + {
5.68 + g_set_error(error,G_MARKUP_ERROR,
5.69 + G_MARKUP_ERROR_UNKNOWN_ATTRIBUTE,
5.70 + "Unknown attribute on element '%s': '%s'",element_name,
5.71 + attribute_names[0]);
5.72 + g_free(baton->warning);
5.73 + baton->warning=NULL;
5.74 + return;
5.75 + }
5.76 + else
5.77 + baton->state=WARNINGS_IN_WARNING;
5.78 + break;
5.79 + case WARNINGS_IN_WARNING:
5.80 + if (!strcmp(element_name,"at"))
5.81 + {
5.82 + baton->location=g_new0(TestcaseLocation,1);
5.83 + for(i=0;attribute_names[i];i++)
5.84 + {
5.85 + if (!strcmp(attribute_names[i],"line"))
5.86 + {
5.87 + tmp=g_ascii_strtoull(attribute_values[i],&endp,0);
5.88 + if (tmp<1 || tmp>G_MAXUINT || tmp==G_MAXUINT64)
5.89 + {
5.90 + g_set_error(error,G_MARKUP_ERROR,
5.91 + G_MARKUP_ERROR_INVALID_CONTENT,"Invalid value "
5.92 + "for attribute 'line' on element '%s': '%s'",
5.93 + element_name,attribute_values[i]);
5.94 + return;
5.95 + }
5.96 + baton->location->line=(guint)tmp;
5.97 + }
5.98 + else if (!strcmp(attribute_names[i],"column"))
5.99 + {
5.100 + tmp=g_ascii_strtoull(attribute_values[i],&endp,0);
5.101 + if (tmp<1 || tmp>G_MAXUINT || tmp==G_MAXUINT64)
5.102 + {
5.103 + g_set_error(error,G_MARKUP_ERROR,
5.104 + G_MARKUP_ERROR_INVALID_CONTENT,"Invalid value "
5.105 + "for attribute 'column' on element '%s': '%s'",
5.106 + element_name,attribute_values[i]);
5.107 + return;
5.108 + }
5.109 + baton->location->column=(guint)tmp;
5.110 + }
5.111 + else
5.112 + {
5.113 + g_set_error(error,G_MARKUP_ERROR,
5.114 + G_MARKUP_ERROR_UNKNOWN_ATTRIBUTE,
5.115 + "Unknown attribute on element '%s': '%s'",
5.116 + element_name,attribute_names[i]);
5.117 + return;
5.118 + }
5.119 + }
5.120 + if (!baton->location->line)
5.121 + {
5.122 + g_set_error(error,G_MARKUP_ERROR,
5.123 + G_MARKUP_ERROR_MISSING_ATTRIBUTE,
5.124 + "Missing attribute on element '%s': 'line'",element_name);
5.125 + return;
5.126 + }
5.127 + baton->state=WARNINGS_IN_AT;
5.128 + }
5.129 + else if (!strcmp(element_name,"text"))
5.130 + {
5.131 + if (attribute_names[0])
5.132 + {
5.133 + g_set_error(error,G_MARKUP_ERROR,
5.134 + G_MARKUP_ERROR_UNKNOWN_ATTRIBUTE,
5.135 + "Unknown attribute on element 'text': '%s'",
5.136 + attribute_names[0]);
5.137 + return;
5.138 + }
5.139 + baton->state=WARNINGS_IN_TEXT;
5.140 + }
5.141 + break;
5.142 + case WARNINGS_IN_AT:
5.143 + g_set_error(error,G_MARKUP_ERROR,G_MARKUP_ERROR_UNKNOWN_ELEMENT,
5.144 + "Unknown element in 'at': '%s'",element_name);
5.145 + return;
5.146 + case WARNINGS_IN_TEXT:
5.147 + g_set_error(error,G_MARKUP_ERROR,G_MARKUP_ERROR_UNKNOWN_ELEMENT,
5.148 + "Unknown element in 'text': '%s'",element_name);
5.149 + return;
5.150 + default:
5.151 + g_set_error(error,G_MARKUP_ERROR,G_MARKUP_ERROR_UNKNOWN_ELEMENT,
5.152 + "Unexpected element: '%s'",element_name);
5.153 + return;
5.154 + }
5.155 +}
5.156 +
5.157 +static void warnings_parser_end_element(GMarkupParseContext *context,
5.158 + const char *element_name,void *user_data,GError **error)
5.159 +{
5.160 + WarningsBaton *baton=user_data;
5.161 + switch(baton->state)
5.162 + {
5.163 + case WARNINGS_IN_EXPECTED:
5.164 + baton->testcase->warnings=
5.165 + g_slist_reverse(baton->testcase->warnings);
5.166 + baton->state=WARNINGS_DONE;
5.167 + break;
5.168 + case WARNINGS_IN_WARNING:
5.169 + baton->warning->locations=
5.170 + g_slist_reverse(baton->warning->locations);
5.171 + baton->testcase->warnings=g_slist_prepend(baton->testcase->warnings,
5.172 + baton->warning);
5.173 + baton->warning=NULL;
5.174 + baton->state=WARNINGS_IN_EXPECTED;
5.175 + break;
5.176 + case WARNINGS_IN_AT:
5.177 + baton->warning->locations=g_slist_prepend(baton->warning->locations,
5.178 + baton->location);
5.179 + baton->location=NULL;
5.180 + baton->state=WARNINGS_IN_WARNING;
5.181 + break;
5.182 + case WARNINGS_IN_TEXT:
5.183 + baton->state=WARNINGS_IN_WARNING;
5.184 + break;
5.185 + default:
5.186 + g_set_error(error,G_MARKUP_ERROR,G_MARKUP_ERROR_UNKNOWN_ELEMENT,
5.187 + "Unexpected element ending: '%s'",element_name);
5.188 + return;
5.189 + }
5.190 +}
5.191 +
5.192 +static void warnings_parser_text(GMarkupParseContext *context,
5.193 + const char *text,gsize text_len,void *user_data,GError **error)
5.194 +{
5.195 + char *s,*t;
5.196 + WarningsBaton *baton=user_data;
5.197 + switch(baton->state)
5.198 + {
5.199 + case WARNINGS_IN_EXPECTED:
5.200 + if (strspn(text," \t\n")!=text_len)
5.201 + g_set_error(error,G_MARKUP_ERROR,G_MARKUP_ERROR_INVALID_CONTENT,
5.202 + "The 'expected' tag does not take any content");
5.203 + break;
5.204 + case WARNINGS_IN_WARNING:
5.205 + if (strspn(text," \t\n")!=text_len)
5.206 + g_set_error(error,G_MARKUP_ERROR,G_MARKUP_ERROR_INVALID_CONTENT,
5.207 + "The warning tags do not take any content");
5.208 + break;
5.209 + case WARNINGS_IN_AT:
5.210 + if (strspn(text," \t\n")!=text_len)
5.211 + g_set_error(error,G_MARKUP_ERROR,G_MARKUP_ERROR_INVALID_CONTENT,
5.212 + "The 'at' tag does not take any content");
5.213 + break;
5.214 + case WARNINGS_IN_TEXT:
5.215 + s=g_strdup(text+strspn(text," \t\n"));
5.216 + g_strchomp(s);
5.217 + if (baton->warning->text)
5.218 + {
5.219 + t=g_strconcat(baton->warning->text,s,NULL);
5.220 + g_free(baton->warning->text);
5.221 + g_free(s);
5.222 + baton->warning->text=t;
5.223 + }
5.224 + else
5.225 + baton->warning->text=s;
5.226 + break;
5.227 + default:
5.228 + g_set_error(error,G_MARKUP_ERROR,G_MARKUP_ERROR_INVALID_CONTENT,
5.229 + "Unexpected content: '%s'",text);
5.230 + return;
5.231 + }
5.232 +}
5.233 +
5.234 +GMarkupParseContext *warnings_parse_context_new(Testcase *testcase)
5.235 +{
5.236 + static GMarkupParser parser={0};
5.237 + WarningsBaton *baton;
5.238 + parser.start_element=warnings_parser_start_element;
5.239 + parser.end_element=warnings_parser_end_element;
5.240 + parser.text=warnings_parser_text;
5.241 + baton=g_new0(WarningsBaton,1);
5.242 + baton->testcase=testcase;
5.243 + baton->state=WARNINGS_INIT;
5.244 + return g_markup_parse_context_new(&parser,
5.245 + G_MARKUP_TREAT_CDATA_AS_TEXT|G_MARKUP_PREFIX_ERROR_POSITION,
5.246 + baton,g_free);
5.247 +}