X-Git-Url: http://git.ozlabs.org/?p=petitboot;a=blobdiff_plain;f=test%2Fparser%2Futils.c;h=394efb3b209b4f0dfa885cc1c7cfe3a09db56592;hp=083d916b082fd4cda6ba3af8a59b370ffa9d5b0c;hb=0e9f4d38b19c2d7557528ef5b11b93377525cd55;hpb=1b646fb733ef99b1dc1862276ae3595bdeaf355b diff --git a/test/parser/utils.c b/test/parser/utils.c index 083d916..394efb3 100644 --- a/test/parser/utils.c +++ b/test/parser/utils.c @@ -15,6 +15,10 @@ #include "device-handler.h" #include "parser.h" #include "resource.h" +#include "event.h" +#include "platform.h" +#include "paths.h" +#include "parser-conf.h" #include "parser-test.h" @@ -25,6 +29,10 @@ struct p_item { struct test_file { struct discover_device *dev; + enum { + TEST_FILE, + TEST_DIR, + } type; const char *name; void *data; int size; @@ -65,7 +73,7 @@ struct discover_device *test_create_device(struct parser_test *test, { struct discover_device *dev; - dev = discover_device_create(test->handler, name); + dev = discover_device_create(test->handler, NULL, name); dev->device->id = talloc_strdup(dev, name); dev->device_path = talloc_asprintf(dev, "/dev/%s", name); @@ -85,19 +93,32 @@ static struct discover_context *test_create_context(struct parser_test *test) list_init(&ctx->boot_options); ctx->device = test_create_device_simple(test); ctx->test_data = test; + ctx->handler = test->handler; device_handler_add_device(test->handler, ctx->device); return ctx; } -extern struct config *test_config_init(struct parser_test *test); +/* define our own test platform */ +static bool test_platform_probe(struct platform *p __attribute__((unused)), + void *ctx __attribute__((unused))) +{ + return true; +} + +struct platform test_platform = { + .name = "test", + .probe = test_platform_probe, +}; + +register_platform(test_platform); struct parser_test *test_init(void) { struct parser_test *test; test = talloc_zero(NULL, struct parser_test); - test->config = test_config_init(test); + platform_init(NULL); test->handler = device_handler_init(NULL, NULL, 0); test->ctx = test_create_context(test); list_init(&test->files); @@ -109,20 +130,24 @@ void test_fini(struct parser_test *test) { device_handler_destroy(test->handler); talloc_free(test); + platform_fini(); } void __test_read_conf_data(struct parser_test *test, + struct discover_device *dev, const char *conf_file, const char *buf, size_t len) { - test->conf.size = len; - test->conf.buf = talloc_memdup(test, buf, len); + test_add_file_data(test, dev, conf_file, buf, len); } -void test_read_conf_file(struct parser_test *test, const char *filename) +void test_read_conf_file(struct parser_test *test, const char *filename, + const char *conf_file) { struct stat stat; + size_t size; char *path; int fd, rc; + char *buf; path = talloc_asprintf(test, "%s/%s", TEST_CONF_BASE, filename); @@ -134,22 +159,18 @@ void test_read_conf_file(struct parser_test *test, const char *filename) assert(!rc); (void)rc; - test->conf.size = stat.st_size; - test->conf.buf = talloc_array(test, char, test->conf.size + 1); + size = stat.st_size; + buf = talloc_array(test, char, size + 1); - rc = read(fd, test->conf.buf, test->conf.size); - assert(rc == (ssize_t)test->conf.size); + rc = read(fd, buf, size); + assert(rc == (ssize_t)size); - *(char *)(test->conf.buf + test->conf.size) = '\0'; + *(buf + size) = '\0'; close(fd); talloc_free(path); -} -void test_set_conf_source(struct parser_test *test, const char *url) -{ - test->ctx->conf_url = pb_url_parse(test, url); - assert(test->ctx->conf_url); + test_add_file_data(test, test->ctx->device, conf_file, buf, size); } void test_add_file_data(struct parser_test *test, struct discover_device *dev, @@ -158,6 +179,7 @@ void test_add_file_data(struct parser_test *test, struct discover_device *dev, struct test_file *file; file = talloc_zero(test, struct test_file); + file->type = TEST_FILE; file->dev = dev; file->name = filename; file->data = talloc_memdup(test, data, size); @@ -165,6 +187,36 @@ void test_add_file_data(struct parser_test *test, struct discover_device *dev, list_add(&test->files, &file->list); } +void test_add_dir(struct parser_test *test, struct discover_device *dev, + const char *dirname) +{ + struct test_file *file; + + file = talloc_zero(test, struct test_file); + file->type = TEST_DIR; + file->dev = dev; + file->name = dirname; + /* Pick a non-zero size for directories so that "[ -s ]" sees that the file has non-zero size. */ + file->size = 1; + list_add(&test->files, &file->list); +} + +void test_set_event_source(struct parser_test *test) +{ + test->ctx->event = talloc_zero(test->ctx, struct event); +} + +void test_set_event_param(struct event *event, const char *name, + const char *value) +{ + event_set_param(event, name, value); +} + +void test_set_event_device(struct event *event, const char *dev) +{ + event->device = talloc_strdup(event, dev); +} int parser_request_file(struct discover_context *ctx, struct discover_device *dev, const char *filename, @@ -179,6 +231,8 @@ int parser_request_file(struct discover_context *ctx, continue; if (strcmp(file->name, filename)) continue; + if (file->type != TEST_FILE) + continue; /* the read_file() interface always adds a trailing null * for string-safety; do the same here */ @@ -193,12 +247,45 @@ int parser_request_file(struct discover_context *ctx, return -1; } +int parser_stat_path(struct discover_context *ctx, + struct discover_device *dev, const char *path, + struct stat *statbuf) +{ + struct parser_test *test = ctx->test_data; + struct test_file *file; + + list_for_each_entry(&test->files, file, list) { + if (file->dev != dev) + continue; + if (strcmp(file->name, path)) + continue; + + statbuf->st_size = (off_t)file->size; + switch (file->type) { + case TEST_FILE: + statbuf->st_mode = S_IFREG; + break; + case TEST_DIR: + statbuf->st_mode = S_IFDIR; + break; + default: + fprintf(stderr, "%s: bad test file mode %d!", __func__, + file->type); + exit(EXIT_FAILURE); + } + + return 0; + } + + return -1; +} + int parser_replace_file(struct discover_context *ctx, struct discover_device *dev, const char *filename, char *buf, int len) { struct parser_test *test = ctx->test_data; - struct test_file *f, *file; + struct test_file *f, *file = NULL; list_for_each_entry(&test->files, f, list) { if (f->dev != dev) @@ -221,6 +308,154 @@ int parser_replace_file(struct discover_context *ctx, file->size = len; return 0; } + +int parser_scandir(struct discover_context *ctx, const char *dirname, + struct dirent ***files, int (*filter)(const struct dirent *) + __attribute__((unused)), + int (*comp)(const struct dirent **, const struct dirent **) + __attribute__((unused))) +{ + struct parser_test *test = ctx->test_data; + struct test_file *f; + char *filename; + struct dirent **dirents = NULL, **new_dirents; + int n = 0, namelen; + + list_for_each_entry(&test->files, f, list) { + if (f->dev != ctx->device) + continue; + + filename = strrchr(f->name, '/'); + if (!filename) + continue; + + namelen = strlen(filename); + + if (strncmp(f->name, dirname, strlen(f->name) - namelen)) + continue; + + if (!dirents) { + dirents = malloc(sizeof(struct dirent *)); + } else { + new_dirents = realloc(dirents, sizeof(struct dirent *) + * (n + 1)); + if (!new_dirents) + goto err_cleanup; + + dirents = new_dirents; + } + + dirents[n] = malloc(sizeof(struct dirent) + namelen + 1); + + if (!dirents[n]) + goto err_cleanup; + + strcpy(dirents[n]->d_name, filename + 1); + n++; + } + + *files = dirents; + + return n; + +err_cleanup: + do { + free(dirents[n]); + } while (n-- > 0); + + free(dirents); + + return -1; +} + +struct load_url_result *load_url_async(void *ctx, struct pb_url *url, + load_url_complete async_cb, void *async_data, + waiter_cb stdout_cb, void *stdout_data) +{ + struct conf_context *conf = async_data; + struct parser_test *test = conf->dc->test_data; + struct load_url_result *result; + char tmp[] = "/tmp/pb-XXXXXX"; + ssize_t rc = -1, sz = 0; + struct test_file *file; + int fd; + + /* Ignore the stdout callback for tests */ + (void)stdout_cb; + (void)stdout_data; + + fd = mkstemp(tmp); + + if (fd < 0) + return NULL; + + /* Some parsers will expect to need to read a file, so write the + * specified file to a temporary file */ + list_for_each_entry(&test->files, file, list) { + if (file->dev) + continue; + + if (strcmp(file->name, url->full)) + continue; + + while (sz < file->size) { + rc = write(fd, file->data, file->size); + if (rc < 0) { + fprintf(stderr, + "Failed to write to tmpfile, %m\n"); + break; + } + sz += rc; + } + break; + } + + close(fd); + + result = talloc_zero(ctx, struct load_url_result); + if (!result) + return NULL; + + result->local = talloc_strdup(result, tmp); + result->url = url; + if (rc < 0) + result->status = LOAD_ERROR; + else + result->status = result->local ? LOAD_OK : LOAD_ERROR; + result->cleanup_local = true; + + async_cb(result, conf); + + return result; +} + +int parser_request_url(struct discover_context *ctx, struct pb_url *url, + char **buf, int *len) +{ + struct parser_test *test = ctx->test_data; + struct test_file *file; + char *tmp; + + list_for_each_entry(&test->files, file, list) { + if (file->dev) + continue; + + if (strcmp(file->name, url->full)) + continue; + + /* the read_file() interface always adds a trailing null + * for string-safety; do the same here */ + tmp = talloc_array(test, char, file->size + 1); + memcpy(tmp, file->data, file->size); + tmp[file->size] = '\0'; + *buf = tmp; + *len = file->size; + return 0; + } + + return -1; +} + int test_run_parser(struct parser_test *test, const char *parser_name) { struct p_item* i; @@ -229,7 +464,7 @@ int test_run_parser(struct parser_test *test, const char *parser_name) if (strcmp(i->parser->name, parser_name)) continue; test->ctx->parser = i->parser; - return i->parser->parse(test->ctx, test->conf.buf, test->conf.size); + return i->parser->parse(test->ctx); } errx(EXIT_FAILURE, "%s: parser '%s' not found", __func__, parser_name); @@ -267,6 +502,21 @@ void test_hotplug_device(struct parser_test *test, struct discover_device *dev) boot_option_resolve(test->handler, opt); } +void test_remove_device(struct parser_test *test, struct discover_device *dev) +{ + struct discover_boot_option *opt, *tmp; + + if (dev == test->ctx->device) { + list_for_each_entry_safe(&test->ctx->boot_options, + opt, tmp, list) { + list_remove(&opt->list); + talloc_free(opt); + } + } + + device_handler_remove(test->handler, dev); +} + struct discover_boot_option *get_boot_option(struct discover_context *ctx, int idx) {