From 5faba45fe1adfaeb316e4616d4e3a4937e57e599 Mon Sep 17 00:00:00 2001 From: "Richard W.M. Jones" Date: Wed, 1 May 2013 09:44:47 +0100 Subject: [PATCH] tests/c-api: Various code refactorings. - Don't use fixed names for the disks. This will allow us to parallelize this test. - Add a new "GETKEY:" String parameter which can retrieve keys from the handle. The temporary disk names are stored as keys. - Don't test the close callback. However this uses the close callback mechanism to delete the temporary disks, and in any case close callbacks are well tested by the language binding tests. - The generated code now produces a static array of tests (instead of a 'perform_tests' function), making it possible to parallelize. --- generator/actions.ml | 18 ++-- generator/tests_c_api.ml | 33 ++----- tests/c-api/tests-main.c | 193 ++++++++++++++++++++------------------- tests/c-api/tests.h | 7 +- 4 files changed, 122 insertions(+), 129 deletions(-) diff --git a/generator/actions.ml b/generator/actions.ml index bc58a4834..0bb04bee2 100644 --- a/generator/actions.ml +++ b/generator/actions.ml @@ -2566,11 +2566,11 @@ data." }; style = RString "format", [String "filename"], []; tests = [ InitEmpty, Always, TestResultString ( - [["disk_format"; "test1.img"]], "raw"); + [["disk_format"; "GETKEY:test1"]], "raw"); InitEmpty, Always, TestResultString ( - [["disk_format"; "test2.img"]], "raw"); + [["disk_format"; "GETKEY:test2"]], "raw"); InitEmpty, Always, TestResultString ( - [["disk_format"; "test3.img"]], "raw"); + [["disk_format"; "GETKEY:test3"]], "raw"); ]; shortdesc = "detect the disk format of a disk image"; longdesc = "\ @@ -2588,11 +2588,11 @@ See also: L" }; style = RInt64 "size", [String "filename"], []; tests = [ InitEmpty, Always, TestResult ( - [["disk_virtual_size"; "test1.img"]], "ret == UINT64_C (524288000)"); + [["disk_virtual_size"; "GETKEY:test1"]], "ret == UINT64_C (524288000)"); InitEmpty, Always, TestResult ( - [["disk_virtual_size"; "test2.img"]], "ret == UINT64_C (52428800)"); + [["disk_virtual_size"; "GETKEY:test2"]], "ret == UINT64_C (52428800)"); InitEmpty, Always, TestResult ( - [["disk_virtual_size"; "test3.img"]], "ret == UINT64_C (10485760)"); + [["disk_virtual_size"; "GETKEY:test3"]], "ret == UINT64_C (10485760)"); ]; shortdesc = "return virtual size of a disk"; longdesc = "\ @@ -2607,11 +2607,11 @@ circumstances. See L." }; style = RBool "backingfile", [String "filename"], []; tests = [ InitEmpty, Always, TestResultFalse ( - [["disk_has_backing_file"; "test1.img"]]); + [["disk_has_backing_file"; "GETKEY:test1"]]); InitEmpty, Always, TestResultFalse ( - [["disk_has_backing_file"; "test2.img"]]); + [["disk_has_backing_file"; "GETKEY:test2"]]); InitEmpty, Always, TestResultFalse ( - [["disk_has_backing_file"; "test3.img"]]); + [["disk_has_backing_file"; "GETKEY:test3"]]); ]; shortdesc = "return whether disk has a backing file"; longdesc = "\ diff --git a/generator/tests_c_api.ml b/generator/tests_c_api.ml index 371ee70d7..3564be9f8 100644 --- a/generator/tests_c_api.ml +++ b/generator/tests_c_api.ml @@ -99,31 +99,12 @@ let rec generate_tests () = let nr_tests = List.length test_names in pr "size_t nr_tests = %d;\n" nr_tests; pr "\n"; - - pr "\ -size_t -perform_tests (guestfs_h *g) -{ - size_t test_num = 0; - size_t nr_failed = 0; - -"; - - iteri ( - fun i test_name -> - pr " test_num++;\n"; - pr " next_test (g, test_num, nr_tests, \"%s\");\n" test_name; - pr " if (%s (g) == -1) {\n" test_name; - pr " printf (\"FAIL: %%s\\n\", \"%s\");\n" test_name; - pr " nr_failed++;\n"; - pr " }\n"; + pr "struct test tests[%d] = {\n" nr_tests; + List.iter ( + fun name -> + pr " { .name = \"%s\", .test_fn = %s },\n" (c_quote name) name ) test_names; - - pr "\ - - return nr_failed; -} -" + pr "};\n" and generate_one_test name optional i (init, prereq, test) = let test_name = sprintf "test_%s_%d" name i in @@ -349,6 +330,10 @@ and generate_test_command_call ?(expect_error = false) ?test ?ret test_name cmd= List.iter ( function | OptString _, "NULL", _ -> () + | String _, arg, sym + when String.length arg >= 7 && String.sub arg 0 7 = "GETKEY:" -> + pr " const char *%s = guestfs_get_private (g, \"%s\");\n" + sym (c_quote (String.sub arg 7 (String.length arg - 7))) | Pathname _, arg, sym | Device _, arg, sym | Mountable _, arg, sym diff --git a/tests/c-api/tests-main.c b/tests/c-api/tests-main.c index 69d567e62..1e569da82 100644 --- a/tests/c-api/tests-main.c +++ b/tests/c-api/tests-main.c @@ -162,14 +162,6 @@ print_strings (char *const *argv) printf ("\t%s\n", argv[argc]); } -static void -incr (guestfs_h *g, void *iv, uint64_t event, int eh, int flags, - const char *buf, size_t buf_len, const uint64_t *array, size_t array_len) -{ - int *i = (int *) iv; - (*i)++; -} - static int compare_lists (char **, char **, int (*) (const char *, const char *)); /* Compare 'ret' to the string list that follows. */ @@ -393,9 +385,8 @@ substitute_srcdir (const char *path) return ret; } -void -next_test (guestfs_h *g, size_t test_num, size_t nr_tests, - const char *test_name) +static void +next_test (guestfs_h *g, size_t test_num, const char *test_name) { if (guestfs_get_verbose (g)) printf ("-------------------------------------------------------------------------------\n"); @@ -418,90 +409,82 @@ skipped (const char *test_name, const char *fs, ...) test_name, reason); } -int -main (int argc, char *argv[]) +static void +delete_file (guestfs_h *g, void *filenamev, + uint64_t event, int eh, int flags, + const char *buf, size_t buf_len, + const uint64_t *array, size_t array_len) { - const char *filename; + char *filename = filenamev; + + unlink (filename); + free (filename); +} + +static void +add_disk (guestfs_h *g, const char *key, off_t size) +{ + CLEANUP_FREE char *tmpdir = guestfs_get_tmpdir (g); + char *filename; int fd; - size_t nr_failed ; - int close_sentinel = 1; + + if (asprintf (&filename, "%s/diskXXXXXX", tmpdir) == -1) { + perror ("asprintf"); + exit (EXIT_FAILURE); + } + + fd = mkostemp (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_TRUNC|O_CLOEXEC); + if (fd == -1) { + perror ("mkstemp"); + exit (EXIT_FAILURE); + } + if (ftruncate (fd, size) == -1) { + perror ("ftruncate"); + close (fd); + unlink (filename); + exit (EXIT_FAILURE); + } + if (close (fd) == -1) { + perror (filename); + unlink (filename); + exit (EXIT_FAILURE); + } + + if (guestfs_add_drive (g, filename) == -1) { + printf ("FAIL: guestfs_add_drive %s\n", filename); + exit (EXIT_FAILURE); + } + + if (guestfs_set_event_callback (g, delete_file, + GUESTFS_EVENT_CLOSE, 0, filename) == -1) { + printf ("FAIL: guestfs_set_event_callback (GUESTFS_EVENT_CLOSE)\n"); + exit (EXIT_FAILURE); + } + + /* Record the real filename in the named private key. Tests can + * retrieve these names using the magic "GETKEY:" String + * parameter. + */ + guestfs_set_private (g, key, filename); +} + +/* Create the handle, with attached disks. */ +static guestfs_h * +create_handle (void) +{ guestfs_h *g; - setbuf (stdout, NULL); - - no_test_warnings (); - g = guestfs_create (); if (g == NULL) { printf ("FAIL: guestfs_create\n"); exit (EXIT_FAILURE); } - filename = "test1.img"; - fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_TRUNC|O_CLOEXEC, 0666); - if (fd == -1) { - perror (filename); - exit (EXIT_FAILURE); - } - if (ftruncate (fd, 524288000) == -1) { - perror ("ftruncate"); - close (fd); - unlink (filename); - exit (EXIT_FAILURE); - } - if (close (fd) == -1) { - perror (filename); - unlink (filename); - exit (EXIT_FAILURE); - } - if (guestfs_add_drive (g, filename) == -1) { - printf ("FAIL: guestfs_add_drive %s\n", filename); - exit (EXIT_FAILURE); - } + add_disk (g, "test1", 524288000); - filename = "test2.img"; - fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_TRUNC|O_CLOEXEC, 0666); - if (fd == -1) { - perror (filename); - exit (EXIT_FAILURE); - } - if (ftruncate (fd, 52428800) == -1) { - perror ("ftruncate"); - close (fd); - unlink (filename); - exit (EXIT_FAILURE); - } - if (close (fd) == -1) { - perror (filename); - unlink (filename); - exit (EXIT_FAILURE); - } - if (guestfs_add_drive (g, filename) == -1) { - printf ("FAIL: guestfs_add_drive %s\n", filename); - exit (EXIT_FAILURE); - } + add_disk (g, "test2", 52428800); - filename = "test3.img"; - fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_TRUNC|O_CLOEXEC, 0666); - if (fd == -1) { - perror (filename); - exit (EXIT_FAILURE); - } - if (ftruncate (fd, 10485760) == -1) { - perror ("ftruncate"); - close (fd); - unlink (filename); - exit (EXIT_FAILURE); - } - if (close (fd) == -1) { - perror (filename); - unlink (filename); - exit (EXIT_FAILURE); - } - if (guestfs_add_drive (g, filename) == -1) { - printf ("FAIL: guestfs_add_drive %s\n", filename); - exit (EXIT_FAILURE); - } + add_disk (g, "test3", 10485760); if (guestfs_add_drive_ro (g, "../data/test.iso") == -1) { printf ("FAIL: guestfs_add_drive_ro ../data/test.iso\n"); @@ -529,21 +512,43 @@ main (int argc, char *argv[]) exit (EXIT_FAILURE); } - nr_failed = perform_tests (g); + return g; +} - /* Check close callback is called. */ - guestfs_set_event_callback (g, incr, GUESTFS_EVENT_CLOSE, 0, &close_sentinel); +static size_t +perform_tests (guestfs_h *g) +{ + size_t test_num; + size_t nr_failed = 0; + struct test *t; - guestfs_close (g); - - if (close_sentinel != 2) { - fprintf (stderr, "FAIL: close callback was not called\n"); - exit (EXIT_FAILURE); + for (test_num = 0; test_num < nr_tests; ++test_num) { + t = &tests[test_num]; + next_test (g, test_num, t->name); + if (t->test_fn (g) == -1) { + printf ("FAIL: %s\n", t->name); + nr_failed++; + } } - unlink ("test1.img"); - unlink ("test2.img"); - unlink ("test3.img"); + return nr_failed; +} + +int +main (int argc, char *argv[]) +{ + size_t nr_failed; + guestfs_h *g; + + setbuf (stdout, NULL); + + no_test_warnings (); + + g = create_handle (); + + nr_failed = perform_tests (g); + + guestfs_close (g); if (nr_failed > 0) { printf ("***** %zu / %zu tests FAILED *****\n", nr_failed, nr_tests); diff --git a/tests/c-api/tests.h b/tests/c-api/tests.h index 122679070..2c846d9ee 100644 --- a/tests/c-api/tests.h +++ b/tests/c-api/tests.h @@ -19,6 +19,11 @@ #ifndef TESTS_H_ #define TESTS_H_ +struct test { + int (*test_fn) (guestfs_h *g); + const char *name; +}; +extern struct test tests[]; extern size_t nr_tests; extern int init_none (guestfs_h *g); @@ -29,7 +34,6 @@ extern int init_basic_fs (guestfs_h *g); extern int init_basic_fs_on_lvm (guestfs_h *g); extern int init_iso_fs (guestfs_h *g); extern int init_scratch_fs (guestfs_h *g); -extern size_t perform_tests (guestfs_h *g); extern void no_test_warnings (void); extern int is_string_list (char **ret, size_t n, ...); extern int is_device_list (char **ret, size_t n, ...); @@ -40,7 +44,6 @@ extern const char *get_key (char **hash, const char *key); extern int check_hash (char **ret, const char *key, const char *expected); extern int match_re (const char *str, const char *pattern); extern char *substitute_srcdir (const char *path); -extern void next_test (guestfs_h *g, size_t test_num, size_t nr_tests, const char *test_name); extern void skipped (const char *test_name, const char *fs, ...) __attribute__((format (printf,2,3))); #endif /* TESTS_H_ */