capitests: Allow tests to properly test optional arguments.
[libguestfs.git] / generator / generator_capitests.ml
index 5b40cc2..963ed51 100644 (file)
@@ -774,43 +774,59 @@ and generate_test_command_call ?(expect_error = false) ?test test_name cmd =
             assert false
       ) args;
 
-      (* Currently can only deal with a complete, in-order list of optargs. *)
       if optargs <> [] then (
         pr "    struct guestfs_%s_argv optargs;\n" name;
-        let len = List.length style_optargs in
-        let bitmask = Int64.pred (Int64.shift_left 1L len) in
+        let bitmask = List.fold_left (
+          fun bitmask optarg ->
+            let is_set =
+              match optarg with
+              | Bool n, "" -> false
+              | Bool n, "true" ->
+                  pr "    optargs.%s = 1;\n" n; true
+              | Bool n, "false" ->
+                  pr "    optargs.%s = 0;\n" n; true
+              | Bool n, arg ->
+                  failwithf "boolean optional arg '%s' should be empty string or \"true\" or \"false\"" n
+              | Int n, "" -> false
+              | Int n, i ->
+                  let i =
+                    try int_of_string i
+                    with Failure _ -> failwithf "integer optional arg '%s' should be empty string or number" n in
+                  pr "    optargs.%s = %d;\n" n i; true
+              | Int64 n, "" -> false
+              | Int64 n, i ->
+                  let i =
+                    try Int64.of_string i
+                    with Failure _ -> failwithf "int64 optional arg '%s' should be empty string or number" n in
+                  pr "    optargs.%s = %Ld;\n" n i; true
+              | String n, "NOARG" -> false
+              | String n, arg ->
+                  pr "    optargs.%s = \"%s\";\n" n (c_quote arg); true
+              | _ -> assert false in
+            let bitmask = Int64.shift_left bitmask 1 in
+            let bitmask = if is_set then Int64.succ bitmask else bitmask in
+            bitmask
+        ) 0L optargs in
         pr "    optargs.bitmask = UINT64_C(0x%Lx);\n" bitmask;
-        List.iter (
-          function
-          | Bool n, arg
-          | Int n, arg
-          | Int64 n, arg ->
-              pr "    optargs.%s = %s;\n" n arg
-          | String n, arg ->
-              pr "    optargs.%s = \"%s\";\n" n (c_quote arg);
-          | _ -> assert false
-        ) optargs;
       );
 
-      let error_code =
-        match style_ret with
-        | RErr | RInt _ | RBool _ -> pr "    int r;\n"; "-1"
-        | RInt64 _ -> pr "    int64_t r;\n"; "-1"
-        | RConstString _ | RConstOptString _ ->
-            pr "    const char *r;\n"; "NULL"
-        | RString _ -> pr "    char *r;\n"; "NULL"
-        | RStringList _ | RHashtable _ ->
-            pr "    char **r;\n";
-            pr "    size_t i;\n";
-            "NULL"
-        | RStruct (_, typ) ->
-            pr "    struct guestfs_%s *r;\n" typ; "NULL"
-        | RStructList (_, typ) ->
-            pr "    struct guestfs_%s_list *r;\n" typ; "NULL"
-        | RBufferOut _ ->
-            pr "    char *r;\n";
-            pr "    size_t size;\n";
-            "NULL" in
+      (match style_ret with
+       | RErr | RInt _ | RBool _ -> pr "    int r;\n"
+       | RInt64 _ -> pr "    int64_t r;\n"
+       | RConstString _ | RConstOptString _ ->
+           pr "    const char *r;\n"
+       | RString _ -> pr "    char *r;\n"
+       | RStringList _ | RHashtable _ ->
+           pr "    char **r;\n";
+           pr "    size_t i;\n"
+       | RStruct (_, typ) ->
+           pr "    struct guestfs_%s *r;\n" typ
+       | RStructList (_, typ) ->
+           pr "    struct guestfs_%s_list *r;\n" typ
+       | RBufferOut _ ->
+           pr "    char *r;\n";
+           pr "    size_t size;\n"
+      );
 
       pr "    suppress_error = %d;\n" (if expect_error then 1 else 0);
       if optargs = [] then
@@ -861,11 +877,21 @@ and generate_test_command_call ?(expect_error = false) ?test test_name cmd =
 
       pr ");\n";
 
-      if not expect_error then
-        pr "    if (r == %s)\n" error_code
-      else
-        pr "    if (r != %s)\n" error_code;
-      pr "      return -1;\n";
+      (match errcode_of_ret style_ret, expect_error with
+       | `CannotReturnError, _ -> ()
+       | `ErrorIsMinusOne, false ->
+           pr "    if (r == -1)\n";
+           pr "      return -1;\n";
+       | `ErrorIsMinusOne, true ->
+           pr "    if (r != -1)\n";
+           pr "      return -1;\n";
+       | `ErrorIsNULL, false ->
+           pr "    if (r == NULL)\n";
+           pr "      return -1;\n";
+       | `ErrorIsNULL, true ->
+           pr "    if (r != NULL)\n";
+           pr "      return -1;\n";
+      );
 
       (* Insert the test code. *)
       (match test with