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