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