From 9041a68272ff0dcac56aad8e44df8e6d1362da15 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Kristian=20H=C3=B8gsberg?= Date: Thu, 3 Jan 2008 19:50:20 -0500 Subject: [PATCH] Add iterator API, boot-strap test suite. --- Makefile | 2 +- main.c | 68 ++++++++++++------- razor.c | 171 ++++++++++++++++++++++++++++++------------------ razor.h | 30 ++++++++- sets.xml | 13 ++++ test-driver.c | 204 +++++++++++++++++++++++++++++++++++++++++++++++++++----- 6 files changed, 379 insertions(+), 109 deletions(-) diff --git a/Makefile b/Makefile index ae7cb78..1d2db52 100644 --- a/Makefile +++ b/Makefile @@ -8,7 +8,7 @@ razor : razor.o import.o main.o rpm.o util.o test-driver : razor.o util.o test-driver.o test : test-driver - ./test-driver sets.xml test.xml + ./test-driver test.xml clean : rm -f *.o razor diff --git a/main.c b/main.c index 5835332..f43784c 100644 --- a/main.c +++ b/main.c @@ -17,60 +17,80 @@ static int command_list(int argc, const char *argv[]) { struct razor_set *set; + struct razor_package_iterator *pi; + struct razor_package *package; + const char *pattern = argv[0], *name, *version; set = razor_set_open(repo_filename); - razor_set_list(set, argv[0]); + pi = razor_package_iterator_create(set); + while (razor_package_iterator_next(pi, &package, &name, &version)) { + if (pattern && fnmatch(pattern, name, 0) != 0) + continue; + + printf("%s-%s\n", name, version); + } + razor_package_iterator_destroy(pi); razor_set_destroy(set); return 0; } static int -command_list_requires(int argc, const char *argv[]) +list_properties(const char *package_name, + enum razor_property_type required_type) { struct razor_set *set; + struct razor_property *property; + struct razor_package *package; + struct razor_property_iterator *pi; + const char *name, *version; + enum razor_property_type type; set = razor_set_open(repo_filename); - razor_set_list_properties(set, argv[0], RAZOR_PROPERTY_REQUIRES); + if (package_name) + package = razor_set_get_package(set, package_name); + else + package = NULL; + + pi = razor_property_iterator_create(set, package); + while (razor_property_iterator_next(pi, &property, + &name, &version, &type)) { + if (type != required_type) + continue; + if (version[0] == '\0') + printf("%s\n", name); + else + printf("%s-%s\n", name, version); + } + razor_property_iterator_destroy(pi); + razor_set_destroy(set); return 0; } static int -command_list_provides(int argc, const char *argv[]) +command_list_requires(int argc, const char *argv[]) { - struct razor_set *set; - - set = razor_set_open(repo_filename); - razor_set_list_properties(set, argv[0], RAZOR_PROPERTY_PROVIDES); - razor_set_destroy(set); + return list_properties(argv[0], RAZOR_PROPERTY_REQUIRES); +} - return 0; +static int +command_list_provides(int argc, const char *argv[]) +{ + return list_properties(argv[0], RAZOR_PROPERTY_PROVIDES); } static int command_list_obsoletes(int argc, const char *argv[]) { - struct razor_set *set; - - set = razor_set_open(repo_filename); - razor_set_list_properties(set, argv[0], RAZOR_PROPERTY_OBSOLETES); - razor_set_destroy(set); - - return 0; + return list_properties(argv[0], RAZOR_PROPERTY_OBSOLETES); } static int command_list_conflicts(int argc, const char *argv[]) { - struct razor_set *set; - - set = razor_set_open(repo_filename); - razor_set_list_properties(set, argv[0], RAZOR_PROPERTY_CONFLICTS); - razor_set_destroy(set); - - return 0; + return list_properties(argv[0], RAZOR_PROPERTY_CONFLICTS); } static int diff --git a/razor.c b/razor.c index cd531dd..e4841d2 100644 --- a/razor.c +++ b/razor.c @@ -323,7 +323,12 @@ add_to_string_pool(struct hashtable *table, const char *key) static unsigned long add_to_property_pool(struct array *pool, struct array *properties) { - unsigned long *p; + unsigned long *p; + + if (properties->size == 0) + return ~0; + else if (properties->size == sizeof *p) + return *(unsigned long *) properties->data | RAZOR_IMMEDIATE; p = array_add(pool, properties->size); memcpy(p, properties->data, properties->size); @@ -756,9 +761,7 @@ serialize_files(struct razor_set *set, s += p->count; if (p->packages.size == 0) { - /* FIXME: We need to make sure this is handled - * correctly as the empty list. */ - e->packages = 0 | RAZOR_IMMEDIATE; + e->packages = ~0; } else if (p->packages.size / sizeof *r == 1) { r = p->packages.data; e->packages = *r | RAZOR_IMMEDIATE; @@ -855,7 +858,7 @@ build_file_tree(struct razor_importer *importer) e = array_add(&importer->set->files, sizeof *e); e->name = root.name | RAZOR_ENTRY_LAST; e->start = 1; - e->packages = 0; + e->packages = ~0; serialize_files(importer->set, &root, &importer->set->files); @@ -874,10 +877,11 @@ build_package_file_lists(struct razor_set *set, unsigned long *rmap) count = set->packages.size / sizeof *p; pkgs = zalloc(count * sizeof *pkgs); - e = set->files.data; end = set->files.data + set->files.size; - while (e < end) { - if (e->packages & RAZOR_IMMEDIATE) { + for (e = set->files.data; e < end; e++) { + if (e->packages == ~0) { + continue; + } else if (e->packages & RAZOR_IMMEDIATE) { e->packages = rmap[e->packages & RAZOR_ENTRY_MASK] | RAZOR_IMMEDIATE; r = &e->packages; @@ -891,7 +895,6 @@ build_package_file_lists(struct razor_set *set, unsigned long *rmap) if (*r++ & RAZOR_IMMEDIATE) break; } - e++; } packages = set->packages.data; @@ -939,23 +942,43 @@ razor_importer_finish(struct razor_importer *importer) return set; } -void -razor_set_list(struct razor_set *set, const char *pattern) +struct razor_package_iterator { + struct razor_set *set; + struct razor_package *package, *end; +}; + +struct razor_package_iterator * +razor_package_iterator_create(struct razor_set *set) +{ + struct razor_package_iterator *pi; + + pi = zalloc(sizeof *pi); + pi->set = set; + pi->package = set->packages.data; + pi->end = set->packages.data + set->packages.size; + + return pi; +} + +int +razor_package_iterator_next(struct razor_package_iterator *pi, + struct razor_package **package, + const char **name, const char **version) { - struct razor_package *p, *end; - int with_version = 0; char *pool; - pool = set->string_pool.data; - end = set->packages.data + set->packages.size; - for (p = set->packages.data; p < end; p++) { - if (pattern && fnmatch(pattern, &pool[p->name], 0) != 0) - continue; - if (with_version) - printf("%s-%s\n", &pool[p->name], &pool[p->version]); - else - printf("%s\n", &pool[p->name]); - } + pool = pi->set->string_pool.data; + *package = pi->package; + *name = &pool[pi->package->name]; + *version = &pool[pi->package->version]; + + return pi->package++ < pi->end; +} + +void +razor_package_iterator_destroy(struct razor_package_iterator *pi) +{ + free(pi); } struct razor_set *bsearch_set; @@ -1010,51 +1033,71 @@ razor_set_get_property(struct razor_set *set, const char *property) return p; } -void -razor_set_list_properties(struct razor_set *set, const char *name, - enum razor_property_type type) -{ - struct razor_property *p, *properties, *end; - struct razor_package *package; - unsigned long *r; - char *pool; +struct razor_property_iterator { + struct razor_set *set; + struct razor_property *property, *end; + unsigned long *index; + int last; +}; - pool = set->string_pool.data; +struct razor_property_iterator * +razor_property_iterator_create(struct razor_set *set, + struct razor_package *package) +{ + struct razor_property_iterator *pi; - if (name) { - package = razor_set_get_package(set, name); - r = (unsigned long *) set->property_pool.data + - package->properties; - properties = set->properties.data; - while (1) { - p = &properties[*r & RAZOR_ENTRY_MASK]; - if ((p->name >> 30) != type) - goto next; - if (pool[p->version] == '\0') - printf("%s\n", - &pool[p->name & RAZOR_ENTRY_MASK]); - else - printf("%s-%s\n", - &pool[p->name & RAZOR_ENTRY_MASK], - &pool[p->version]); - next: - if (*r++ & RAZOR_IMMEDIATE) - break; - } + pi = zalloc(sizeof *pi); + pi->set = set; + pi->property = set->properties.data; + pi->end = set->properties.data + set->properties.size; + if (package) { + pi->index = (unsigned long *) + set->property_pool.data + package->properties; + pi->last = 0; } else { - end = set->properties.data + set->properties.size; - for (p = set->properties.data; p < end; p++) { - if ((p->name >> 30) != type) - continue; - if (pool[p->version] == '\0') - printf("%s\n", - &pool[p->name & RAZOR_ENTRY_MASK]); - else - printf("%s-%s\n", - &pool[p->name & RAZOR_ENTRY_MASK], - &pool[p->version]); - } + pi->index = NULL; + pi->last = 0; } + + return pi; +} + +int +razor_property_iterator_next(struct razor_property_iterator *pi, + struct razor_property **property, + const char **name, const char **version, + enum razor_property_type *type) +{ + char *pool; + unsigned long flags, index; + int valid; + struct razor_property *p, *properties; + + if (pi->index) { + properties = pi->set->properties.data; + p = &properties[*pi->index & RAZOR_ENTRY_MASK]; + valid = !pi->last; + pi->last = (*pi->index++ & RAZOR_IMMEDIATE) != 0; + if (!valid) + return valid; + } else { + p = pi->property++; + valid = p < pi->end; + } + + pool = pi->set->string_pool.data; + *property = p; + *name = &pool[p->name & RAZOR_ENTRY_MASK]; + *version = &pool[p->version]; + *type = p->name >> 30; + + return valid; +} + +void +razor_property_iterator_destroy(struct razor_property_iterator *pi) +{ + free(pi); } void diff --git a/razor.h b/razor.h index 0f7083d..b400711 100644 --- a/razor.h +++ b/razor.h @@ -4,6 +4,8 @@ #define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0])) struct razor_set; +struct razor_package; +struct razor_property; enum razor_property_type { RAZOR_PROPERTY_REQUIRES, @@ -17,7 +19,33 @@ struct razor_set *razor_set_open(const char *filename); void razor_set_destroy(struct razor_set *set); int razor_set_write(struct razor_set *set, const char *filename); -void razor_set_list(struct razor_set *set, const char *pattern); +struct razor_package * +razor_set_get_package(struct razor_set *set, const char *package); + +struct razor_property * +razor_set_get_property(struct razor_set *set, const char *property); + +struct razor_package_iterator; +struct razor_package_iterator * +razor_package_iterator_create(struct razor_set *set); + +int razor_package_iterator_next(struct razor_package_iterator *pi, + struct razor_package **package, + const char **name, const char **version); +void razor_package_iterator_destroy(struct razor_package_iterator *pi); + +struct razor_property_iterator; +struct razor_property_iterator * +razor_property_iterator_create(struct razor_set *set, + struct razor_package *package); +int razor_property_iterator_next(struct razor_property_iterator *pi, + struct razor_property **property, + const char **name, const char **version, + enum razor_property_type *type); +void +razor_property_iterator_destroy(struct razor_property_iterator *pi); + + void razor_set_list_properties(struct razor_set *set, const char *name, enum razor_property_type type); void razor_set_list_property_packages(struct razor_set *set, diff --git a/sets.xml b/sets.xml index 8f8ae12..88bc376 100644 --- a/sets.xml +++ b/sets.xml @@ -1,4 +1,5 @@ + @@ -8,4 +9,16 @@ + + + + + + + + + + + + diff --git a/test-driver.c b/test-driver.c index b7e3b4f..fa548b3 100644 --- a/test-driver.c +++ b/test-driver.c @@ -28,7 +28,7 @@ parse_xml_file(const char *filename, fd = open(filename, O_RDONLY); if (fd < 0) { - fprintf(stderr, "open: %m\n"); + fprintf(stderr, "failed to open %s: %m\n", filename); exit(-1); } @@ -59,6 +59,8 @@ struct test_set { struct test_context { struct razor_importer *importer; struct test_set *sets; + struct razor_package_iterator *package_iterator; + struct razor_property_iterator *property_iterator; }; static void @@ -71,6 +73,7 @@ get_atts(const char **atts, ...) va_start(ap, atts); while (name = va_arg(ap, const char *), name != NULL) { ptr = va_arg(ap, const char **); + *ptr = NULL; for (i = 0; atts[i]; i += 2) { if (strcmp(atts[i], name) == 0) *ptr = atts[i + 1]; @@ -84,14 +87,8 @@ parse_property(struct test_context *ctx, const char **atts, enum razor_property_type type) { const char *name = NULL, *version = NULL; - int i; - for (i = 0; atts[i]; i += 2) { - if (strcmp(atts[i], "name") == 0) - name = atts[i + 1]; - else if (strcmp(atts[i], "eq") == 0) - version = atts[i + 1]; - } + get_atts(atts, "name", &name, "eq", &version, NULL); if (name == NULL) { fprintf(stderr, "no name specified for property\n"); @@ -102,7 +99,7 @@ parse_property(struct test_context *ctx, const char **atts, } static void -start_test_sets_element(void *data, const char *element, const char **atts) +start_set_element(void *data, const char *element, const char **atts) { struct test_context *ctx = data; struct test_set *set; @@ -136,7 +133,7 @@ start_test_sets_element(void *data, const char *element, const char **atts) } static void -end_test_sets_element (void *data, const char *name) +end_set_element (void *data, const char *name) { struct test_context *ctx = data; @@ -147,24 +144,193 @@ end_test_sets_element (void *data, const char *name) } } +static struct razor_set * +lookup_set(struct test_context *ctx, const char *name) +{ + struct test_set *set; + + for (set = ctx->sets; set != NULL; set = set->next) { + if (strcmp(set->name, name) == 0) + return set->set; + } + + return NULL; +} + +static void +verify_begin(struct test_context *ctx, const char **atts) +{ + struct razor_set *set; + const char *type, *name; + + get_atts(atts, "type", &type, "set", &name, NULL); + set = lookup_set(ctx, name); + if (set == NULL) { + fprintf(stderr, "set %s not found\n", name); + exit(-1); + } + + if (strcmp(type, "packages") == 0) { + ctx->package_iterator = + razor_package_iterator_create(set); + } else if (strcmp(type, "properties") == 0) { + ctx->property_iterator = + razor_property_iterator_create(set, NULL); + } else { + fprintf(stderr, + "unknown compare type \"%s\"\n", type); + exit(-1); + } +} + +static void +verify_end(struct test_context *ctx) +{ + struct razor_package *package; + struct razor_property *property; + const char *name, *version, *ref_name, *ref_version; + enum razor_property_type type; + + if (ctx->package_iterator != NULL) { + if (razor_package_iterator_next(ctx->package_iterator, + &package, + &name, &version)) { + fprintf(stderr, "too few packages in set\n"); + exit(-1); + } + + razor_package_iterator_destroy(ctx->package_iterator); + ctx->package_iterator = NULL; + } + + if (ctx->property_iterator != NULL) { + if (razor_property_iterator_next(ctx->property_iterator, + &property, + &name, &version, &type)) { + fprintf(stderr, "too few properties in set\n"); + exit(-1); + } + + razor_property_iterator_destroy(ctx->property_iterator); + ctx->property_iterator = NULL; + } +} + +static void +verify_package(struct test_context *ctx, const char **atts) +{ + struct razor_package *package; + const char *name, *version, *ref_name, *ref_version; + + if (ctx->package_iterator == NULL) { + fprintf(stderr, + "\"package\" element seen, " + "but not in package verify mode\n"); + exit(-1); + } + + get_atts(atts, "name", &ref_name, "version", &ref_version, NULL); + if (!razor_package_iterator_next(ctx->package_iterator, + &package, &name, &version)) { + fprintf(stderr, "too many packages in set\n"); + exit(-1); + } + + if (strcmp(name, ref_name) != 0 || strcmp(version, ref_version) != 0) { + fprintf(stderr, + "package mismatch; expected %s-%s, got %s-%s\n", + ref_name, ref_version, name, version); + exit(-1); + } +} + +static void +verify_property(struct test_context *ctx, + enum razor_property_type ref_type, const char **atts) +{ + struct razor_property *property; + const char *name, *version, *ref_name, *ref_version; + enum razor_property_type type; + int same_version; + + if (ctx->property_iterator == NULL) { + fprintf(stderr, + "\"requires/provides\" element seen, " + "but not in property verify mode\n"); + exit(-1); + } + + get_atts(atts, "name", &ref_name, "eq", &ref_version, NULL); + if (!razor_property_iterator_next(ctx->property_iterator, &property, + &name, &version, &type)) { + fprintf(stderr, "too many properties in set\n"); + exit(-1); + } + + if (version != NULL && ref_version != NULL) + same_version = strcmp(version, ref_version) == 0; + else if (version == NULL && ref_version == NULL) + same_version = 1; + else + same_version = 0; + + if (strcmp(name, ref_name) != 0 || !same_version || type != ref_type) { + fprintf(stderr, + "property mismatch; expected %s-%s/%d, got %s-%s/%d\n", + ref_name, ref_version, ref_type, + name, version, type); + exit(-1); + } +} + +static void +start_test_element(void *data, const char *element, const char **atts) +{ + struct test_context *ctx = data; + struct razor_set *set; + const char *name; + + if (strcmp(element, "import") == 0) { + get_atts(atts, "file", &name, NULL); + parse_xml_file(name, start_set_element, end_set_element, ctx); + } else if (strcmp(element, "update") == 0) { + /* run update to create new set */ + } else if (strcmp(element, "verify") == 0) { + verify_begin(ctx, atts); + } else if (strcmp(element, "package") == 0) { + verify_package(ctx, atts); + } else if (strcmp(element, "requires") == 0) { + verify_property(ctx, RAZOR_PROPERTY_REQUIRES, atts); + } else if (strcmp(element, "provides") == 0) { + verify_property(ctx, RAZOR_PROPERTY_PROVIDES, atts); + } else if (strcmp(element, "conflicts") == 0) { + verify_property(ctx, RAZOR_PROPERTY_CONFLICTS, atts); + } else if (strcmp(element, "obsoletes") == 0) { + verify_property(ctx, RAZOR_PROPERTY_OBSOLETES, atts); + } +} + +static void +end_test_element (void *data, const char *element) +{ + struct test_context *ctx = data; + + if (strcmp(element, "verify") == 0) + verify_end(ctx); +} + int main(int argc, char *argv[]) { struct test_context ctx; struct test_set *set; - if (argc != 3) { - fprintf(stderr, "usage: %s SETS-FILE TESTS-FILE\n", argv[0]); + if (argc != 2) { + fprintf(stderr, "usage: %s TESTS-FILE\n", argv[0]); exit(-1); } memset(&ctx, 0, sizeof ctx); - parse_xml_file(argv[1], - start_test_sets_element, - end_test_sets_element, - &ctx); - - for (set = ctx.sets; set != NULL; set = set->next) - printf("set %s\n", set->name); + parse_xml_file(argv[1], start_test_element, end_test_element, &ctx); return 0; } -- 1.7.1