test-driver.c
author Dan Winship <danw@gnome.org>
Mon Feb 04 10:46:29 2008 -0500 (2008-02-04)
changeset 108 340d92912f49
parent 92 74f19848a71b
child 109 313b0a615c14
permissions -rw-r--r--
Fix repo format on x86_64 by using uint32_t instead of unsigned long
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
	
krh@80
    98
	razor_importer_add_property(ctx->importer, name, version, type);
krh@80
    99
}
krh@80
   100
krh@80
   101
static void
krh@92
   102
start_set_element(void *data, const char *element, const char **atts)
krh@80
   103
{
krh@80
   104
	struct test_context *ctx = data;
krh@80
   105
	struct test_set *set;
krh@80
   106
	const char *name, *version;
krh@80
   107
krh@80
   108
	if (strcmp(element, "set") == 0) {
krh@80
   109
		get_atts(atts, "name", &name, NULL);
krh@80
   110
		ctx->importer = razor_importer_new();	
krh@80
   111
		set = malloc(sizeof *set);
krh@80
   112
		set->name = strdup(name);
krh@80
   113
		set->next = ctx->sets;
krh@80
   114
		ctx->sets = set;
krh@80
   115
	} else if (strcmp(element, "package") == 0) {
krh@80
   116
		get_atts(atts, "name", &name, "version", &version, NULL);
krh@80
   117
		razor_importer_begin_package(ctx->importer, name, version);
krh@80
   118
	} else if (strcmp(element, "requires") == 0) {
krh@80
   119
		parse_property(ctx, atts, RAZOR_PROPERTY_REQUIRES);
krh@80
   120
	} else if (strcmp(element, "provides") == 0) {
krh@80
   121
		parse_property(ctx, atts, RAZOR_PROPERTY_PROVIDES);
krh@80
   122
	} else if (strcmp(element, "obsoletes") == 0) {
krh@80
   123
		parse_property(ctx, atts, RAZOR_PROPERTY_OBSOLETES);
krh@80
   124
	} else if (strcmp(element, "conflicts") == 0) {
krh@80
   125
		parse_property(ctx, atts, RAZOR_PROPERTY_CONFLICTS);
krh@80
   126
	} else if (strcmp(element, "file") == 0) {
krh@80
   127
		get_atts(atts, "name", &name, NULL);
krh@80
   128
		razor_importer_add_file(ctx->importer, name);		
krh@80
   129
	} else if (strcmp(element, "dir") == 0) {
krh@80
   130
		get_atts(atts, "name", &name, NULL);
krh@80
   131
		razor_importer_add_file(ctx->importer, name);		
krh@80
   132
	}
krh@80
   133
}
krh@80
   134
krh@80
   135
static void
krh@92
   136
end_set_element (void *data, const char *name)
krh@80
   137
{
krh@80
   138
	struct test_context *ctx = data;
krh@80
   139
krh@80
   140
	if (strcmp(name, "set") == 0) {
krh@80
   141
		ctx->sets->set = razor_importer_finish(ctx->importer);
krh@80
   142
	} else if (strcmp(name, "package") == 0) {
krh@80
   143
		razor_importer_finish_package(ctx->importer);
krh@80
   144
	}
krh@80
   145
}
krh@80
   146
krh@92
   147
static struct razor_set *
krh@92
   148
lookup_set(struct test_context *ctx, const char *name)
krh@92
   149
{
krh@92
   150
	struct test_set *set;
krh@92
   151
krh@92
   152
	for (set = ctx->sets; set != NULL; set = set->next) {
krh@92
   153
		if (strcmp(set->name, name) == 0)
krh@92
   154
			return set->set;
krh@92
   155
	}
krh@92
   156
krh@92
   157
	return NULL;
krh@92
   158
}
krh@92
   159
krh@92
   160
static void
krh@92
   161
verify_begin(struct test_context *ctx, const char **atts)
krh@92
   162
{
krh@92
   163
	struct razor_set *set;
krh@92
   164
	const char *type, *name;
krh@92
   165
krh@92
   166
	get_atts(atts, "type", &type, "set", &name, NULL);
krh@92
   167
	set = lookup_set(ctx, name);
krh@92
   168
	if (set == NULL) {
krh@92
   169
		fprintf(stderr, "set %s not found\n", name);
krh@92
   170
		exit(-1);
krh@92
   171
	}
krh@92
   172
krh@92
   173
	if (strcmp(type, "packages") == 0) {
krh@92
   174
		ctx->package_iterator =
krh@92
   175
			razor_package_iterator_create(set);
krh@92
   176
	} else if (strcmp(type, "properties") == 0) {
krh@92
   177
		ctx->property_iterator =
krh@92
   178
			razor_property_iterator_create(set, NULL);
krh@92
   179
	} else {
krh@92
   180
		fprintf(stderr,
krh@92
   181
			"unknown compare type \"%s\"\n", type);
krh@92
   182
		exit(-1);
krh@92
   183
	}
krh@92
   184
}
krh@92
   185
krh@92
   186
static void
krh@92
   187
verify_end(struct test_context *ctx)
krh@92
   188
{
krh@92
   189
	struct razor_package *package;
krh@92
   190
	struct razor_property *property;
krh@94
   191
	const char *name, *version;
krh@92
   192
	enum razor_property_type type;
krh@92
   193
krh@92
   194
	if (ctx->package_iterator != NULL) {
krh@92
   195
		if (razor_package_iterator_next(ctx->package_iterator,
krh@92
   196
						&package,
krh@92
   197
						&name, &version)) {
krh@92
   198
			fprintf(stderr, "too few packages in set\n");
krh@92
   199
			exit(-1);
krh@92
   200
		}
krh@92
   201
				
krh@92
   202
		razor_package_iterator_destroy(ctx->package_iterator);
krh@92
   203
		ctx->package_iterator = NULL;
krh@92
   204
	}
krh@92
   205
krh@92
   206
	if (ctx->property_iterator != NULL) {
krh@92
   207
		if (razor_property_iterator_next(ctx->property_iterator,
krh@92
   208
						 &property,
krh@92
   209
						 &name, &version, &type)) {
krh@92
   210
			fprintf(stderr, "too few properties in set\n");
krh@92
   211
			exit(-1);
krh@92
   212
		}
krh@92
   213
krh@92
   214
		razor_property_iterator_destroy(ctx->property_iterator);
krh@92
   215
		ctx->property_iterator = NULL;
krh@92
   216
	}
krh@92
   217
}
krh@92
   218
krh@92
   219
static void
krh@92
   220
verify_package(struct test_context *ctx, const char **atts)
krh@92
   221
{
krh@92
   222
	struct razor_package *package;
krh@92
   223
	const char *name, *version, *ref_name, *ref_version;
krh@92
   224
krh@92
   225
	if (ctx->package_iterator == NULL) {
krh@92
   226
		fprintf(stderr,
krh@92
   227
			"\"package\" element seen, "
krh@92
   228
			"but not in package verify mode\n");
krh@92
   229
		exit(-1);
krh@92
   230
	}
krh@92
   231
krh@92
   232
	get_atts(atts, "name", &ref_name, "version", &ref_version, NULL);
krh@92
   233
	if (!razor_package_iterator_next(ctx->package_iterator,
krh@92
   234
					 &package, &name, &version)) {
krh@92
   235
		fprintf(stderr, "too many packages in set\n");
krh@92
   236
		exit(-1);
krh@92
   237
	}
krh@92
   238
			
krh@92
   239
	if (strcmp(name, ref_name) != 0 || strcmp(version, ref_version) != 0) {
krh@92
   240
		fprintf(stderr,
krh@92
   241
			"package mismatch; expected %s-%s, got %s-%s\n",
krh@92
   242
			ref_name, ref_version, name, version);
krh@92
   243
		exit(-1);
krh@92
   244
	}
krh@92
   245
}
krh@92
   246
krh@92
   247
static void
krh@92
   248
verify_property(struct test_context *ctx,
krh@92
   249
		enum razor_property_type ref_type, const char **atts)
krh@92
   250
{
krh@92
   251
	struct razor_property *property;
krh@92
   252
	const char *name, *version, *ref_name, *ref_version;
krh@92
   253
	enum razor_property_type type;
krh@92
   254
	int same_version;
krh@92
   255
krh@92
   256
	if (ctx->property_iterator == NULL) {
krh@92
   257
		fprintf(stderr,
krh@92
   258
			"\"requires/provides\" element seen, "
krh@92
   259
			"but not in property verify mode\n");
krh@92
   260
		exit(-1);
krh@92
   261
	}
krh@92
   262
krh@92
   263
	get_atts(atts, "name", &ref_name, "eq", &ref_version, NULL);
krh@92
   264
	if (!razor_property_iterator_next(ctx->property_iterator, &property,
krh@92
   265
					  &name, &version, &type)) {
krh@92
   266
		fprintf(stderr, "too many properties in set\n");
krh@92
   267
		exit(-1);
krh@92
   268
	}
krh@92
   269
			
krh@92
   270
	if (version != NULL && ref_version != NULL)
krh@92
   271
		same_version = strcmp(version, ref_version) == 0;
krh@92
   272
	else if (version == NULL && ref_version == NULL)
krh@92
   273
		same_version = 1;
krh@92
   274
	else
krh@92
   275
		same_version = 0;
krh@92
   276
krh@92
   277
	if (strcmp(name, ref_name) != 0 || !same_version || type != ref_type) {
krh@92
   278
		fprintf(stderr,
krh@92
   279
			"property mismatch; expected %s-%s/%d, got %s-%s/%d\n",
krh@92
   280
			ref_name, ref_version, ref_type,
krh@92
   281
			name, version, type);
krh@92
   282
		exit(-1);
krh@92
   283
	}
krh@92
   284
}
krh@92
   285
krh@92
   286
static void
krh@92
   287
start_test_element(void *data, const char *element, const char **atts)
krh@92
   288
{
krh@92
   289
	struct test_context *ctx = data;
krh@92
   290
	const char *name;
krh@92
   291
krh@92
   292
	if (strcmp(element, "import") == 0) {
krh@92
   293
		get_atts(atts, "file", &name, NULL);
krh@92
   294
		parse_xml_file(name, start_set_element, end_set_element, ctx);
krh@92
   295
	} else if (strcmp(element, "update") == 0) {
krh@92
   296
		/* run update to create new set */
krh@92
   297
	} else if (strcmp(element, "verify") == 0) {
krh@92
   298
		verify_begin(ctx, atts);
krh@92
   299
	} else if (strcmp(element, "package") == 0) {
krh@92
   300
		verify_package(ctx, atts);
krh@92
   301
	} else if (strcmp(element, "requires") == 0) {
krh@92
   302
		verify_property(ctx, RAZOR_PROPERTY_REQUIRES, atts);
krh@92
   303
	} else if (strcmp(element, "provides") == 0) {
krh@92
   304
		verify_property(ctx, RAZOR_PROPERTY_PROVIDES, atts);
krh@92
   305
	} else if (strcmp(element, "conflicts") == 0) {
krh@92
   306
		verify_property(ctx, RAZOR_PROPERTY_CONFLICTS, atts);
krh@92
   307
	} else if (strcmp(element, "obsoletes") == 0) {
krh@92
   308
		verify_property(ctx, RAZOR_PROPERTY_OBSOLETES, atts);
krh@92
   309
	}
krh@92
   310
}
krh@92
   311
krh@92
   312
static void
krh@92
   313
end_test_element (void *data, const char *element)
krh@92
   314
{
krh@92
   315
	struct test_context *ctx = data;
krh@92
   316
krh@92
   317
	if (strcmp(element, "verify") == 0)
krh@92
   318
		verify_end(ctx);
krh@92
   319
}
krh@92
   320
krh@80
   321
int main(int argc, char *argv[])
krh@80
   322
{
krh@80
   323
	struct test_context ctx;
krh@80
   324
krh@92
   325
	if (argc != 2) {
krh@92
   326
		fprintf(stderr, "usage: %s TESTS-FILE\n", argv[0]);
krh@80
   327
		exit(-1);			
krh@80
   328
	}
krh@80
   329
krh@80
   330
	memset(&ctx, 0, sizeof ctx);
krh@92
   331
	parse_xml_file(argv[1], start_test_element, end_test_element, &ctx);
krh@80
   332
krh@80
   333
	return 0;
krh@80
   334
}