# HG changeset patch # User Kristian H?gsberg # Date 1199407820 18000 # Node ID 74f19848a71b517f80c7db667cd304449d74d3e9 # Parent 6884cefd1b8c8ff45aab561d8fe1d782b49ad654 Add iterator API, boot-strap test suite. diff -r 6884cefd1b8c -r 74f19848a71b Makefile --- a/Makefile Thu Jan 03 09:32:31 2008 -0500 +++ b/Makefile Thu Jan 03 19:50:20 2008 -0500 @@ -8,7 +8,7 @@ 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 -r 6884cefd1b8c -r 74f19848a71b main.c --- a/main.c Thu Jan 03 09:32:31 2008 -0500 +++ b/main.c Thu Jan 03 19:50:20 2008 -0500 @@ -17,9 +17,53 @@ 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 +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); + 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; @@ -28,49 +72,25 @@ static int 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_REQUIRES); - razor_set_destroy(set); - - return 0; + return list_properties(argv[0], RAZOR_PROPERTY_REQUIRES); } static int command_list_provides(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 0; + 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 -r 6884cefd1b8c -r 74f19848a71b razor.c --- a/razor.c Thu Jan 03 09:32:31 2008 -0500 +++ b/razor.c Thu Jan 03 19:50:20 2008 -0500 @@ -323,7 +323,12 @@ 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 @@ 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 @@ 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 @@ 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 @@ if (*r++ & RAZOR_IMMEDIATE) break; } - e++; } packages = set->packages.data; @@ -939,23 +942,43 @@ 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 *p, *end; - int with_version = 0; + 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) +{ 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 @@ return p; } +struct razor_property_iterator { + struct razor_set *set; + struct razor_property *property, *end; + unsigned long *index; + int last; +}; + +struct razor_property_iterator * +razor_property_iterator_create(struct razor_set *set, + struct razor_package *package) +{ + struct razor_property_iterator *pi; + + 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 { + 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_set_list_properties(struct razor_set *set, const char *name, - enum razor_property_type type) +razor_property_iterator_destroy(struct razor_property_iterator *pi) { - struct razor_property *p, *properties, *end; - struct razor_package *package; - unsigned long *r; - char *pool; - - pool = set->string_pool.data; - - 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; - } - } 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]); - } - } + free(pi); } void diff -r 6884cefd1b8c -r 74f19848a71b razor.h --- a/razor.h Thu Jan 03 09:32:31 2008 -0500 +++ b/razor.h Thu Jan 03 19:50:20 2008 -0500 @@ -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 @@ 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 -r 6884cefd1b8c -r 74f19848a71b sets.xml --- a/sets.xml Thu Jan 03 09:32:31 2008 -0500 +++ b/sets.xml Thu Jan 03 19:50:20 2008 -0500 @@ -1,4 +1,5 @@ + @@ -8,4 +9,16 @@ + + + + + + + + + + + + diff -r 6884cefd1b8c -r 74f19848a71b test-driver.c --- a/test-driver.c Thu Jan 03 09:32:31 2008 -0500 +++ b/test-driver.c Thu Jan 03 19:50:20 2008 -0500 @@ -28,7 +28,7 @@ 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_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 @@ 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 @@ 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 @@ } 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 @@ } 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 @@ } } +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; }