test/harness/warningsparser.c
author ali <ali@juiblex.co.uk>
Wed Oct 16 22:51:29 2013 +0100 (2013-10-16)
changeset 104 70cc629ec1e0
parent 17 2c88fd553e5d
permissions -rw-r--r--
Fix bug #28: Don't report ., as double punctuation after "etc" or "&c"
ali@17
     1
#include <stdlib.h>
ali@17
     2
#include <string.h>
ali@17
     3
#include <glib.h>
ali@17
     4
#include "testcase.h"
ali@17
     5
#include "warningsparser.h"
ali@17
     6
ali@17
     7
/*
ali@17
     8
 * A GMarkupParser for the contents of a WARNINGS tag.
ali@17
     9
 */
ali@17
    10
ali@17
    11
typedef struct {
ali@17
    12
    Testcase *testcase;
ali@17
    13
    TestcaseWarning *warning;
ali@17
    14
    TestcaseLocation *location;
ali@17
    15
    enum {
ali@17
    16
	WARNINGS_INIT,
ali@17
    17
	WARNINGS_IN_EXPECTED,
ali@101
    18
	WARNINGS_IN_SUMMARY,
ali@17
    19
	WARNINGS_IN_WARNING,
ali@17
    20
	WARNINGS_IN_AT,
ali@17
    21
	WARNINGS_IN_TEXT,
ali@17
    22
	WARNINGS_DONE,
ali@101
    23
    } state,parent_state;
ali@17
    24
} WarningsBaton;
ali@17
    25
ali@17
    26
static void warnings_parser_start_element(GMarkupParseContext *context,
ali@17
    27
  const char *element_name,const char **attribute_names,
ali@17
    28
  const char **attribute_values,void *user_data,GError **error)
ali@17
    29
{
ali@17
    30
    int i;
ali@17
    31
    guint64 tmp;
ali@17
    32
    char *endp;
ali@17
    33
    WarningsBaton *baton=user_data;
ali@101
    34
    baton->parent_state=baton->state;
ali@17
    35
    switch(baton->state)
ali@17
    36
    {
ali@17
    37
	case WARNINGS_INIT:
ali@17
    38
	    if (strcmp(element_name,"expected"))
ali@17
    39
		g_set_error(error,G_MARKUP_ERROR,G_MARKUP_ERROR_UNKNOWN_ELEMENT,
ali@17
    40
		  "Unknown root element: '%s'",element_name);
ali@17
    41
	    else if (attribute_names[0])
ali@17
    42
		g_set_error(error,G_MARKUP_ERROR,
ali@17
    43
		  G_MARKUP_ERROR_UNKNOWN_ATTRIBUTE,
ali@17
    44
		  "Unknown attribute on element 'expected': '%s'",
ali@17
    45
		  attribute_names[0]);
ali@17
    46
	    else
ali@17
    47
		baton->state=WARNINGS_IN_EXPECTED;
ali@17
    48
	    break;
ali@17
    49
	case WARNINGS_IN_EXPECTED:
ali@101
    50
	    if (!strcmp(element_name,"summary"))
ali@101
    51
	    {
ali@101
    52
		if (baton->testcase->summary.texts)
ali@101
    53
		{
ali@101
    54
		    g_set_error(error,G_MARKUP_ERROR,
ali@101
    55
		      G_MARKUP_ERROR_INVALID_CONTENT,"Multiple summary "
ali@101
    56
		      "elements are not valid");
ali@101
    57
		}
ali@101
    58
		else
ali@101
    59
		    baton->state=WARNINGS_IN_SUMMARY;
ali@101
    60
	    }
ali@17
    61
	    else
ali@17
    62
	    {
ali@101
    63
		baton->warning=g_new0(TestcaseWarning,1);
ali@101
    64
		if (!strcmp(element_name,"error"))
ali@101
    65
		    baton->warning->is_real=TRUE;
ali@101
    66
		else if (!strcmp(element_name,"false-positive"))
ali@101
    67
		    baton->warning->xfail=TRUE;
ali@101
    68
		else if (!strcmp(element_name,"false-negative"))
ali@101
    69
		    baton->warning->is_real=baton->warning->xfail=TRUE;
ali@101
    70
		else
ali@101
    71
		{
ali@101
    72
		    g_set_error(error,G_MARKUP_ERROR,
ali@101
    73
		      G_MARKUP_ERROR_UNKNOWN_ELEMENT,
ali@101
    74
		      "Unknown element in 'expected': '%s'",element_name);
ali@101
    75
		    g_free(baton->warning);
ali@101
    76
		    baton->warning=NULL;
ali@101
    77
		    return;
ali@101
    78
		}
ali@101
    79
		baton->state=WARNINGS_IN_WARNING;
ali@17
    80
	    }
ali@17
    81
	    if (attribute_names[0])
ali@17
    82
	    {
ali@17
    83
		g_set_error(error,G_MARKUP_ERROR,
ali@17
    84
		  G_MARKUP_ERROR_UNKNOWN_ATTRIBUTE,
ali@17
    85
		  "Unknown attribute on element '%s': '%s'",element_name,
ali@17
    86
		  attribute_names[0]);
ali@101
    87
		if (baton->state==WARNINGS_IN_WARNING)
ali@101
    88
		{
ali@101
    89
		    g_free(baton->warning);
ali@101
    90
		    baton->warning=NULL;
ali@101
    91
		}
ali@101
    92
		baton->state=WARNINGS_IN_EXPECTED;
ali@17
    93
		return;
ali@17
    94
	    }
ali@101
    95
	    break;
ali@101
    96
	case WARNINGS_IN_SUMMARY:
ali@101
    97
	    if (!strcmp(element_name,"text"))
ali@101
    98
	    {
ali@101
    99
		if (attribute_names[0])
ali@101
   100
		{
ali@101
   101
		    g_set_error(error,G_MARKUP_ERROR,
ali@101
   102
		      G_MARKUP_ERROR_UNKNOWN_ATTRIBUTE,
ali@101
   103
		      "Unknown attribute on element 'text': '%s'",
ali@101
   104
		      attribute_names[0]);
ali@101
   105
		    return;
ali@101
   106
		}
ali@101
   107
		baton->state=WARNINGS_IN_TEXT;
ali@101
   108
	    }
ali@17
   109
	    break;
ali@17
   110
	case WARNINGS_IN_WARNING:
ali@17
   111
	    if (!strcmp(element_name,"at"))
ali@17
   112
	    {
ali@17
   113
		baton->location=g_new0(TestcaseLocation,1);
ali@17
   114
		for(i=0;attribute_names[i];i++)
ali@17
   115
		{
ali@17
   116
		    if (!strcmp(attribute_names[i],"line"))
ali@17
   117
		    {
ali@17
   118
			tmp=g_ascii_strtoull(attribute_values[i],&endp,0);
ali@17
   119
			if (tmp<1 || tmp>G_MAXUINT || tmp==G_MAXUINT64)
ali@17
   120
			{
ali@17
   121
			    g_set_error(error,G_MARKUP_ERROR,
ali@17
   122
			      G_MARKUP_ERROR_INVALID_CONTENT,"Invalid value "
ali@17
   123
			      "for attribute 'line' on element '%s': '%s'",
ali@17
   124
			      element_name,attribute_values[i]);
ali@17
   125
			    return;
ali@17
   126
			}
ali@17
   127
			baton->location->line=(guint)tmp;
ali@17
   128
		    }
ali@17
   129
		    else if (!strcmp(attribute_names[i],"column"))
ali@17
   130
		    {
ali@17
   131
			tmp=g_ascii_strtoull(attribute_values[i],&endp,0);
ali@17
   132
			if (tmp<1 || tmp>G_MAXUINT || tmp==G_MAXUINT64)
ali@17
   133
			{
ali@17
   134
			    g_set_error(error,G_MARKUP_ERROR,
ali@17
   135
			      G_MARKUP_ERROR_INVALID_CONTENT,"Invalid value "
ali@17
   136
			      "for attribute 'column' on element '%s': '%s'",
ali@17
   137
			      element_name,attribute_values[i]);
ali@17
   138
			    return;
ali@17
   139
			}
ali@17
   140
			baton->location->column=(guint)tmp;
ali@17
   141
		    }
ali@17
   142
		    else
ali@17
   143
		    {
ali@17
   144
			g_set_error(error,G_MARKUP_ERROR,
ali@17
   145
			  G_MARKUP_ERROR_UNKNOWN_ATTRIBUTE,
ali@17
   146
			  "Unknown attribute on element '%s': '%s'",
ali@17
   147
			  element_name,attribute_names[i]);
ali@17
   148
			return;
ali@17
   149
		    }
ali@17
   150
		}
ali@17
   151
		if (!baton->location->line)
ali@17
   152
		{
ali@17
   153
		    g_set_error(error,G_MARKUP_ERROR,
ali@17
   154
		      G_MARKUP_ERROR_MISSING_ATTRIBUTE,
ali@17
   155
		      "Missing attribute on element '%s': 'line'",element_name);
ali@17
   156
		    return;
ali@17
   157
		}
ali@17
   158
		baton->state=WARNINGS_IN_AT;
ali@17
   159
	    }
ali@17
   160
	    else if (!strcmp(element_name,"text"))
ali@17
   161
	    {
ali@17
   162
		if (attribute_names[0])
ali@17
   163
		{
ali@17
   164
		    g_set_error(error,G_MARKUP_ERROR,
ali@17
   165
		      G_MARKUP_ERROR_UNKNOWN_ATTRIBUTE,
ali@17
   166
		      "Unknown attribute on element 'text': '%s'",
ali@17
   167
		      attribute_names[0]);
ali@17
   168
		    return;
ali@17
   169
		}
ali@17
   170
		baton->state=WARNINGS_IN_TEXT;
ali@17
   171
	    }
ali@17
   172
	    break;
ali@17
   173
	case WARNINGS_IN_AT:
ali@17
   174
	    g_set_error(error,G_MARKUP_ERROR,G_MARKUP_ERROR_UNKNOWN_ELEMENT,
ali@17
   175
	      "Unknown element in 'at': '%s'",element_name);
ali@17
   176
	    return;
ali@17
   177
	case WARNINGS_IN_TEXT:
ali@17
   178
	    g_set_error(error,G_MARKUP_ERROR,G_MARKUP_ERROR_UNKNOWN_ELEMENT,
ali@17
   179
	      "Unknown element in 'text': '%s'",element_name);
ali@17
   180
	    return;
ali@17
   181
	default:
ali@17
   182
	    g_set_error(error,G_MARKUP_ERROR,G_MARKUP_ERROR_UNKNOWN_ELEMENT,
ali@17
   183
	      "Unexpected element: '%s'",element_name);
ali@17
   184
	    return;
ali@17
   185
    }
ali@17
   186
}
ali@17
   187
ali@17
   188
static void warnings_parser_end_element(GMarkupParseContext *context,
ali@17
   189
  const char *element_name,void *user_data,GError **error)
ali@17
   190
{
ali@17
   191
    WarningsBaton *baton=user_data;
ali@17
   192
    switch(baton->state)
ali@17
   193
    {
ali@17
   194
	case WARNINGS_IN_EXPECTED:
ali@17
   195
	    baton->testcase->warnings=
ali@17
   196
	      g_slist_reverse(baton->testcase->warnings);
ali@17
   197
	    baton->state=WARNINGS_DONE;
ali@17
   198
	    break;
ali@101
   199
	case WARNINGS_IN_SUMMARY:
ali@101
   200
	    if (!baton->testcase->summary.texts)
ali@101
   201
		g_set_error(error,G_MARKUP_ERROR,G_MARKUP_ERROR_INVALID_CONTENT,
ali@101
   202
		  "Summary element must contain at least one text element");
ali@101
   203
	    else
ali@101
   204
		baton->testcase->summary.texts=
ali@101
   205
		  g_slist_reverse(baton->testcase->summary.texts);
ali@101
   206
	    baton->state=WARNINGS_IN_EXPECTED;
ali@101
   207
	    break;
ali@17
   208
	case WARNINGS_IN_WARNING:
ali@17
   209
	    baton->warning->locations=
ali@17
   210
	      g_slist_reverse(baton->warning->locations);
ali@17
   211
	    baton->testcase->warnings=g_slist_prepend(baton->testcase->warnings,
ali@17
   212
	      baton->warning);
ali@17
   213
	    baton->warning=NULL;
ali@17
   214
	    baton->state=WARNINGS_IN_EXPECTED;
ali@17
   215
	    break;
ali@17
   216
	case WARNINGS_IN_AT:
ali@17
   217
	    baton->warning->locations=g_slist_prepend(baton->warning->locations,
ali@17
   218
	      baton->location);
ali@17
   219
	    baton->location=NULL;
ali@17
   220
	    baton->state=WARNINGS_IN_WARNING;
ali@17
   221
	    break;
ali@17
   222
	case WARNINGS_IN_TEXT:
ali@101
   223
	    baton->state=baton->parent_state;
ali@17
   224
	    break;
ali@17
   225
	default:
ali@17
   226
	    g_set_error(error,G_MARKUP_ERROR,G_MARKUP_ERROR_UNKNOWN_ELEMENT,
ali@17
   227
	      "Unexpected element ending: '%s'",element_name);
ali@17
   228
	    return;
ali@17
   229
    }
ali@17
   230
}
ali@17
   231
ali@17
   232
static void warnings_parser_text(GMarkupParseContext *context,
ali@17
   233
  const char *text,gsize text_len,void *user_data,GError **error)
ali@17
   234
{
ali@17
   235
    char *s,*t;
ali@17
   236
    WarningsBaton *baton=user_data;
ali@17
   237
    switch(baton->state)
ali@17
   238
    {
ali@17
   239
	case WARNINGS_IN_EXPECTED:
ali@17
   240
	    if (strspn(text," \t\n")!=text_len)
ali@17
   241
		g_set_error(error,G_MARKUP_ERROR,G_MARKUP_ERROR_INVALID_CONTENT,
ali@17
   242
		  "The 'expected' tag does not take any content");
ali@17
   243
	    break;
ali@101
   244
	case WARNINGS_IN_SUMMARY:
ali@101
   245
	    if (strspn(text," \t\n")!=text_len)
ali@101
   246
		g_set_error(error,G_MARKUP_ERROR,G_MARKUP_ERROR_INVALID_CONTENT,
ali@101
   247
		  "The summary tags do not take any content");
ali@101
   248
	    break;
ali@17
   249
	case WARNINGS_IN_WARNING:
ali@17
   250
	    if (strspn(text," \t\n")!=text_len)
ali@17
   251
		g_set_error(error,G_MARKUP_ERROR,G_MARKUP_ERROR_INVALID_CONTENT,
ali@17
   252
		  "The warning tags do not take any content");
ali@17
   253
	    break;
ali@17
   254
	case WARNINGS_IN_AT:
ali@17
   255
	    if (strspn(text," \t\n")!=text_len)
ali@17
   256
		g_set_error(error,G_MARKUP_ERROR,G_MARKUP_ERROR_INVALID_CONTENT,
ali@17
   257
		  "The 'at' tag does not take any content");
ali@17
   258
	    break;
ali@17
   259
	case WARNINGS_IN_TEXT:
ali@17
   260
	    s=g_strdup(text+strspn(text," \t\n"));
ali@17
   261
	    g_strchomp(s);
ali@101
   262
	    if (baton->parent_state==WARNINGS_IN_SUMMARY)
ali@101
   263
		baton->testcase->summary.texts=
ali@101
   264
		  g_slist_prepend(baton->testcase->summary.texts,s);
ali@101
   265
	    else if (baton->warning->text)
ali@17
   266
	    {
ali@17
   267
		t=g_strconcat(baton->warning->text,s,NULL);
ali@17
   268
		g_free(baton->warning->text);
ali@17
   269
		g_free(s);
ali@17
   270
		baton->warning->text=t;
ali@17
   271
	    }
ali@17
   272
	    else
ali@17
   273
		baton->warning->text=s;
ali@17
   274
	    break;
ali@17
   275
	default:
ali@17
   276
	    g_set_error(error,G_MARKUP_ERROR,G_MARKUP_ERROR_INVALID_CONTENT,
ali@17
   277
	      "Unexpected content: '%s'",text);
ali@17
   278
	    return;
ali@17
   279
    }
ali@17
   280
}
ali@17
   281
ali@17
   282
GMarkupParseContext *warnings_parse_context_new(Testcase *testcase)
ali@17
   283
{
ali@17
   284
    static GMarkupParser parser={0};
ali@17
   285
    WarningsBaton *baton;
ali@17
   286
    parser.start_element=warnings_parser_start_element;
ali@17
   287
    parser.end_element=warnings_parser_end_element;
ali@17
   288
    parser.text=warnings_parser_text;
ali@17
   289
    baton=g_new0(WarningsBaton,1);
ali@17
   290
    baton->testcase=testcase;
ali@101
   291
    baton->parent_state=WARNINGS_INIT;
ali@17
   292
    baton->state=WARNINGS_INIT;
ali@17
   293
    return g_markup_parse_context_new(&parser,
ali@17
   294
      G_MARKUP_TREAT_CDATA_AS_TEXT|G_MARKUP_PREFIX_ERROR_POSITION,
ali@17
   295
      baton,g_free);
ali@17
   296
}