X-Git-Url: http://git.annexia.org/?a=blobdiff_plain;f=src%2Fgenerator.ml;h=99913a331219f210281b568a2fd002737ba937a3;hb=26637995f07006b7664e572879018adca7e328cb;hp=009b9804594685fb51aa3196df39eb277cc303c0;hpb=17fa7abbb83024deb639aebf27686848e232e085;p=libguestfs.git diff --git a/src/generator.ml b/src/generator.ml index 009b980..99913a3 100755 --- a/src/generator.ml +++ b/src/generator.ml @@ -136,8 +136,7 @@ can easily destroy all your data>." * the virtual machine and block devices are reused between tests. * So don't try testing kill_subprocess :-x * - * Between each test we blockdev-setrw, umount-all, lvm-remove-all - * (except InitNone). + * Between each test we blockdev-setrw, umount-all, lvm-remove-all. * * If the appliance is running an older Linux kernel (eg. RHEL 5) then * devices are named /dev/hda etc. To cope with this, the test suite @@ -154,6 +153,11 @@ can easily destroy all your data>." * skipped. Useful if testing a command which might not work on * all variations of libguestfs builds. A test that has prerequisite * of 'Always' is run unconditionally. + * + * In addition, packagers can skip individual tests by setting the + * environment variables: eg: + * SKIP_TEST__=1 SKIP_TEST_COMMAND_3=1 (skips test #3 of command) + * SKIP_TEST_=1 SKIP_TEST_ZEROFREE=1 (skips all zerofree tests) *) type tests = (test_init * test_prereq * test) list and test = @@ -207,6 +211,12 @@ and test_prereq = * unimplemented feature. *) | Disabled + (* 'string' is some C code (a function body) that should return + * true or false. The test will run if the code returns true. + *) + | If of string + (* As for 'If' but the test runs _unless_ the code returns true. *) + | Unless of string (* Some initial scenarios for testing. *) and test_init = @@ -1065,7 +1075,9 @@ information refer to the L manpage. To create a single partition occupying the whole disk, you would pass C as a single element list, when the single element being -the string C<,> (comma)."); +the string C<,> (comma). + +See also: C, C"); ("write_file", (RErr, [String "path"; String "content"; Int "size"]), 44, [ProtocolLimitWarning], [InitBasicFS, Always, TestOutput ( @@ -1650,22 +1662,25 @@ to find out what you can do."); ("lvremove", (RErr, [String "device"]), 77, [], [InitEmpty, Always, TestOutputList ( - [["pvcreate"; "/dev/sda"]; - ["vgcreate"; "VG"; "/dev/sda"]; + [["sfdisk"; "/dev/sda"; "0"; "0"; "0"; ","]; + ["pvcreate"; "/dev/sda1"]; + ["vgcreate"; "VG"; "/dev/sda1"]; ["lvcreate"; "LV1"; "VG"; "50"]; ["lvcreate"; "LV2"; "VG"; "50"]; ["lvremove"; "/dev/VG/LV1"]; ["lvs"]], ["/dev/VG/LV2"]); InitEmpty, Always, TestOutputList ( - [["pvcreate"; "/dev/sda"]; - ["vgcreate"; "VG"; "/dev/sda"]; + [["sfdisk"; "/dev/sda"; "0"; "0"; "0"; ","]; + ["pvcreate"; "/dev/sda1"]; + ["vgcreate"; "VG"; "/dev/sda1"]; ["lvcreate"; "LV1"; "VG"; "50"]; ["lvcreate"; "LV2"; "VG"; "50"]; ["lvremove"; "/dev/VG"]; ["lvs"]], []); InitEmpty, Always, TestOutputList ( - [["pvcreate"; "/dev/sda"]; - ["vgcreate"; "VG"; "/dev/sda"]; + [["sfdisk"; "/dev/sda"; "0"; "0"; "0"; ","]; + ["pvcreate"; "/dev/sda1"]; + ["vgcreate"; "VG"; "/dev/sda1"]; ["lvcreate"; "LV1"; "VG"; "50"]; ["lvcreate"; "LV2"; "VG"; "50"]; ["lvremove"; "/dev/VG"]; @@ -1680,15 +1695,17 @@ the VG name, C."); ("vgremove", (RErr, [String "vgname"]), 78, [], [InitEmpty, Always, TestOutputList ( - [["pvcreate"; "/dev/sda"]; - ["vgcreate"; "VG"; "/dev/sda"]; + [["sfdisk"; "/dev/sda"; "0"; "0"; "0"; ","]; + ["pvcreate"; "/dev/sda1"]; + ["vgcreate"; "VG"; "/dev/sda1"]; ["lvcreate"; "LV1"; "VG"; "50"]; ["lvcreate"; "LV2"; "VG"; "50"]; ["vgremove"; "VG"]; ["lvs"]], []); InitEmpty, Always, TestOutputList ( - [["pvcreate"; "/dev/sda"]; - ["vgcreate"; "VG"; "/dev/sda"]; + [["sfdisk"; "/dev/sda"; "0"; "0"; "0"; ","]; + ["pvcreate"; "/dev/sda1"]; + ["vgcreate"; "VG"; "/dev/sda1"]; ["lvcreate"; "LV1"; "VG"; "50"]; ["lvcreate"; "LV2"; "VG"; "50"]; ["vgremove"; "VG"]; @@ -1702,28 +1719,31 @@ group (if any)."); ("pvremove", (RErr, [String "device"]), 79, [], [InitEmpty, Always, TestOutputList ( - [["pvcreate"; "/dev/sda"]; - ["vgcreate"; "VG"; "/dev/sda"]; + [["sfdisk"; "/dev/sda"; "0"; "0"; "0"; ","]; + ["pvcreate"; "/dev/sda1"]; + ["vgcreate"; "VG"; "/dev/sda1"]; ["lvcreate"; "LV1"; "VG"; "50"]; ["lvcreate"; "LV2"; "VG"; "50"]; ["vgremove"; "VG"]; - ["pvremove"; "/dev/sda"]; + ["pvremove"; "/dev/sda1"]; ["lvs"]], []); InitEmpty, Always, TestOutputList ( - [["pvcreate"; "/dev/sda"]; - ["vgcreate"; "VG"; "/dev/sda"]; + [["sfdisk"; "/dev/sda"; "0"; "0"; "0"; ","]; + ["pvcreate"; "/dev/sda1"]; + ["vgcreate"; "VG"; "/dev/sda1"]; ["lvcreate"; "LV1"; "VG"; "50"]; ["lvcreate"; "LV2"; "VG"; "50"]; ["vgremove"; "VG"]; - ["pvremove"; "/dev/sda"]; + ["pvremove"; "/dev/sda1"]; ["vgs"]], []); InitEmpty, Always, TestOutputList ( - [["pvcreate"; "/dev/sda"]; - ["vgcreate"; "VG"; "/dev/sda"]; + [["sfdisk"; "/dev/sda"; "0"; "0"; "0"; ","]; + ["pvcreate"; "/dev/sda1"]; + ["vgcreate"; "VG"; "/dev/sda1"]; ["lvcreate"; "LV1"; "VG"; "50"]; ["lvcreate"; "LV2"; "VG"; "50"]; ["vgremove"; "VG"]; - ["pvremove"; "/dev/sda"]; + ["pvremove"; "/dev/sda1"]; ["pvs"]], [])], "remove an LVM physical volume", "\ @@ -1985,6 +2005,188 @@ The returned strings are transcoded to UTF-8."); This runs C on the given C. The result is the human-readable, canonical hex dump of the file."); + ("zerofree", (RErr, [String "device"]), 97, [], + [InitNone, Always, TestOutput ( + [["sfdisk"; "/dev/sda"; "0"; "0"; "0"; ","]; + ["mkfs"; "ext3"; "/dev/sda1"]; + ["mount"; "/dev/sda1"; "/"]; + ["write_file"; "/new"; "test file"; "0"]; + ["umount"; "/dev/sda1"]; + ["zerofree"; "/dev/sda1"]; + ["mount"; "/dev/sda1"; "/"]; + ["cat"; "/new"]], "test file")], + "zero unused inodes and disk blocks on ext2/3 filesystem", + "\ +This runs the I program on C. This program +claims to zero unused inodes and disk blocks on an ext2/3 +filesystem, thus making it possible to compress the filesystem +more effectively. + +You should B run this program if the filesystem is +mounted. + +It is possible that using this program can damage the filesystem +or data on the filesystem."); + + ("pvresize", (RErr, [String "device"]), 98, [], + [], + "resize an LVM physical volume", + "\ +This resizes (expands or shrinks) an existing LVM physical +volume to match the new size of the underlying device."); + + ("sfdisk_N", (RErr, [String "device"; Int "n"; + Int "cyls"; Int "heads"; Int "sectors"; + String "line"]), 99, [DangerWillRobinson], + [], + "modify a single partition on a block device", + "\ +This runs L option to modify just the single +partition C (note: C counts from 1). + +For other parameters, see C. You should usually +pass C<0> for the cyls/heads/sectors parameters."); + + ("sfdisk_l", (RString "partitions", [String "device"]), 100, [], + [], + "display the partition table", + "\ +This displays the partition table on C, in the +human-readable output of the L command. It is +not intended to be parsed."); + + ("sfdisk_kernel_geometry", (RString "partitions", [String "device"]), 101, [], + [], + "display the kernel geometry", + "\ +This displays the kernel's idea of the geometry of C. + +The result is in human-readable format, and not designed to +be parsed."); + + ("sfdisk_disk_geometry", (RString "partitions", [String "device"]), 102, [], + [], + "display the disk geometry from the partition table", + "\ +This displays the disk geometry of C read from the +partition table. Especially in the case where the underlying +block device has been resized, this can be different from the +kernel's idea of the geometry (see C). + +The result is in human-readable format, and not designed to +be parsed."); + + ("vg_activate_all", (RErr, [Bool "activate"]), 103, [], + [], + "activate or deactivate all volume groups", + "\ +This command activates or (if C is false) deactivates +all logical volumes in all volume groups. +If activated, then they are made known to the +kernel, ie. they appear as C devices. If deactivated, +then those devices disappear. + +This command is the same as running C"); + + ("vg_activate", (RErr, [Bool "activate"; StringList "volgroups"]), 104, [], + [], + "activate or deactivate some volume groups", + "\ +This command activates or (if C is false) deactivates +all logical volumes in the listed volume groups C. +If activated, then they are made known to the +kernel, ie. they appear as C devices. If deactivated, +then those devices disappear. + +This command is the same as running C + +Note that if C is an empty list then B volume groups +are activated or deactivated."); + + ("lvresize", (RErr, [String "device"; Int "mbytes"]), 105, [], + [InitNone, Always, TestOutput ( + [["sfdisk"; "/dev/sda"; "0"; "0"; "0"; ","]; + ["pvcreate"; "/dev/sda1"]; + ["vgcreate"; "VG"; "/dev/sda1"]; + ["lvcreate"; "LV"; "VG"; "10"]; + ["mkfs"; "ext2"; "/dev/VG/LV"]; + ["mount"; "/dev/VG/LV"; "/"]; + ["write_file"; "/new"; "test content"; "0"]; + ["umount"; "/"]; + ["lvresize"; "/dev/VG/LV"; "20"]; + ["e2fsck_f"; "/dev/VG/LV"]; + ["resize2fs"; "/dev/VG/LV"]; + ["mount"; "/dev/VG/LV"; "/"]; + ["cat"; "/new"]], "test content")], + "resize an LVM logical volume", + "\ +This resizes (expands or shrinks) an existing LVM logical +volume to C. When reducing, data in the reduced part +is lost."); + + ("resize2fs", (RErr, [String "device"]), 106, [], + [], (* lvresize tests this *) + "resize an ext2/ext3 filesystem", + "\ +This resizes an ext2 or ext3 filesystem to match the size of +the underlying device. + +I It is sometimes required that you run C +on the C before calling this command. For unknown reasons +C sometimes gives an error about this and sometimes not. +In any case, it is always safe to call C before +calling this function."); + + ("find", (RStringList "names", [String "directory"]), 107, [], + [InitBasicFS, Always, TestOutputList ( + [["find"; "/"]], ["lost+found"]); + InitBasicFS, Always, TestOutputList ( + [["touch"; "/a"]; + ["mkdir"; "/b"]; + ["touch"; "/b/c"]; + ["find"; "/"]], ["a"; "b"; "b/c"; "lost+found"]); + InitBasicFS, Always, TestOutputList ( + [["mkdir_p"; "/a/b/c"]; + ["touch"; "/a/b/c/d"]; + ["find"; "/a/b/"]], ["c"; "c/d"])], + "find all files and directories", + "\ +This command lists out all files and directories, recursively, +starting at C. It is essentially equivalent to +running the shell command C but some +post-processing happens on the output, described below. + +This returns a list of strings I. Thus +if the directory structure was: + + /tmp/a + /tmp/b + /tmp/c/d + +then the returned list from C C would be +4 elements: + + a + b + c + c/d + +If C is not a directory, then this command returns +an error. + +The returned list is sorted."); + + ("e2fsck_f", (RErr, [String "device"]), 108, [], + [], (* lvresize tests this *) + "check an ext2/ext3 filesystem", + "\ +This runs C, ie. runs the ext2/ext3 +filesystem checker on C, noninteractively (C<-p>), +even if the filesystem appears to be clean (C<-f>). + +This command is only needed because of C +(q.v.). Normally you should use C."); + ] let all_functions = non_daemon_functions @ daemon_functions @@ -2233,8 +2435,10 @@ let check_functions () = fun (name, _, _, _, _, _, _) -> if String.length name >= 7 && String.sub name 0 7 = "guestfs" then failwithf "function name %s does not need 'guestfs' prefix" name; - if contains_uppercase name then - failwithf "function name %s should not contain uppercase chars" name; + if name = "" then + failwithf "function name is empty"; + if name.[0] < 'a' || name.[0] > 'z' then + failwithf "function name %s must start with lowercase a-z" name; if String.contains name '-' then failwithf "function name %s should not contain '-', use '_' instead." name @@ -3666,12 +3870,57 @@ int main (int argc, char *argv[]) and generate_one_test name i (init, prereq, test) = let test_name = sprintf "test_%s_%d" name i in - pr "static int %s (void)\n" test_name; - pr "{\n"; + pr "\ +static int %s_skip (void) +{ + const char *str; + + str = getenv (\"SKIP_%s\"); + if (str && strcmp (str, \"1\") == 0) return 1; + str = getenv (\"SKIP_TEST_%s\"); + if (str && strcmp (str, \"1\") == 0) return 1; + return 0; +} + +" test_name (String.uppercase test_name) (String.uppercase name); + + (match prereq with + | Disabled | Always -> () + | If code | Unless code -> + pr "static int %s_prereq (void)\n" test_name; + pr "{\n"; + pr " %s\n" code; + pr "}\n"; + pr "\n"; + ); + + pr "\ +static int %s (void) +{ + if (%s_skip ()) { + printf (\"%%s skipped (reason: SKIP_TEST_* variable set)\\n\", \"%s\"); + return 0; + } + +" test_name test_name test_name; (match prereq with | Disabled -> - pr " printf (\"%%s skipped (test disabled in generator)\\n\", \"%s\");\n" test_name + pr " printf (\"%%s skipped (reason: test disabled in generator)\\n\", \"%s\");\n" test_name + | If _ -> + pr " if (! %s_prereq ()) {\n" test_name; + pr " printf (\"%%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name; + pr " return 0;\n"; + pr " }\n"; + pr "\n"; + generate_one_test_body name i test_name init test; + | Unless _ -> + pr " if (%s_prereq ()) {\n" test_name; + pr " printf (\"%%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name; + pr " return 0;\n"; + pr " }\n"; + pr "\n"; + generate_one_test_body name i test_name init test; | Always -> generate_one_test_body name i test_name init test ); @@ -3683,15 +3932,15 @@ and generate_one_test name i (init, prereq, test) = and generate_one_test_body name i test_name init test = (match init with - | InitNone -> () + | InitNone | InitEmpty -> - pr " /* InitEmpty for %s (%d) */\n" name i; + pr " /* InitNone|InitEmpty for %s */\n" test_name; List.iter (generate_test_command_call test_name) [["blockdev_setrw"; "/dev/sda"]; ["umount_all"]; ["lvm_remove_all"]] | InitBasicFS -> - pr " /* InitBasicFS for %s (%d): create ext2 on /dev/sda1 */\n" name i; + pr " /* InitBasicFS for %s: create ext2 on /dev/sda1 */\n" test_name; List.iter (generate_test_command_call test_name) [["blockdev_setrw"; "/dev/sda"]; ["umount_all"]; @@ -3700,8 +3949,8 @@ and generate_one_test_body name i test_name init test = ["mkfs"; "ext2"; "/dev/sda1"]; ["mount"; "/dev/sda1"; "/"]] | InitBasicFSonLVM -> - pr " /* InitBasicFSonLVM for %s (%d): create ext2 on /dev/VG/LV */\n" - name i; + pr " /* InitBasicFSonLVM for %s: create ext2 on /dev/VG/LV */\n" + test_name; List.iter (generate_test_command_call test_name) [["blockdev_setrw"; "/dev/sda"]; ["umount_all"];