X-Git-Url: http://git.annexia.org/?p=libguestfs.git;a=blobdiff_plain;f=src%2Fgenerator.ml;h=b3f27cd709362bd29f356a6264c64dd72665b943;hp=ffee564ed6e89527887fe923ba2da2c9cdb29c62;hb=ccc1d216032ff61a81eb1116df44d5bd82079462;hpb=2ef06eacc2be08b0268c98a4d157176aff9356e0 diff --git a/src/generator.ml b/src/generator.ml index ffee564..b3f27cd 100755 --- a/src/generator.ml +++ b/src/generator.ml @@ -143,13 +143,6 @@ can easily destroy all your data>." * * 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 - * adds some hairly logic to detect this case, and then automagically - * replaces all strings which match "/dev/sd.*" with "/dev/hd.*". - * When writing test cases you shouldn't have to worry about this - * difference. - * * Don't assume anything about the previous contents of the block * devices. Use 'Init*' to create some initial scenarios. * @@ -177,6 +170,12 @@ and test = *) | TestOutputList of seq * string list (* Run the command sequence and expect the output of the final + * command to be the list of block devices (could be either + * "/dev/sd.." or "/dev/hd.." form - we don't check the 5th + * character of each string). + *) + | TestOutputListOfDevices of seq * string list + (* Run the command sequence and expect the output of the final * command to be the integer. *) | TestOutputInt of seq * int @@ -693,7 +692,7 @@ This command is mostly useful for interactive sessions. Programs should probably use C instead."); ("list_devices", (RStringList "devices", []), 7, [], - [InitEmpty, Always, TestOutputList ( + [InitEmpty, Always, TestOutputListOfDevices ( [["list_devices"]], ["/dev/sda"; "/dev/sdb"; "/dev/sdc"; "/dev/sdd"])], "list the block devices", "\ @@ -702,9 +701,9 @@ List all the block devices. The full block device names are returned, eg. C"); ("list_partitions", (RStringList "partitions", []), 8, [], - [InitBasicFS, Always, TestOutputList ( + [InitBasicFS, Always, TestOutputListOfDevices ( [["list_partitions"]], ["/dev/sda1"]); - InitEmpty, Always, TestOutputList ( + InitEmpty, Always, TestOutputListOfDevices ( [["sfdisk"; "/dev/sda"; "0"; "0"; "0"; ",10 ,20 ,"]; ["list_partitions"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])], "list the partitions", @@ -717,9 +716,9 @@ This does not return logical volumes. For that you will need to call C."); ("pvs", (RStringList "physvols", []), 9, [], - [InitBasicFSonLVM, Always, TestOutputList ( + [InitBasicFSonLVM, Always, TestOutputListOfDevices ( [["pvs"]], ["/dev/sda1"]); - InitEmpty, Always, TestOutputList ( + InitEmpty, Always, TestOutputListOfDevices ( [["sfdisk"; "/dev/sda"; "0"; "0"; "0"; ",10 ,20 ,"]; ["pvcreate"; "/dev/sda1"]; ["pvcreate"; "/dev/sda2"]; @@ -1112,7 +1111,7 @@ other objects like files. See also C."); ("pvcreate", (RErr, [String "device"]), 39, [], - [InitEmpty, Always, TestOutputList ( + [InitEmpty, Always, TestOutputListOfDevices ( [["sfdisk"; "/dev/sda"; "0"; "0"; "0"; ",10 ,20 ,"]; ["pvcreate"; "/dev/sda1"]; ["pvcreate"; "/dev/sda2"]; @@ -1235,7 +1234,7 @@ We hope to resolve this bug in a future version. In the meantime use C."); ("umount", (RErr, [String "pathordevice"]), 45, [FishAlias "unmount"], - [InitEmpty, Always, TestOutputList ( + [InitEmpty, Always, TestOutputListOfDevices ( [["sfdisk"; "/dev/sda"; "0"; "0"; "0"; ","]; ["mkfs"; "ext2"; "/dev/sda1"]; ["mount"; "/dev/sda1"; "/"]; @@ -1253,7 +1252,7 @@ specified either by its mountpoint (path) or the device which contains the filesystem."); ("mounts", (RStringList "devices", []), 46, [], - [InitBasicFS, Always, TestOutputList ( + [InitBasicFS, Always, TestOutputListOfDevices ( [["mounts"]], ["/dev/sda1"])], "show mounted filesystems", "\ @@ -1656,7 +1655,10 @@ See also C, C."); [["write_file"; "/new"; "test\n"; "0"]; ["checksum"; "sha512"; "/new"]], "0e3e75234abc68f4378a86b3f4b32a198ba301845b0cd6e50106e874345700cc6663a86c1ea125dc5e92be17c98f9a0f85ca9d5f595db2012f7cc3571945c123"); InitBasicFS, Always, TestOutput ( - [["mount"; "/dev/sdd"; "/"]; + (* RHEL 5 thinks this is an HFS+ filesystem unless we give + * the type explicitly. + *) + [["mount_vfs"; "ro"; "squashfs"; "/dev/sdd"; "/"]; ["checksum"; "md5"; "/known-3"]], "46d6ca27ee07cdc6fa99c2e138cc522c")], "compute MD5, SHAx or CRC checksum of file", "\ @@ -1842,7 +1844,7 @@ This also forcibly removes all logical volumes in the volume group (if any)."); ("pvremove", (RErr, [String "device"]), 79, [], - [InitEmpty, Always, TestOutputList ( + [InitEmpty, Always, TestOutputListOfDevices ( [["sfdisk"; "/dev/sda"; "0"; "0"; "0"; ","]; ["pvcreate"; "/dev/sda1"]; ["vgcreate"; "VG"; "/dev/sda1"]; @@ -1851,7 +1853,7 @@ group (if any)."); ["vgremove"; "VG"]; ["pvremove"; "/dev/sda1"]; ["lvs"]], []); - InitEmpty, Always, TestOutputList ( + InitEmpty, Always, TestOutputListOfDevices ( [["sfdisk"; "/dev/sda"; "0"; "0"; "0"; ","]; ["pvcreate"; "/dev/sda1"]; ["vgcreate"; "VG"; "/dev/sda1"]; @@ -1860,7 +1862,7 @@ group (if any)."); ["vgremove"; "VG"]; ["pvremove"; "/dev/sda1"]; ["vgs"]], []); - InitEmpty, Always, TestOutputList ( + InitEmpty, Always, TestOutputListOfDevices ( [["sfdisk"; "/dev/sda"; "0"; "0"; "0"; ","]; ["pvcreate"; "/dev/sda1"]; ["vgcreate"; "VG"; "/dev/sda1"]; @@ -2318,6 +2320,29 @@ This command is only needed because of C "\ Sleep for C seconds."); + ("ntfs_3g_probe", (RInt "status", [Bool "rw"; String "device"]), 110, [], + [InitNone, Always, TestOutputInt ( + [["sfdisk"; "/dev/sda"; "0"; "0"; "0"; ","]; + ["mkfs"; "ntfs"; "/dev/sda1"]; + ["ntfs_3g_probe"; "true"; "/dev/sda1"]], 0); + InitNone, Always, TestOutputInt ( + [["sfdisk"; "/dev/sda"; "0"; "0"; "0"; ","]; + ["mkfs"; "ext2"; "/dev/sda1"]; + ["ntfs_3g_probe"; "true"; "/dev/sda1"]], 12)], + "probe NTFS volume", + "\ +This command runs the L command which probes +an NTFS C for mountability. (Not all NTFS volumes can +be mounted read-write, and some cannot be mounted at all). + +C is a boolean flag. Set it to true if you want to test +if the volume can be mounted read-write. Set it to false if +you want to test if the volume can be mounted read-only. + +The return value is an integer which C<0> if the operation +would succeed, or some non-zero value documented in the +L manual page."); + ] let all_functions = non_daemon_functions @ daemon_functions @@ -2550,6 +2575,7 @@ let name_of_argt = function let seq_of_test = function | TestRun s | TestOutput (s, _) | TestOutputList (s, _) + | TestOutputListOfDevices (s, _) | TestOutputInt (s, _) | TestOutputTrue s | TestOutputFalse s | TestOutputLength (s, _) | TestOutputStruct (s, _) | TestLastFail s -> s @@ -3473,8 +3499,12 @@ and generate_daemon_actions () = pr " struct guestfs_%s_args args;\n" name; List.iter ( function + (* Note we allow the string to be writable, in order to + * allow device name translation. This is safe because + * we can modify the string (passed from RPC). + *) | String n - | OptString n -> pr " const char *%s;\n" n + | OptString n -> pr " char *%s;\n" n | StringList n -> pr " char **%s;\n" n | Bool n -> pr " int %s;\n" n | Int n -> pr " int %s;\n" n @@ -3785,11 +3815,6 @@ and generate_tests () = static guestfs_h *g; static int suppress_error = 0; -/* This will be 's' or 'h' depending on whether the guest kernel - * names IDE devices /dev/sd* or /dev/hd*. - */ -static char devchar = 's'; - static void print_error (guestfs_h *g, void *data, const char *msg) { if (!suppress_error) @@ -3847,9 +3872,8 @@ int main (int argc, char *argv[]) char c = 0; int failed = 0; const char *filename; - int fd, i; + int fd; int nr_tests, test_num = 0; - char **devs; no_test_warnings (); @@ -3961,28 +3985,6 @@ int main (int argc, char *argv[]) exit (1); } - /* Detect if the appliance uses /dev/sd* or /dev/hd* in device - * names. This changed between RHEL 5 and RHEL 6 so we have to - * support both. - */ - devs = guestfs_list_devices (g); - if (devs == NULL || devs[0] == NULL) { - printf (\"guestfs_list_devices FAILED\\n\"); - exit (1); - } - if (strncmp (devs[0], \"/dev/sd\", 7) == 0) - devchar = 's'; - else if (strncmp (devs[0], \"/dev/hd\", 7) == 0) - devchar = 'h'; - else { - printf (\"guestfs_list_devices returned unexpected string '%%s'\\n\", - devs[0]); - exit (1); - } - for (i = 0; devs[i] != NULL; ++i) - free (devs[i]); - free (devs); - nr_tests = %d; " (500 * 1024 * 1024) (50 * 1024 * 1024) (10 * 1024 * 1024) nr_tests; @@ -4125,9 +4127,6 @@ and generate_one_test_body name i test_name init test = | TestOutput (seq, expected) -> pr " /* TestOutput for %s (%d) */\n" name i; pr " char expected[] = \"%s\";\n" (c_quote expected); - if String.length expected > 7 && - String.sub expected 0 7 = "/dev/sd" then - pr " expected[5] = devchar;\n"; let seq, last = get_seq_last seq in let test () = pr " if (strcmp (r, expected) != 0) {\n"; @@ -4150,8 +4149,35 @@ and generate_one_test_body name i test_name init test = pr " }\n"; pr " {\n"; pr " char expected[] = \"%s\";\n" (c_quote str); - if String.length str > 7 && String.sub str 0 7 = "/dev/sd" then - pr " expected[5] = devchar;\n"; + pr " if (strcmp (r[%d], expected) != 0) {\n" i; + pr " fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i; + pr " return -1;\n"; + pr " }\n"; + pr " }\n" + ) expected; + pr " if (r[%d] != NULL) {\n" (List.length expected); + pr " fprintf (stderr, \"%s: extra elements returned from command\\n\");\n" + test_name; + pr " print_strings (r);\n"; + pr " return -1;\n"; + pr " }\n" + in + List.iter (generate_test_command_call test_name) seq; + generate_test_command_call ~test test_name last + | TestOutputListOfDevices (seq, expected) -> + pr " /* TestOutputListOfDevices for %s (%d) */\n" name i; + let seq, last = get_seq_last seq in + let test () = + iteri ( + fun i str -> + pr " if (!r[%d]) {\n" i; + pr " fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name; + pr " print_strings (r);\n"; + pr " return -1;\n"; + pr " }\n"; + pr " {\n"; + pr " char expected[] = \"%s\";\n" (c_quote str); + pr " r[%d][5] = 's';\n" i; pr " if (strcmp (r[%d], expected) != 0) {\n" i; pr " fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i; pr " return -1;\n"; @@ -4297,8 +4323,6 @@ and generate_test_command_call ?(expect_error = false) ?test test_name cmd = | String n, arg | OptString n, arg -> pr " char %s[] = \"%s\";\n" n (c_quote arg); - if String.length arg > 7 && String.sub arg 0 7 = "/dev/sd" then - pr " %s[5] = devchar;\n" n | Int _, _ | Bool _, _ | FileIn _, _ | FileOut _, _ -> () @@ -4307,8 +4331,6 @@ and generate_test_command_call ?(expect_error = false) ?test test_name cmd = iteri ( fun i str -> pr " char %s_%d[] = \"%s\";\n" n i (c_quote str); - if String.length str > 7 && String.sub str 0 7 = "/dev/sd" then - pr " %s_%d[5] = devchar;\n" n i ) strs; pr " char *%s[] = {\n" n; iteri ( @@ -4906,8 +4928,14 @@ and generate_prototype ?(extern = true) ?(static = false) ?(semicolon = true) List.iter ( function | String n - | OptString n -> next (); pr "const char *%s" n - | StringList n -> next (); pr "char * const* const %s" n + | OptString n -> + next (); + if not in_daemon then pr "const char *%s" n + else pr "char *%s" n + | StringList n -> + next (); + if not in_daemon then pr "char * const* const %s" n + else pr "char **%s" n | Bool n -> next (); pr "int %s" n | Int n -> next (); pr "int %s" n | FileIn n