src/test-driver.c
author J. Ali Harlow <ali@juiblex.co.uk>
Thu Oct 09 17:27:41 2014 +0100 (2014-10-09)
changeset 455 df914f383f5c
parent 406 5ab137def3d1
permissions -rw-r--r--
Support downloading from local repository even without libcurl

Using the --url option of the razor executable, it is possible
to specify a yum repository on the local machine (eg., on installation
media) and import from there, eg.,:

C> razor --url file:///d:/ import-yum

This will be handled by libcurl if available but if not, an internal
copy routine will be used.

Note that if Microsoft's KTM implementation of atomic transactions is
used, then the current directory must support atomic transactions
(also improve error messages for this, and other, cases).
richard@300
     1
/*
richard@300
     2
 * Copyright (C) 2008  Kristian Høgsberg <krh@redhat.com>
richard@300
     3
 * Copyright (C) 2008  Red Hat, Inc
ali@369
     4
 * Copyright (C) 2009  J. Ali Harlow <ali@juiblex.co.uk>
richard@300
     5
 *
richard@300
     6
 * This program is free software; you can redistribute it and/or modify
richard@300
     7
 * it under the terms of the GNU General Public License as published by
richard@300
     8
 * the Free Software Foundation; either version 2 of the License, or
richard@300
     9
 * (at your option) any later version.
richard@300
    10
 *
richard@300
    11
 * This program is distributed in the hope that it will be useful,
richard@300
    12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
richard@300
    13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
richard@300
    14
 * GNU General Public License for more details.
richard@300
    15
 *
richard@300
    16
 * You should have received a copy of the GNU General Public License along
richard@300
    17
 * with this program; if not, write to the Free Software Foundation, Inc.,
richard@300
    18
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
richard@300
    19
 */
richard@300
    20
ali@444
    21
#include "config.h"
rhughes@241
    22
#include <stdio.h>
rhughes@241
    23
#include <string.h>
rhughes@241
    24
#include <stdarg.h>
rhughes@241
    25
#include <unistd.h>
rhughes@241
    26
#include <fcntl.h>
rhughes@241
    27
#include <errno.h>
rhughes@241
    28
#include <expat.h>
rhughes@241
    29
rhughes@241
    30
#include "razor.h"
rhughes@241
    31
rhughes@241
    32
#define XML_BUFFER_SIZE 4096
rhughes@241
    33
rhughes@241
    34
static void
rhughes@241
    35
parse_xml_file(const char *filename,
rhughes@241
    36
	       XML_StartElementHandler start,
rhughes@241
    37
	       XML_EndElementHandler end,
rhughes@241
    38
	       void *data)
rhughes@241
    39
{
rhughes@241
    40
	XML_Parser parser;
rhughes@241
    41
	char *buffer;
rhughes@241
    42
	int fd, len, err;
rhughes@241
    43
rhughes@241
    44
	parser = XML_ParserCreate(NULL);
rhughes@241
    45
	XML_SetElementHandler(parser, start, end);
rhughes@241
    46
	XML_SetUserData(parser, data);
rhughes@241
    47
rhughes@241
    48
	fd = open(filename, O_RDONLY);
rhughes@241
    49
	if (fd < 0) {
ali@339
    50
		fprintf(stderr, "failed to open %s: %s\n", filename,
ali@339
    51
			strerror(errno));
rhughes@241
    52
		exit(-1);
rhughes@241
    53
	}
rhughes@241
    54
rhughes@241
    55
	while (1) {
rhughes@241
    56
		buffer = XML_GetBuffer(parser, XML_BUFFER_SIZE);
rhughes@241
    57
		len = read(fd, buffer, XML_BUFFER_SIZE);
rhughes@241
    58
		if (len == 0)
rhughes@241
    59
			break;
rhughes@241
    60
		err = XML_ParseBuffer(parser, len, len == 0);
rhughes@241
    61
		if (err == XML_STATUS_ERROR) {
rhughes@241
    62
			fprintf(stderr, "parse error at line %lu:\n%s\n",
rhughes@241
    63
				XML_GetCurrentLineNumber(parser),
rhughes@241
    64
				XML_ErrorString(XML_GetErrorCode(parser)));
rhughes@241
    65
			exit(-1);
rhughes@241
    66
		}
rhughes@241
    67
	}
rhughes@241
    68
rhughes@241
    69
	if (fd < 0) {
ali@339
    70
		perror("read");
rhughes@241
    71
		exit(-1);
rhughes@241
    72
	}
rhughes@241
    73
rhughes@241
    74
	close(fd);
rhughes@241
    75
}
rhughes@241
    76
rhughes@241
    77
struct test_context {
rhughes@241
    78
	struct razor_set *system_set, *repo_set, *result_set;
rhughes@241
    79
rhughes@241
    80
	struct razor_importer *importer;
rhughes@241
    81
	struct razor_set **importer_set;
rhughes@241
    82
rhughes@241
    83
	struct razor_transaction *trans;
rhughes@241
    84
rhughes@241
    85
	char *install_pkgs[3], *remove_pkgs[3];
rhughes@241
    86
	int n_install_pkgs, n_remove_pkgs;
rhughes@241
    87
rhughes@241
    88
	int unsat;
rhughes@241
    89
	int in_result;
rhughes@241
    90
rhughes@241
    91
	int debug, errors;
rhughes@241
    92
};
rhughes@241
    93
rhughes@241
    94
static void
rhughes@241
    95
get_atts(const char **atts, ...)
rhughes@241
    96
{
rhughes@241
    97
	va_list ap;
rhughes@241
    98
	const char *name, **ptr;
rhughes@241
    99
	int i;
rhughes@241
   100
rhughes@241
   101
	va_start(ap, atts);
rhughes@241
   102
	while (name = va_arg(ap, const char *), name != NULL) {
rhughes@241
   103
		ptr = va_arg(ap, const char **);
rhughes@241
   104
		*ptr = NULL;
rhughes@241
   105
		for (i = 0; atts[i]; i += 2) {
rhughes@241
   106
			if (strcmp(atts[i], name) == 0)
rhughes@241
   107
				*ptr = atts[i + 1];
rhughes@241
   108
		}
rhughes@241
   109
	}
rhughes@241
   110
	va_end(ap);
rhughes@241
   111
}
rhughes@241
   112
jbowes@284
   113
static enum razor_property_flags
rhughes@241
   114
parse_relation (const char *rel_str)
rhughes@241
   115
{
rhughes@241
   116
	if (!rel_str)
rhughes@241
   117
		return -1;
rhughes@241
   118
	if (rel_str[0] == 'L')
jbowes@284
   119
		return rel_str[1] == 'E' ? RAZOR_PROPERTY_LESS | RAZOR_PROPERTY_EQUAL : RAZOR_PROPERTY_LESS;
rhughes@241
   120
	else if (rel_str[0] == 'G')
jbowes@284
   121
		return rel_str[1] == 'E' ? RAZOR_PROPERTY_GREATER | RAZOR_PROPERTY_EQUAL : RAZOR_PROPERTY_GREATER;
rhughes@241
   122
	else if (rel_str[0] == 'E' || rel_str[1] == 'Q')
jbowes@284
   123
		return RAZOR_PROPERTY_EQUAL;
rhughes@241
   124
	else
rhughes@241
   125
		return -1;
rhughes@241
   126
}
rhughes@241
   127
rhughes@241
   128
static void
rhughes@241
   129
start_test(struct test_context *ctx, const char **atts)
rhughes@241
   130
{
rhughes@241
   131
	const char *name = NULL;
rhughes@241
   132
rhughes@241
   133
	get_atts(atts, "name", &name, NULL);
rhughes@241
   134
	if (!name) {
rhughes@241
   135
		fprintf(stderr, "Test with no name\n");
rhughes@241
   136
		exit(1);
rhughes@241
   137
	}
rhughes@241
   138
	printf("%s\n", name);
rhughes@241
   139
}
rhughes@241
   140
rhughes@241
   141
static void
rhughes@241
   142
end_test(struct test_context *ctx)
rhughes@241
   143
{
rhughes@241
   144
	if (ctx->system_set) {
ali@406
   145
		razor_set_unref(ctx->system_set);
rhughes@241
   146
		ctx->system_set = NULL;
rhughes@241
   147
	}
rhughes@241
   148
	if (ctx->repo_set) {
ali@406
   149
		razor_set_unref(ctx->repo_set);
rhughes@241
   150
		ctx->repo_set = NULL;
rhughes@241
   151
	}
rhughes@241
   152
	if (ctx->result_set) {
ali@406
   153
		razor_set_unref(ctx->result_set);
rhughes@241
   154
		ctx->result_set = NULL;
rhughes@241
   155
	}
rhughes@241
   156
	if (ctx->trans) {
rhughes@241
   157
		razor_transaction_destroy(ctx->trans);
rhughes@241
   158
		ctx->trans = NULL;
rhughes@241
   159
	}
rhughes@241
   160
}
rhughes@241
   161
rhughes@241
   162
static void
rhughes@241
   163
start_set(struct test_context *ctx, const char **atts)
rhughes@241
   164
{
rhughes@241
   165
	const char *name = NULL;
rhughes@241
   166
jbowes@284
   167
	ctx->importer = razor_importer_create();
rhughes@241
   168
	get_atts(atts, "name", &name, NULL);
rhughes@241
   169
	if (!name)
rhughes@241
   170
		ctx->importer_set = &ctx->result_set;
rhughes@241
   171
	else if (!strcmp(name, "system"))
rhughes@241
   172
		ctx->importer_set = &ctx->system_set;
rhughes@241
   173
	else if (!strcmp(name, "repo"))
rhughes@241
   174
		ctx->importer_set = &ctx->repo_set;
rhughes@241
   175
	else {
rhughes@241
   176
		fprintf(stderr, "  bad set name '%s'\n", name);
rhughes@241
   177
		exit(1);
rhughes@241
   178
	}
rhughes@241
   179
}
rhughes@241
   180
rhughes@241
   181
static void
rhughes@241
   182
end_set(struct test_context *ctx)
rhughes@241
   183
{
rhughes@241
   184
	*ctx->importer_set = razor_importer_finish(ctx->importer);
rhughes@241
   185
	ctx->importer = NULL;
rhughes@241
   186
}
rhughes@241
   187
rhughes@241
   188
static void
rhughes@241
   189
start_package(struct test_context *ctx, const char **atts)
rhughes@241
   190
{
rhughes@241
   191
	const char *name = NULL, *version = NULL, *arch = NULL;
rhughes@241
   192
rhughes@241
   193
	get_atts(atts, "name", &name,
rhughes@241
   194
		 "version", &version,
rhughes@241
   195
		 "arch", &arch,
rhughes@241
   196
		 NULL);
rhughes@241
   197
rhughes@241
   198
	if (!name) {
rhughes@241
   199
		fprintf(stderr, "  package with no name\n");
rhughes@241
   200
		exit(1);
rhughes@241
   201
	}
rhughes@241
   202
rhughes@241
   203
	razor_importer_begin_package(ctx->importer, name, version, arch);
rhughes@241
   204
	razor_importer_add_property(ctx->importer, name,
jbowes@284
   205
				    RAZOR_PROPERTY_EQUAL | RAZOR_PROPERTY_PROVIDES,
jbowes@284
   206
				    version);
rhughes@241
   207
}
rhughes@241
   208
rhughes@241
   209
static void
rhughes@241
   210
end_package(struct test_context *ctx)
rhughes@241
   211
{
rhughes@241
   212
	razor_importer_finish_package(ctx->importer);
rhughes@241
   213
}
rhughes@241
   214
rhughes@241
   215
static void
jbowes@284
   216
add_property(struct test_context *ctx, enum razor_property_flags type, const char *name, enum razor_property_flags rel, const char *version)
rhughes@241
   217
{
rhughes@241
   218
	razor_importer_add_property(ctx->importer, name,
jbowes@284
   219
				    rel | type, version);
jbowes@284
   220
}
jbowes@284
   221
jbowes@284
   222
static const char*
jbowes@284
   223
razor_property_flags_relation_to_string(enum razor_property_flags rel)
jbowes@284
   224
{
jbowes@284
   225
	if (rel == RAZOR_PROPERTY_LESS)
jbowes@284
   226
		return "<";
jbowes@284
   227
	if (rel == (RAZOR_PROPERTY_EQUAL | RAZOR_PROPERTY_LESS))
jbowes@284
   228
		return "<=";
jbowes@284
   229
	if (rel == RAZOR_PROPERTY_EQUAL)
jbowes@284
   230
		return "=";
jbowes@284
   231
	if (rel == (RAZOR_PROPERTY_EQUAL | RAZOR_PROPERTY_GREATER))
jbowes@284
   232
		return ">=";
jbowes@284
   233
	if (rel == RAZOR_PROPERTY_GREATER)
jbowes@284
   234
		return ">";
jbowes@284
   235
jbowes@284
   236
	return "";
rhughes@241
   237
}
rhughes@241
   238
rhughes@241
   239
static void
rhughes@241
   240
check_unsatisfiable_property(struct test_context *ctx,
jbowes@284
   241
			     enum razor_property_flags type,
rhughes@241
   242
			     const char *name,
jbowes@284
   243
			     enum razor_property_flags rel,
rhughes@241
   244
			     const char *version)
rhughes@241
   245
{
rhughes@241
   246
	if (!version)
rhughes@241
   247
		version = "";
rhughes@241
   248
rhughes@241
   249
	if (razor_transaction_unsatisfied_property(ctx->trans,
jbowes@284
   250
						   name, rel | type, version))
rhughes@241
   251
		return;
rhughes@241
   252
rhughes@241
   253
	fprintf(stderr, "  didn't get unsatisfiable '%s %s %s'\n",
jbowes@284
   254
		name, razor_property_flags_relation_to_string(rel), version);
rhughes@241
   255
	ctx->errors++;
rhughes@241
   256
}
rhughes@241
   257
rhughes@241
   258
static void
jbowes@284
   259
start_property(struct test_context *ctx, enum razor_property_flags type, const char **atts)
rhughes@241
   260
{
rhughes@241
   261
	const char *name = NULL, *rel_str = NULL, *version = NULL;
jbowes@284
   262
	enum razor_property_flags rel;
rhughes@241
   263
rhughes@241
   264
	get_atts(atts, "name", &name, "relation", &rel_str, "version", &version, NULL);
rhughes@241
   265
	if (name == NULL) {
rhughes@241
   266
		fprintf(stderr, "  no name specified for property\n");
rhughes@241
   267
		exit(1);
rhughes@241
   268
	}
rhughes@241
   269
	if (version) {
rhughes@241
   270
		rel = parse_relation(rel_str);
rhughes@241
   271
		if (rel == -1) {
rhughes@241
   272
			fprintf(stderr, "  bad or missing version relation for property %s\n", name);
rhughes@241
   273
			exit(1);
rhughes@241
   274
		}
rhughes@241
   275
	} else
jbowes@284
   276
		rel = RAZOR_PROPERTY_EQUAL;
rhughes@241
   277
rhughes@241
   278
	if (ctx->unsat)
rhughes@241
   279
		check_unsatisfiable_property(ctx, type, name, rel, version);
rhughes@241
   280
	else
rhughes@241
   281
		add_property(ctx, type, name, rel, version);
rhughes@241
   282
}
rhughes@241
   283
rhughes@241
   284
static void
rhughes@241
   285
start_transaction(struct test_context *ctx, const char **atts)
rhughes@241
   286
{
rhughes@241
   287
	ctx->n_install_pkgs = 0;
rhughes@241
   288
	ctx->n_remove_pkgs = 0;
rhughes@241
   289
}
rhughes@241
   290
krh@306
   291
static struct razor_package *
krh@306
   292
get_package(struct razor_set *set, const char *package)
krh@306
   293
{
krh@306
   294
	struct razor_package_iterator *pi;
krh@306
   295
	struct razor_package *p;
krh@306
   296
	const char *name, *version, *arch;
krh@306
   297
krh@306
   298
	pi = razor_package_iterator_create(set);
richard@307
   299
	while (razor_package_iterator_next(pi, &p, RAZOR_DETAIL_NAME, &name,
richard@307
   300
					   RAZOR_DETAIL_VERSION, &version,
richard@307
   301
					   RAZOR_DETAIL_ARCH, &arch,
richard@307
   302
					   RAZOR_DETAIL_LAST)) {
krh@306
   303
		if (strcmp(package, name) == 0)
krh@306
   304
			break;
krh@306
   305
	}
krh@306
   306
	razor_package_iterator_destroy(pi);
krh@306
   307
krh@306
   308
	return p;
krh@306
   309
}
krh@306
   310
rhughes@241
   311
static void
rhughes@241
   312
end_transaction(struct test_context *ctx)
rhughes@241
   313
{
rhughes@241
   314
	struct razor_package *pkg;
rhughes@241
   315
	int errors, i;
rhughes@241
   316
rhughes@241
   317
	ctx->trans = razor_transaction_create(ctx->system_set, ctx->repo_set);
rhughes@241
   318
	for (i = 0; i < ctx->n_install_pkgs; i++) {
krh@306
   319
		pkg = get_package(ctx->repo_set, ctx->install_pkgs[i]);
rhughes@241
   320
		razor_transaction_install_package(ctx->trans, pkg);
rhughes@241
   321
	}
rhughes@241
   322
	for (i = 0; i < ctx->n_remove_pkgs; i++) {
krh@306
   323
		pkg = get_package(ctx->system_set, ctx->remove_pkgs[i]);
jbowes@258
   324
		if (!pkg)
krh@306
   325
			pkg = get_package(ctx->repo_set, ctx->remove_pkgs[i]);
jbowes@258
   326
rhughes@241
   327
		razor_transaction_remove_package(ctx->trans, pkg);
rhughes@241
   328
	}
rhughes@241
   329
jbowes@284
   330
	razor_transaction_resolve(ctx->trans);
jbowes@284
   331
	errors = razor_transaction_describe(ctx->trans);
rhughes@241
   332
	printf("\n");
rhughes@241
   333
rhughes@241
   334
	while (ctx->n_install_pkgs--)
rhughes@241
   335
		free(ctx->install_pkgs[ctx->n_install_pkgs]);
rhughes@241
   336
	while (ctx->n_remove_pkgs--)
rhughes@241
   337
		free(ctx->remove_pkgs[ctx->n_remove_pkgs]);
rhughes@241
   338
rhughes@241
   339
	if (!errors) {
rhughes@241
   340
		struct razor_set *new;
ali@369
   341
		new = razor_transaction_commit(ctx->trans);
ali@369
   342
		razor_transaction_destroy(ctx->trans);
jbowes@258
   343
		ctx->trans = NULL;
rhughes@241
   344
		ctx->system_set = new;
rhughes@241
   345
	}
rhughes@241
   346
}
rhughes@241
   347
rhughes@241
   348
static void
rhughes@241
   349
start_install_or_update(struct test_context *ctx, const char **atts)
rhughes@241
   350
{
rhughes@241
   351
	const char *name = NULL;
rhughes@241
   352
rhughes@241
   353
	get_atts(atts, "name", &name, NULL);
rhughes@241
   354
	if (!name) {
rhughes@241
   355
		fprintf(stderr, "  install/update with no name\n");
rhughes@241
   356
		exit(1);
rhughes@241
   357
	}
rhughes@241
   358
rhughes@241
   359
	ctx->install_pkgs[ctx->n_install_pkgs++] = strdup(name);
rhughes@241
   360
}
rhughes@241
   361
rhughes@241
   362
static void
rhughes@241
   363
start_remove(struct test_context *ctx, const char **atts)
rhughes@241
   364
{
rhughes@241
   365
	const char *name = NULL;
rhughes@241
   366
rhughes@241
   367
	get_atts(atts, "name", &name, NULL);
rhughes@241
   368
	if (!name) {
rhughes@241
   369
		fprintf(stderr, "  remove with no name\n");
rhughes@241
   370
		exit(1);
rhughes@241
   371
	}
rhughes@241
   372
rhughes@241
   373
	ctx->remove_pkgs[ctx->n_remove_pkgs++] = strdup(name);
rhughes@241
   374
}
rhughes@241
   375
rhughes@241
   376
static void
rhughes@241
   377
start_result(struct test_context *ctx, const char **atts)
rhughes@241
   378
{
rhughes@241
   379
	ctx->in_result = 1;
rhughes@241
   380
}
rhughes@241
   381
rhughes@241
   382
static void
jbowes@284
   383
diff_callback(enum razor_diff_action action,
jbowes@284
   384
	      struct razor_package *package,
jbowes@284
   385
	      const char *name,
jbowes@284
   386
	      const char *version,
rhughes@241
   387
	      const char *arch,
rhughes@241
   388
	      void *data)
rhughes@241
   389
{
rhughes@241
   390
	struct test_context *ctx = data;
rhughes@241
   391
rhughes@241
   392
	ctx->errors++;
jbowes@284
   393
	if (action == RAZOR_DIFF_ACTION_REMOVE) {
rhughes@241
   394
		fprintf(stderr, "  result set should not contain %s %s\n",
jbowes@284
   395
			name, version);
rhughes@241
   396
	} else {
rhughes@241
   397
		fprintf(stderr, "  result set should contain %s %s\n",
jbowes@284
   398
			name, version);
rhughes@241
   399
	}
rhughes@241
   400
}
rhughes@241
   401
rhughes@241
   402
static void
rhughes@241
   403
end_result(struct test_context *ctx)
rhughes@241
   404
{
rhughes@241
   405
	ctx->in_result = 0;
rhughes@241
   406
rhughes@241
   407
	if (ctx->result_set) {
rhughes@241
   408
		if (!ctx->system_set)
rhughes@241
   409
			ctx->system_set = razor_set_create();
rhughes@241
   410
		razor_set_diff(ctx->system_set, ctx->result_set,
rhughes@241
   411
			       diff_callback, ctx);
rhughes@241
   412
	}
rhughes@241
   413
}
rhughes@241
   414
rhughes@241
   415
static void
rhughes@241
   416
start_unsatisfiable(struct test_context *ctx, const char **atts)
rhughes@241
   417
{
rhughes@241
   418
	if (ctx->result_set) {
rhughes@241
   419
		fprintf(stderr, "Expected to fail, but didn't\n");
rhughes@241
   420
		exit(1);
rhughes@241
   421
	}
rhughes@241
   422
rhughes@241
   423
	ctx->unsat = 1;
rhughes@241
   424
}
rhughes@241
   425
rhughes@241
   426
static void
rhughes@241
   427
end_unsatisfiable(struct test_context *ctx)
rhughes@241
   428
{
rhughes@241
   429
	ctx->unsat = 0;
rhughes@241
   430
}
rhughes@241
   431
rhughes@241
   432
static void
rhughes@241
   433
start_test_element(void *data, const char *element, const char **atts)
rhughes@241
   434
{
rhughes@241
   435
	struct test_context *ctx = data;
rhughes@241
   436
rhughes@241
   437
	if (strcmp(element, "tests") == 0) {
rhughes@241
   438
		;
rhughes@241
   439
	} else if (strcmp(element, "test") == 0) {
rhughes@241
   440
		start_test(ctx, atts);
rhughes@241
   441
	} else if (strcmp(element, "set") == 0) {
rhughes@241
   442
		start_set(ctx, atts);
rhughes@241
   443
	} else if (strcmp(element, "transaction") == 0) {
rhughes@241
   444
		start_transaction(ctx, atts);
rhughes@241
   445
	} else if (strcmp(element, "install") == 0) {
rhughes@241
   446
		start_install_or_update(ctx, atts);
rhughes@241
   447
	} else if (strcmp(element, "install") == 0) {
rhughes@241
   448
		start_install_or_update(ctx, atts);
rhughes@241
   449
	} else if (strcmp(element, "remove") == 0) {
rhughes@241
   450
		start_remove(ctx, atts);
rhughes@241
   451
	} else if (strcmp(element, "result") == 0) {
rhughes@241
   452
		start_result(ctx, atts);
rhughes@241
   453
	} else if (strcmp(element, "unsatisfiable") == 0) {
rhughes@241
   454
		start_unsatisfiable(ctx, atts);
rhughes@241
   455
	} else if (strcmp(element, "package") == 0) {
rhughes@241
   456
		start_package(ctx, atts);
rhughes@241
   457
	} else if (strcmp(element, "requires") == 0) {
rhughes@241
   458
		start_property(ctx, RAZOR_PROPERTY_REQUIRES, atts);
rhughes@241
   459
	} else if (strcmp(element, "provides") == 0) {
rhughes@241
   460
		start_property(ctx, RAZOR_PROPERTY_PROVIDES, atts);
rhughes@241
   461
	} else if (strcmp(element, "conflicts") == 0) {
rhughes@241
   462
		start_property(ctx, RAZOR_PROPERTY_CONFLICTS, atts);
rhughes@241
   463
	} else if (strcmp(element, "obsoletes") == 0) {
rhughes@241
   464
		start_property(ctx, RAZOR_PROPERTY_OBSOLETES, atts);
rhughes@241
   465
	} else {
rhughes@241
   466
		fprintf(stderr, "Unrecognized element '%s'\n", element);
rhughes@241
   467
		exit(1);
rhughes@241
   468
	}
rhughes@241
   469
}
rhughes@241
   470
rhughes@241
   471
static void
rhughes@241
   472
end_test_element (void *data, const char *element)
rhughes@241
   473
{
rhughes@241
   474
	struct test_context *ctx = data;
rhughes@241
   475
rhughes@241
   476
	if (strcmp(element, "test") == 0) {
rhughes@241
   477
		end_test(ctx);
rhughes@241
   478
	} else if (strcmp(element, "set") == 0) {
rhughes@241
   479
		end_set(ctx);
rhughes@241
   480
	} else if (strcmp(element, "package") == 0) {
rhughes@241
   481
		end_package(ctx);
rhughes@241
   482
	} else if (strcmp(element, "transaction") == 0) {
rhughes@241
   483
		end_transaction(ctx);
rhughes@241
   484
	} else if (strcmp(element, "result") == 0) {
rhughes@241
   485
		end_result(ctx);
rhughes@241
   486
	} else if (strcmp(element, "unsatisfiable") == 0) {
rhughes@241
   487
		end_unsatisfiable(ctx);
rhughes@241
   488
	}
rhughes@241
   489
}
rhughes@241
   490
rhughes@241
   491
int main(int argc, char *argv[])
rhughes@241
   492
{
rhughes@241
   493
	struct test_context ctx;
rhughes@241
   494
	const char *test_file;
rhughes@241
   495
rhughes@241
   496
	memset(&ctx, 0, sizeof ctx);
rhughes@241
   497
rhughes@241
   498
	if (argc > 3) {
rhughes@241
   499
		fprintf(stderr, "usage: %s [-d] [TESTS-FILE]\n", argv[0]);
rhughes@241
   500
		exit(-1);
rhughes@241
   501
	}
rhughes@241
   502
rhughes@241
   503
	if (argc >= 2 && !strcmp (argv[1], "-d")) {
rhughes@241
   504
		ctx.debug = 1;
rhughes@241
   505
		argc--;
rhughes@241
   506
		argv++;
rhughes@241
   507
	}
rhughes@241
   508
	if (argc == 2)
rhughes@241
   509
		test_file = argv[1];
rhughes@241
   510
	else
rhughes@241
   511
		test_file = "test.xml";
rhughes@241
   512
rhughes@241
   513
	parse_xml_file(test_file, start_test_element, end_test_element, &ctx);
rhughes@241
   514
rhughes@241
   515
	if (ctx.errors) {
rhughes@241
   516
		fprintf(stderr, "\n%d errors\n", ctx.errors);
rhughes@241
   517
		return 1;
rhughes@241
   518
	} else
rhughes@241
   519
		return 0;
rhughes@241
   520
}