test-driver.c
author Dan Winship <danw@gnome.org>
Mon Feb 11 11:57:47 2008 -0500 (2008-02-11)
changeset 120 b937596c33d7
parent 94 0aa93cfbcb3f
child 125 e56c83bda295
permissions -rw-r--r--
Split razor_package and razor_entry names into name and flags
krh@80
     1
#include <stdio.h>
krh@80
     2
#include <string.h>
krh@80
     3
#include <stdarg.h>
krh@80
     4
#include <unistd.h>
krh@80
     5
#include <fcntl.h>
krh@80
     6
#include <errno.h>
krh@80
     7
#include <expat.h>
krh@80
     8
krh@80
     9
#include "razor.h"
krh@80
    10
krh@80
    11
#define XML_BUFFER_SIZE 4096
krh@80
    12
krh@80
    13
static void
krh@80
    14
parse_xml_file(const char *filename,
krh@80
    15
	       XML_StartElementHandler start,
krh@80
    16
	       XML_EndElementHandler end,
krh@80
    17
	       void *data)
krh@80
    18
{
krh@80
    19
	XML_Parser parser;
krh@80
    20
	char *buffer;
krh@80
    21
	int fd, len, err;
krh@80
    22
krh@80
    23
	parser = XML_ParserCreate(NULL);
krh@80
    24
	XML_SetElementHandler(parser, start, end);
krh@80
    25
	XML_SetUserData(parser, data);
krh@80
    26
krh@80
    27
	buffer = XML_GetBuffer(parser, XML_BUFFER_SIZE);
krh@80
    28
krh@80
    29
	fd = open(filename, O_RDONLY);
krh@80
    30
	if (fd < 0) {
krh@92
    31
		fprintf(stderr, "failed to open %s: %m\n", filename);
krh@80
    32
		exit(-1);
krh@80
    33
	}
krh@80
    34
krh@80
    35
	while (len = read(fd, buffer, XML_BUFFER_SIZE), len > 0) {
krh@80
    36
		err = XML_ParseBuffer(parser, len, len == 0);
krh@80
    37
		if (err == XML_STATUS_ERROR) {
krh@80
    38
			fprintf(stderr, "parse error at line %lu:\n%s\n",
krh@80
    39
				XML_GetCurrentLineNumber(parser),
krh@80
    40
				XML_ErrorString(XML_GetErrorCode(parser)));
krh@80
    41
			exit(-1);
krh@80
    42
		}
krh@80
    43
	}
krh@80
    44
krh@80
    45
	if (fd < 0) {
krh@80
    46
		fprintf(stderr, "read: %m\n");
krh@80
    47
		exit(-1);
krh@80
    48
	}
krh@80
    49
krh@80
    50
	close(fd);
krh@80
    51
}
krh@80
    52
krh@80
    53
struct test_set {
krh@80
    54
	char *name;
krh@80
    55
	struct razor_set *set;
krh@80
    56
	struct test_set *next;
krh@80
    57
};
krh@80
    58
krh@80
    59
struct test_context {
krh@80
    60
	struct razor_importer *importer;
krh@80
    61
	struct test_set *sets;
krh@92
    62
	struct razor_package_iterator *package_iterator;
krh@92
    63
	struct razor_property_iterator *property_iterator;
krh@80
    64
};
krh@80
    65
krh@80
    66
static void
krh@80
    67
get_atts(const char **atts, ...)
krh@80
    68
{
krh@80
    69
	va_list ap;
krh@80
    70
	const char *name, **ptr;
krh@80
    71
	int i;
krh@80
    72
krh@80
    73
	va_start(ap, atts);
krh@80
    74
	while (name = va_arg(ap, const char *), name != NULL) {
krh@80
    75
		ptr = va_arg(ap, const char **);
krh@92
    76
		*ptr = NULL;
krh@80
    77
		for (i = 0; atts[i]; i += 2) {
krh@80
    78
			if (strcmp(atts[i], name) == 0)
krh@80
    79
				*ptr = atts[i + 1];
krh@80
    80
		}
krh@80
    81
	}
krh@80
    82
	va_end(ap);
krh@80
    83
}
krh@80
    84
krh@80
    85
static void
krh@80
    86
parse_property(struct test_context *ctx, const char **atts,
krh@80
    87
	       enum razor_property_type type)
krh@80
    88
{
krh@80
    89
	const char *name = NULL, *version = NULL;
krh@80
    90
krh@92
    91
	get_atts(atts, "name", &name, "eq", &version, NULL);
krh@80
    92
krh@80
    93
	if (name == NULL) {
krh@80
    94
		fprintf(stderr, "no name specified for property\n");
krh@80
    95
		exit(-1);
krh@80
    96
	}
krh@80
    97
	
danw@109
    98
	razor_importer_add_property(ctx->importer, name,
danw@109
    99
				    RAZOR_VERSION_EQUAL, version, type);
krh@80
   100
}
krh@80
   101
krh@80
   102
static void
krh@92
   103
start_set_element(void *data, const char *element, const char **atts)
krh@80
   104
{
krh@80
   105
	struct test_context *ctx = data;
krh@80
   106
	struct test_set *set;
krh@80
   107
	const char *name, *version;
krh@80
   108
krh@80
   109
	if (strcmp(element, "set") == 0) {
krh@80
   110
		get_atts(atts, "name", &name, NULL);
krh@80
   111
		ctx->importer = razor_importer_new();	
krh@80
   112
		set = malloc(sizeof *set);
krh@80
   113
		set->name = strdup(name);
krh@80
   114
		set->next = ctx->sets;
krh@80
   115
		ctx->sets = set;
krh@80
   116
	} else if (strcmp(element, "package") == 0) {
krh@80
   117
		get_atts(atts, "name", &name, "version", &version, NULL);
krh@80
   118
		razor_importer_begin_package(ctx->importer, name, version);
krh@80
   119
	} else if (strcmp(element, "requires") == 0) {
krh@80
   120
		parse_property(ctx, atts, RAZOR_PROPERTY_REQUIRES);
krh@80
   121
	} else if (strcmp(element, "provides") == 0) {
krh@80
   122
		parse_property(ctx, atts, RAZOR_PROPERTY_PROVIDES);
krh@80
   123
	} else if (strcmp(element, "obsoletes") == 0) {
krh@80
   124
		parse_property(ctx, atts, RAZOR_PROPERTY_OBSOLETES);
krh@80
   125
	} else if (strcmp(element, "conflicts") == 0) {
krh@80
   126
		parse_property(ctx, atts, RAZOR_PROPERTY_CONFLICTS);
krh@80
   127
	} else if (strcmp(element, "file") == 0) {
krh@80
   128
		get_atts(atts, "name", &name, NULL);
krh@80
   129
		razor_importer_add_file(ctx->importer, name);		
krh@80
   130
	} else if (strcmp(element, "dir") == 0) {
krh@80
   131
		get_atts(atts, "name", &name, NULL);
krh@80
   132
		razor_importer_add_file(ctx->importer, name);		
krh@80
   133
	}
krh@80
   134
}
krh@80
   135
krh@80
   136
static void
krh@92
   137
end_set_element (void *data, const char *name)
krh@80
   138
{
krh@80
   139
	struct test_context *ctx = data;
krh@80
   140
krh@80
   141
	if (strcmp(name, "set") == 0) {
krh@80
   142
		ctx->sets->set = razor_importer_finish(ctx->importer);
krh@80
   143
	} else if (strcmp(name, "package") == 0) {
krh@80
   144
		razor_importer_finish_package(ctx->importer);
krh@80
   145
	}
krh@80
   146
}
krh@80
   147
krh@92
   148
static struct razor_set *
krh@92
   149
lookup_set(struct test_context *ctx, const char *name)
krh@92
   150
{
krh@92
   151
	struct test_set *set;
krh@92
   152
krh@92
   153
	for (set = ctx->sets; set != NULL; set = set->next) {
krh@92
   154
		if (strcmp(set->name, name) == 0)
krh@92
   155
			return set->set;
krh@92
   156
	}
krh@92
   157
krh@92
   158
	return NULL;
krh@92
   159
}
krh@92
   160
krh@92
   161
static void
krh@92
   162
verify_begin(struct test_context *ctx, const char **atts)
krh@92
   163
{
krh@92
   164
	struct razor_set *set;
krh@92
   165
	const char *type, *name;
krh@92
   166
krh@92
   167
	get_atts(atts, "type", &type, "set", &name, NULL);
krh@92
   168
	set = lookup_set(ctx, name);
krh@92
   169
	if (set == NULL) {
krh@92
   170
		fprintf(stderr, "set %s not found\n", name);
krh@92
   171
		exit(-1);
krh@92
   172
	}
krh@92
   173
krh@92
   174
	if (strcmp(type, "packages") == 0) {
krh@92
   175
		ctx->package_iterator =
krh@92
   176
			razor_package_iterator_create(set);
krh@92
   177
	} else if (strcmp(type, "properties") == 0) {
krh@92
   178
		ctx->property_iterator =
krh@92
   179
			razor_property_iterator_create(set, NULL);
krh@92
   180
	} else {
krh@92
   181
		fprintf(stderr,
krh@92
   182
			"unknown compare type \"%s\"\n", type);
krh@92
   183
		exit(-1);
krh@92
   184
	}
krh@92
   185
}
krh@92
   186
krh@92
   187
static void
krh@92
   188
verify_end(struct test_context *ctx)
krh@92
   189
{
krh@92
   190
	struct razor_package *package;
krh@92
   191
	struct razor_property *property;
krh@94
   192
	const char *name, *version;
krh@92
   193
	enum razor_property_type type;
danw@109
   194
	enum razor_version_relation relation;
krh@92
   195
krh@92
   196
	if (ctx->package_iterator != NULL) {
krh@92
   197
		if (razor_package_iterator_next(ctx->package_iterator,
krh@92
   198
						&package,
krh@92
   199
						&name, &version)) {
krh@92
   200
			fprintf(stderr, "too few packages in set\n");
krh@92
   201
			exit(-1);
krh@92
   202
		}
krh@92
   203
				
krh@92
   204
		razor_package_iterator_destroy(ctx->package_iterator);
krh@92
   205
		ctx->package_iterator = NULL;
krh@92
   206
	}
krh@92
   207
krh@92
   208
	if (ctx->property_iterator != NULL) {
krh@92
   209
		if (razor_property_iterator_next(ctx->property_iterator,
krh@92
   210
						 &property,
danw@109
   211
						 &name, &relation, &version,
danw@109
   212
						 &type)) {
krh@92
   213
			fprintf(stderr, "too few properties in set\n");
krh@92
   214
			exit(-1);
krh@92
   215
		}
krh@92
   216
krh@92
   217
		razor_property_iterator_destroy(ctx->property_iterator);
krh@92
   218
		ctx->property_iterator = NULL;
krh@92
   219
	}
krh@92
   220
}
krh@92
   221
krh@92
   222
static void
krh@92
   223
verify_package(struct test_context *ctx, const char **atts)
krh@92
   224
{
krh@92
   225
	struct razor_package *package;
krh@92
   226
	const char *name, *version, *ref_name, *ref_version;
krh@92
   227
krh@92
   228
	if (ctx->package_iterator == NULL) {
krh@92
   229
		fprintf(stderr,
krh@92
   230
			"\"package\" element seen, "
krh@92
   231
			"but not in package verify mode\n");
krh@92
   232
		exit(-1);
krh@92
   233
	}
krh@92
   234
krh@92
   235
	get_atts(atts, "name", &ref_name, "version", &ref_version, NULL);
krh@92
   236
	if (!razor_package_iterator_next(ctx->package_iterator,
krh@92
   237
					 &package, &name, &version)) {
krh@92
   238
		fprintf(stderr, "too many packages in set\n");
krh@92
   239
		exit(-1);
krh@92
   240
	}
krh@92
   241
			
krh@92
   242
	if (strcmp(name, ref_name) != 0 || strcmp(version, ref_version) != 0) {
krh@92
   243
		fprintf(stderr,
krh@92
   244
			"package mismatch; expected %s-%s, got %s-%s\n",
krh@92
   245
			ref_name, ref_version, name, version);
krh@92
   246
		exit(-1);
krh@92
   247
	}
krh@92
   248
}
krh@92
   249
krh@92
   250
static void
krh@92
   251
verify_property(struct test_context *ctx,
krh@92
   252
		enum razor_property_type ref_type, const char **atts)
krh@92
   253
{
krh@92
   254
	struct razor_property *property;
krh@92
   255
	const char *name, *version, *ref_name, *ref_version;
krh@92
   256
	enum razor_property_type type;
danw@109
   257
	enum razor_version_relation relation;
krh@92
   258
	int same_version;
krh@92
   259
krh@92
   260
	if (ctx->property_iterator == NULL) {
krh@92
   261
		fprintf(stderr,
krh@92
   262
			"\"requires/provides\" element seen, "
krh@92
   263
			"but not in property verify mode\n");
krh@92
   264
		exit(-1);
krh@92
   265
	}
krh@92
   266
krh@92
   267
	get_atts(atts, "name", &ref_name, "eq", &ref_version, NULL);
krh@92
   268
	if (!razor_property_iterator_next(ctx->property_iterator, &property,
danw@109
   269
					  &name, &relation, &version, &type)) {
krh@92
   270
		fprintf(stderr, "too many properties in set\n");
krh@92
   271
		exit(-1);
krh@92
   272
	}
krh@92
   273
			
krh@92
   274
	if (version != NULL && ref_version != NULL)
krh@92
   275
		same_version = strcmp(version, ref_version) == 0;
krh@92
   276
	else if (version == NULL && ref_version == NULL)
krh@92
   277
		same_version = 1;
krh@92
   278
	else
krh@92
   279
		same_version = 0;
krh@92
   280
krh@92
   281
	if (strcmp(name, ref_name) != 0 || !same_version || type != ref_type) {
krh@92
   282
		fprintf(stderr,
krh@92
   283
			"property mismatch; expected %s-%s/%d, got %s-%s/%d\n",
krh@92
   284
			ref_name, ref_version, ref_type,
krh@92
   285
			name, version, type);
krh@92
   286
		exit(-1);
krh@92
   287
	}
krh@92
   288
}
krh@92
   289
krh@92
   290
static void
krh@92
   291
start_test_element(void *data, const char *element, const char **atts)
krh@92
   292
{
krh@92
   293
	struct test_context *ctx = data;
krh@92
   294
	const char *name;
krh@92
   295
krh@92
   296
	if (strcmp(element, "import") == 0) {
krh@92
   297
		get_atts(atts, "file", &name, NULL);
krh@92
   298
		parse_xml_file(name, start_set_element, end_set_element, ctx);
krh@92
   299
	} else if (strcmp(element, "update") == 0) {
krh@92
   300
		/* run update to create new set */
krh@92
   301
	} else if (strcmp(element, "verify") == 0) {
krh@92
   302
		verify_begin(ctx, atts);
krh@92
   303
	} else if (strcmp(element, "package") == 0) {
krh@92
   304
		verify_package(ctx, atts);
krh@92
   305
	} else if (strcmp(element, "requires") == 0) {
krh@92
   306
		verify_property(ctx, RAZOR_PROPERTY_REQUIRES, atts);
krh@92
   307
	} else if (strcmp(element, "provides") == 0) {
krh@92
   308
		verify_property(ctx, RAZOR_PROPERTY_PROVIDES, atts);
krh@92
   309
	} else if (strcmp(element, "conflicts") == 0) {
krh@92
   310
		verify_property(ctx, RAZOR_PROPERTY_CONFLICTS, atts);
krh@92
   311
	} else if (strcmp(element, "obsoletes") == 0) {
krh@92
   312
		verify_property(ctx, RAZOR_PROPERTY_OBSOLETES, atts);
krh@92
   313
	}
krh@92
   314
}
krh@92
   315
krh@92
   316
static void
krh@92
   317
end_test_element (void *data, const char *element)
krh@92
   318
{
krh@92
   319
	struct test_context *ctx = data;
krh@92
   320
krh@92
   321
	if (strcmp(element, "verify") == 0)
krh@92
   322
		verify_end(ctx);
krh@92
   323
}
krh@92
   324
krh@80
   325
int main(int argc, char *argv[])
krh@80
   326
{
krh@80
   327
	struct test_context ctx;
krh@80
   328
krh@92
   329
	if (argc != 2) {
krh@92
   330
		fprintf(stderr, "usage: %s TESTS-FILE\n", argv[0]);
krh@80
   331
		exit(-1);			
krh@80
   332
	}
krh@80
   333
krh@80
   334
	memset(&ctx, 0, sizeof ctx);
krh@92
   335
	parse_xml_file(argv[1], start_test_element, end_test_element, &ctx);
krh@80
   336
krh@80
   337
	return 0;
krh@80
   338
}