test/harness/warningsparser.c
author ali <ali@juiblex.co.uk>
Sat Oct 05 21:37:31 2013 +0100 (2013-10-05)
changeset 99 783eff3047bc
child 101 f44c530f80da
permissions -rw-r--r--
Fix bug #21: False positive: Opening slanted double-quote, followed by single slanted quote, should be accepted by BL
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@17
    18
	WARNINGS_IN_WARNING,
ali@17
    19
	WARNINGS_IN_AT,
ali@17
    20
	WARNINGS_IN_TEXT,
ali@17
    21
	WARNINGS_DONE,
ali@17
    22
    } state;
ali@17
    23
} WarningsBaton;
ali@17
    24
ali@17
    25
static void warnings_parser_start_element(GMarkupParseContext *context,
ali@17
    26
  const char *element_name,const char **attribute_names,
ali@17
    27
  const char **attribute_values,void *user_data,GError **error)
ali@17
    28
{
ali@17
    29
    int i;
ali@17
    30
    guint64 tmp;
ali@17
    31
    char *endp;
ali@17
    32
    WarningsBaton *baton=user_data;
ali@17
    33
    switch(baton->state)
ali@17
    34
    {
ali@17
    35
	case WARNINGS_INIT:
ali@17
    36
	    if (strcmp(element_name,"expected"))
ali@17
    37
		g_set_error(error,G_MARKUP_ERROR,G_MARKUP_ERROR_UNKNOWN_ELEMENT,
ali@17
    38
		  "Unknown root element: '%s'",element_name);
ali@17
    39
	    else if (attribute_names[0])
ali@17
    40
		g_set_error(error,G_MARKUP_ERROR,
ali@17
    41
		  G_MARKUP_ERROR_UNKNOWN_ATTRIBUTE,
ali@17
    42
		  "Unknown attribute on element 'expected': '%s'",
ali@17
    43
		  attribute_names[0]);
ali@17
    44
	    else
ali@17
    45
		baton->state=WARNINGS_IN_EXPECTED;
ali@17
    46
	    break;
ali@17
    47
	case WARNINGS_IN_EXPECTED:
ali@17
    48
	    baton->warning=g_new0(TestcaseWarning,1);
ali@17
    49
	    if (!strcmp(element_name,"error"))
ali@17
    50
		baton->warning->is_real=TRUE;
ali@17
    51
	    else if (!strcmp(element_name,"false-positive"))
ali@17
    52
		baton->warning->xfail=TRUE;
ali@17
    53
	    else if (!strcmp(element_name,"false-negative"))
ali@17
    54
		baton->warning->is_real=baton->warning->xfail=TRUE;
ali@17
    55
	    else
ali@17
    56
	    {
ali@17
    57
		g_set_error(error,G_MARKUP_ERROR,G_MARKUP_ERROR_UNKNOWN_ELEMENT,
ali@17
    58
		  "Unknown element in 'expected': '%s'",element_name);
ali@17
    59
		g_free(baton->warning);
ali@17
    60
		baton->warning=NULL;
ali@17
    61
		return;
ali@17
    62
	    }
ali@17
    63
	    if (attribute_names[0])
ali@17
    64
	    {
ali@17
    65
		g_set_error(error,G_MARKUP_ERROR,
ali@17
    66
		  G_MARKUP_ERROR_UNKNOWN_ATTRIBUTE,
ali@17
    67
		  "Unknown attribute on element '%s': '%s'",element_name,
ali@17
    68
		  attribute_names[0]);
ali@17
    69
		g_free(baton->warning);
ali@17
    70
		baton->warning=NULL;
ali@17
    71
		return;
ali@17
    72
	    }
ali@17
    73
	    else
ali@17
    74
		baton->state=WARNINGS_IN_WARNING;
ali@17
    75
	    break;
ali@17
    76
	case WARNINGS_IN_WARNING:
ali@17
    77
	    if (!strcmp(element_name,"at"))
ali@17
    78
	    {
ali@17
    79
		baton->location=g_new0(TestcaseLocation,1);
ali@17
    80
		for(i=0;attribute_names[i];i++)
ali@17
    81
		{
ali@17
    82
		    if (!strcmp(attribute_names[i],"line"))
ali@17
    83
		    {
ali@17
    84
			tmp=g_ascii_strtoull(attribute_values[i],&endp,0);
ali@17
    85
			if (tmp<1 || tmp>G_MAXUINT || tmp==G_MAXUINT64)
ali@17
    86
			{
ali@17
    87
			    g_set_error(error,G_MARKUP_ERROR,
ali@17
    88
			      G_MARKUP_ERROR_INVALID_CONTENT,"Invalid value "
ali@17
    89
			      "for attribute 'line' on element '%s': '%s'",
ali@17
    90
			      element_name,attribute_values[i]);
ali@17
    91
			    return;
ali@17
    92
			}
ali@17
    93
			baton->location->line=(guint)tmp;
ali@17
    94
		    }
ali@17
    95
		    else if (!strcmp(attribute_names[i],"column"))
ali@17
    96
		    {
ali@17
    97
			tmp=g_ascii_strtoull(attribute_values[i],&endp,0);
ali@17
    98
			if (tmp<1 || tmp>G_MAXUINT || tmp==G_MAXUINT64)
ali@17
    99
			{
ali@17
   100
			    g_set_error(error,G_MARKUP_ERROR,
ali@17
   101
			      G_MARKUP_ERROR_INVALID_CONTENT,"Invalid value "
ali@17
   102
			      "for attribute 'column' on element '%s': '%s'",
ali@17
   103
			      element_name,attribute_values[i]);
ali@17
   104
			    return;
ali@17
   105
			}
ali@17
   106
			baton->location->column=(guint)tmp;
ali@17
   107
		    }
ali@17
   108
		    else
ali@17
   109
		    {
ali@17
   110
			g_set_error(error,G_MARKUP_ERROR,
ali@17
   111
			  G_MARKUP_ERROR_UNKNOWN_ATTRIBUTE,
ali@17
   112
			  "Unknown attribute on element '%s': '%s'",
ali@17
   113
			  element_name,attribute_names[i]);
ali@17
   114
			return;
ali@17
   115
		    }
ali@17
   116
		}
ali@17
   117
		if (!baton->location->line)
ali@17
   118
		{
ali@17
   119
		    g_set_error(error,G_MARKUP_ERROR,
ali@17
   120
		      G_MARKUP_ERROR_MISSING_ATTRIBUTE,
ali@17
   121
		      "Missing attribute on element '%s': 'line'",element_name);
ali@17
   122
		    return;
ali@17
   123
		}
ali@17
   124
		baton->state=WARNINGS_IN_AT;
ali@17
   125
	    }
ali@17
   126
	    else if (!strcmp(element_name,"text"))
ali@17
   127
	    {
ali@17
   128
		if (attribute_names[0])
ali@17
   129
		{
ali@17
   130
		    g_set_error(error,G_MARKUP_ERROR,
ali@17
   131
		      G_MARKUP_ERROR_UNKNOWN_ATTRIBUTE,
ali@17
   132
		      "Unknown attribute on element 'text': '%s'",
ali@17
   133
		      attribute_names[0]);
ali@17
   134
		    return;
ali@17
   135
		}
ali@17
   136
		baton->state=WARNINGS_IN_TEXT;
ali@17
   137
	    }
ali@17
   138
	    break;
ali@17
   139
	case WARNINGS_IN_AT:
ali@17
   140
	    g_set_error(error,G_MARKUP_ERROR,G_MARKUP_ERROR_UNKNOWN_ELEMENT,
ali@17
   141
	      "Unknown element in 'at': '%s'",element_name);
ali@17
   142
	    return;
ali@17
   143
	case WARNINGS_IN_TEXT:
ali@17
   144
	    g_set_error(error,G_MARKUP_ERROR,G_MARKUP_ERROR_UNKNOWN_ELEMENT,
ali@17
   145
	      "Unknown element in 'text': '%s'",element_name);
ali@17
   146
	    return;
ali@17
   147
	default:
ali@17
   148
	    g_set_error(error,G_MARKUP_ERROR,G_MARKUP_ERROR_UNKNOWN_ELEMENT,
ali@17
   149
	      "Unexpected element: '%s'",element_name);
ali@17
   150
	    return;
ali@17
   151
    }
ali@17
   152
}
ali@17
   153
ali@17
   154
static void warnings_parser_end_element(GMarkupParseContext *context,
ali@17
   155
  const char *element_name,void *user_data,GError **error)
ali@17
   156
{
ali@17
   157
    WarningsBaton *baton=user_data;
ali@17
   158
    switch(baton->state)
ali@17
   159
    {
ali@17
   160
	case WARNINGS_IN_EXPECTED:
ali@17
   161
	    baton->testcase->warnings=
ali@17
   162
	      g_slist_reverse(baton->testcase->warnings);
ali@17
   163
	    baton->state=WARNINGS_DONE;
ali@17
   164
	    break;
ali@17
   165
	case WARNINGS_IN_WARNING:
ali@17
   166
	    baton->warning->locations=
ali@17
   167
	      g_slist_reverse(baton->warning->locations);
ali@17
   168
	    baton->testcase->warnings=g_slist_prepend(baton->testcase->warnings,
ali@17
   169
	      baton->warning);
ali@17
   170
	    baton->warning=NULL;
ali@17
   171
	    baton->state=WARNINGS_IN_EXPECTED;
ali@17
   172
	    break;
ali@17
   173
	case WARNINGS_IN_AT:
ali@17
   174
	    baton->warning->locations=g_slist_prepend(baton->warning->locations,
ali@17
   175
	      baton->location);
ali@17
   176
	    baton->location=NULL;
ali@17
   177
	    baton->state=WARNINGS_IN_WARNING;
ali@17
   178
	    break;
ali@17
   179
	case WARNINGS_IN_TEXT:
ali@17
   180
	    baton->state=WARNINGS_IN_WARNING;
ali@17
   181
	    break;
ali@17
   182
	default:
ali@17
   183
	    g_set_error(error,G_MARKUP_ERROR,G_MARKUP_ERROR_UNKNOWN_ELEMENT,
ali@17
   184
	      "Unexpected element ending: '%s'",element_name);
ali@17
   185
	    return;
ali@17
   186
    }
ali@17
   187
}
ali@17
   188
ali@17
   189
static void warnings_parser_text(GMarkupParseContext *context,
ali@17
   190
  const char *text,gsize text_len,void *user_data,GError **error)
ali@17
   191
{
ali@17
   192
    char *s,*t;
ali@17
   193
    WarningsBaton *baton=user_data;
ali@17
   194
    switch(baton->state)
ali@17
   195
    {
ali@17
   196
	case WARNINGS_IN_EXPECTED:
ali@17
   197
	    if (strspn(text," \t\n")!=text_len)
ali@17
   198
		g_set_error(error,G_MARKUP_ERROR,G_MARKUP_ERROR_INVALID_CONTENT,
ali@17
   199
		  "The 'expected' tag does not take any content");
ali@17
   200
	    break;
ali@17
   201
	case WARNINGS_IN_WARNING:
ali@17
   202
	    if (strspn(text," \t\n")!=text_len)
ali@17
   203
		g_set_error(error,G_MARKUP_ERROR,G_MARKUP_ERROR_INVALID_CONTENT,
ali@17
   204
		  "The warning tags do not take any content");
ali@17
   205
	    break;
ali@17
   206
	case WARNINGS_IN_AT:
ali@17
   207
	    if (strspn(text," \t\n")!=text_len)
ali@17
   208
		g_set_error(error,G_MARKUP_ERROR,G_MARKUP_ERROR_INVALID_CONTENT,
ali@17
   209
		  "The 'at' tag does not take any content");
ali@17
   210
	    break;
ali@17
   211
	case WARNINGS_IN_TEXT:
ali@17
   212
	    s=g_strdup(text+strspn(text," \t\n"));
ali@17
   213
	    g_strchomp(s);
ali@17
   214
	    if (baton->warning->text)
ali@17
   215
	    {
ali@17
   216
		t=g_strconcat(baton->warning->text,s,NULL);
ali@17
   217
		g_free(baton->warning->text);
ali@17
   218
		g_free(s);
ali@17
   219
		baton->warning->text=t;
ali@17
   220
	    }
ali@17
   221
	    else
ali@17
   222
		baton->warning->text=s;
ali@17
   223
	    break;
ali@17
   224
	default:
ali@17
   225
	    g_set_error(error,G_MARKUP_ERROR,G_MARKUP_ERROR_INVALID_CONTENT,
ali@17
   226
	      "Unexpected content: '%s'",text);
ali@17
   227
	    return;
ali@17
   228
    }
ali@17
   229
}
ali@17
   230
ali@17
   231
GMarkupParseContext *warnings_parse_context_new(Testcase *testcase)
ali@17
   232
{
ali@17
   233
    static GMarkupParser parser={0};
ali@17
   234
    WarningsBaton *baton;
ali@17
   235
    parser.start_element=warnings_parser_start_element;
ali@17
   236
    parser.end_element=warnings_parser_end_element;
ali@17
   237
    parser.text=warnings_parser_text;
ali@17
   238
    baton=g_new0(WarningsBaton,1);
ali@17
   239
    baton->testcase=testcase;
ali@17
   240
    baton->state=WARNINGS_INIT;
ali@17
   241
    return g_markup_parse_context_new(&parser,
ali@17
   242
      G_MARKUP_TREAT_CDATA_AS_TEXT|G_MARKUP_PREFIX_ERROR_POSITION,
ali@17
   243
      baton,g_free);
ali@17
   244
}