2 * Copyright (C) 2009-2010 Red Hat Inc.
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 (* Please read generator/README first. *)
26 open Generator_docstrings
27 open Generator_optgroups
28 open Generator_actions
29 open Generator_structs
32 let rec generate_bindtests () =
33 generate_header CStyle LGPLv2plus;
41 #include \"guestfs.h\"
42 #include \"guestfs-internal.h\"
43 #include \"guestfs-internal-actions.h\"
44 #include \"guestfs_protocol.h\"
47 print_strings (char *const *argv)
52 for (argc = 0; argv[argc] != NULL; ++argc) {
53 if (argc > 0) printf (\", \");
54 printf (\"\\\"%%s\\\"\", argv[argc]);
59 /* The test0 function prints its parameters to stdout. */
63 match test_functions with
65 | test0 :: tests -> test0, tests in
68 let (name, (ret, args, _ as style), _, _, _, _, _) = test0 in
69 generate_prototype ~extern:false ~semicolon:false ~newline:true
70 ~handle:"g" ~prefix:"guestfs__" name style;
75 | Device n | Dev_or_Path n
79 | Key n -> pr " printf (\"%%s\\n\", %s);\n" n
83 pr " for (i = 0; i < %s_size; ++i)\n" n;
84 pr " printf (\"<%%02x>\", %s[i]);\n" n;
85 pr " printf (\"\\n\");\n";
87 | OptString n -> pr " printf (\"%%s\\n\", %s ? %s : \"null\");\n" n n
88 | StringList n | DeviceList n -> pr " print_strings (%s);\n" n
89 | Bool n -> pr " printf (\"%%s\\n\", %s ? \"true\" : \"false\");\n" n
90 | Int n -> pr " printf (\"%%d\\n\", %s);\n" n
91 | Int64 n -> pr " printf (\"%%\" PRIi64 \"\\n\", %s);\n" n
92 | Pointer _ -> assert false
94 pr " /* Java changes stdout line buffering so we need this: */\n";
95 pr " fflush (stdout);\n";
101 fun (name, (ret, args, _ as style), _, _, _, _, _) ->
102 if String.sub name (String.length name - 3) 3 <> "err" then (
103 pr "/* Test normal return. */\n";
104 generate_prototype ~extern:false ~semicolon:false ~newline:true
105 ~handle:"g" ~prefix:"guestfs__" name style;
112 pr " if (sscanf (val, \"%%d\", &r) != 1) {\n";
113 pr " error (g, \"%%s: expecting int argument\", \"%s\");\n" name;
119 pr " if (sscanf (val, \"%%\" SCNi64, &r) != 1) {\n";
120 pr " error (g, \"%%s: expecting int64 argument\", \"%s\");\n" name;
125 pr " return STREQ (val, \"true\");\n"
127 | RConstOptString _ ->
128 (* Can't return the input string here. Return a static
129 * string so we ensure we get a segfault if the caller
132 pr " return \"static string\";\n"
134 pr " return strdup (val);\n"
136 pr " char **strs;\n";
138 pr " if (sscanf (val, \"%%d\", &n) != 1) {\n";
139 pr " error (g, \"%%s: expecting int argument\", \"%s\");\n" name;
140 pr " return NULL;\n";
142 pr " strs = safe_malloc (g, (n+1) * sizeof (char *));\n";
143 pr " for (i = 0; i < n; ++i) {\n";
144 pr " strs[i] = safe_malloc (g, 16);\n";
145 pr " snprintf (strs[i], 16, \"%%d\", i);\n";
147 pr " strs[n] = NULL;\n";
149 | RStruct (_, typ) ->
150 pr " struct guestfs_%s *r;\n" typ;
151 pr " r = safe_calloc (g, sizeof *r, 1);\n";
153 | RStructList (_, typ) ->
154 pr " struct guestfs_%s_list *r;\n" typ;
155 pr " uint32_t len;\n";
156 pr " if (sscanf (val, \"%%\" SCNu32, &len) != 1) {\n";
157 pr " error (g, \"%%s: expecting uint32 argument\", \"%s\");\n" name;
158 pr " return NULL;\n";
160 pr " r = safe_calloc (g, sizeof *r, 1);\n";
161 pr " r->len = len;\n";
162 pr " r->val = safe_calloc (g, r->len, sizeof *r->val);\n";
165 pr " char **strs;\n";
167 pr " if (sscanf (val, \"%%d\", &n) != -1) {\n";
168 pr " error (g, \"%%s: expecting int argument\", \"%s\");\n" name;
169 pr " return NULL;\n";
171 pr " strs = safe_malloc (g, (n*2+1) * sizeof (*strs));\n";
172 pr " for (i = 0; i < n; ++i) {\n";
173 pr " strs[i*2] = safe_malloc (g, 16);\n";
174 pr " strs[i*2+1] = safe_malloc (g, 16);\n";
175 pr " snprintf (strs[i*2], 16, \"%%d\", i);\n";
176 pr " snprintf (strs[i*2+1], 16, \"%%d\", i);\n";
178 pr " strs[n*2] = NULL;\n";
181 pr " return strdup (val);\n"
186 pr "/* Test error return. */\n";
187 generate_prototype ~extern:false ~semicolon:false ~newline:true
188 ~handle:"g" ~prefix:"guestfs__" name style;
190 pr " error (g, \"error\");\n";
192 | RErr | RInt _ | RInt64 _ | RBool _ ->
194 | RConstString _ | RConstOptString _
195 | RString _ | RStringList _ | RStruct _
206 and generate_ocaml_bindtests () =
207 generate_header OCamlStyle GPLv2plus;
211 let g = Guestfs.create () in
218 | CallString s -> "\"" ^ s ^ "\""
219 | CallOptString None -> "None"
220 | CallOptString (Some s) -> sprintf "(Some \"%s\")" s
221 | CallStringList xs ->
222 "[|" ^ String.concat ";" (List.map (sprintf "\"%s\"") xs) ^ "|]"
223 | CallInt i when i >= 0 -> string_of_int i
224 | CallInt i (* when i < 0 *) -> "(" ^ string_of_int i ^ ")"
225 | CallInt64 i when i >= 0L -> Int64.to_string i ^ "L"
226 | CallInt64 i (* when i < 0L *) -> "(" ^ Int64.to_string i ^ "L)"
227 | CallBool b -> string_of_bool b
228 | CallBuffer s -> sprintf "%S" s
233 generate_lang_bindtests (
234 fun f args -> pr " Guestfs.%s g %s;\n" f (mkargs args)
237 pr "print_endline \"EOF\"\n"
239 and generate_perl_bindtests () =
240 pr "#!/usr/bin/perl -w\n";
241 generate_header HashStyle GPLv2plus;
248 my $g = Sys::Guestfs->new ();
255 | CallString s -> "\"" ^ s ^ "\""
256 | CallOptString None -> "undef"
257 | CallOptString (Some s) -> sprintf "\"%s\"" s
258 | CallStringList xs ->
259 "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
260 | CallInt i -> string_of_int i
261 | CallInt64 i -> Int64.to_string i
262 | CallBool b -> if b then "1" else "0"
263 | CallBuffer s -> "\"" ^ c_quote s ^ "\""
268 generate_lang_bindtests (
269 fun f args -> pr "$g->%s (%s);\n" f (mkargs args)
272 pr "print \"EOF\\n\"\n"
274 and generate_python_bindtests () =
275 generate_header HashStyle GPLv2plus;
280 g = guestfs.GuestFS ()
287 | CallString s -> "\"" ^ s ^ "\""
288 | CallOptString None -> "None"
289 | CallOptString (Some s) -> sprintf "\"%s\"" s
290 | CallStringList xs ->
291 "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
292 | CallInt i -> string_of_int i
293 | CallInt64 i -> Int64.to_string i
294 | CallBool b -> if b then "1" else "0"
295 | CallBuffer s -> "\"" ^ c_quote s ^ "\""
300 generate_lang_bindtests (
301 fun f args -> pr "g.%s (%s)\n" f (mkargs args)
304 pr "print (\"EOF\")\n"
306 and generate_ruby_bindtests () =
307 generate_header HashStyle GPLv2plus;
312 g = Guestfs::create()
319 | CallString s -> "\"" ^ s ^ "\""
320 | CallOptString None -> "nil"
321 | CallOptString (Some s) -> sprintf "\"%s\"" s
322 | CallStringList xs ->
323 "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
324 | CallInt i -> string_of_int i
325 | CallInt64 i -> Int64.to_string i
326 | CallBool b -> string_of_bool b
327 | CallBuffer s -> "\"" ^ c_quote s ^ "\""
332 generate_lang_bindtests (
333 fun f args -> pr "g.%s(%s)\n" f (mkargs args)
336 pr "print \"EOF\\n\"\n"
338 and generate_java_bindtests () =
339 generate_header CStyle GPLv2plus;
342 import com.redhat.et.libguestfs.*;
344 public class Bindtests {
345 public static void main (String[] argv)
348 GuestFS g = new GuestFS ();
355 | CallString s -> "\"" ^ s ^ "\""
356 | CallOptString None -> "null"
357 | CallOptString (Some s) -> sprintf "\"%s\"" s
358 | CallStringList xs ->
360 String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "}"
361 | CallInt i -> string_of_int i
362 | CallInt64 i -> Int64.to_string i
363 | CallBool b -> string_of_bool b
365 "new byte[] { " ^ String.concat "," (
366 map_chars (fun c -> string_of_int (Char.code c)) s
372 generate_lang_bindtests (
373 fun f args -> pr " g.%s (%s);\n" f (mkargs args)
377 System.out.println (\"EOF\");
379 catch (Exception exn) {
380 System.err.println (exn);
387 and generate_haskell_bindtests () =
388 generate_header HaskellStyle GPLv2plus;
391 module Bindtests where
392 import qualified Guestfs
402 | CallString s -> "\"" ^ s ^ "\""
403 | CallOptString None -> "Nothing"
404 | CallOptString (Some s) -> sprintf "(Just \"%s\")" s
405 | CallStringList xs ->
406 "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
407 | CallInt i when i < 0 -> "(" ^ string_of_int i ^ ")"
408 | CallInt i -> string_of_int i
409 | CallInt64 i when i < 0L -> "(" ^ Int64.to_string i ^ ")"
410 | CallInt64 i -> Int64.to_string i
411 | CallBool true -> "True"
412 | CallBool false -> "False"
413 | CallBuffer s -> "\"" ^ c_quote s ^ "\""
418 generate_lang_bindtests (
419 fun f args -> pr " Guestfs.%s g %s\n" f (mkargs args)
422 pr " putStrLn \"EOF\"\n"
424 (* Language-independent bindings tests - we do it this way to
425 * ensure there is parity in testing bindings across all languages.
427 and generate_lang_bindtests call =
428 call "test0" [CallString "abc"; CallOptString (Some "def");
429 CallStringList []; CallBool false;
430 CallInt 0; CallInt64 0L; CallString "123"; CallString "456";
431 CallBuffer "abc\000abc"];
432 call "test0" [CallString "abc"; CallOptString None;
433 CallStringList []; CallBool false;
434 CallInt 0; CallInt64 0L; CallString "123"; CallString "456";
435 CallBuffer "abc\000abc"];
436 call "test0" [CallString ""; CallOptString (Some "def");
437 CallStringList []; CallBool false;
438 CallInt 0; CallInt64 0L; CallString "123"; CallString "456";
439 CallBuffer "abc\000abc"];
440 call "test0" [CallString ""; CallOptString (Some "");
441 CallStringList []; CallBool false;
442 CallInt 0; CallInt64 0L; CallString "123"; CallString "456";
443 CallBuffer "abc\000abc"];
444 call "test0" [CallString "abc"; CallOptString (Some "def");
445 CallStringList ["1"]; CallBool false;
446 CallInt 0; CallInt64 0L; CallString "123"; CallString "456";
447 CallBuffer "abc\000abc"];
448 call "test0" [CallString "abc"; CallOptString (Some "def");
449 CallStringList ["1"; "2"]; CallBool false;
450 CallInt 0; CallInt64 0L; CallString "123"; CallString "456";
451 CallBuffer "abc\000abc"];
452 call "test0" [CallString "abc"; CallOptString (Some "def");
453 CallStringList ["1"]; CallBool true;
454 CallInt 0; CallInt64 0L; CallString "123"; CallString "456";
455 CallBuffer "abc\000abc"];
456 call "test0" [CallString "abc"; CallOptString (Some "def");
457 CallStringList ["1"]; CallBool false;
458 CallInt (-1); CallInt64 (-1L); CallString "123"; CallString "456";
459 CallBuffer "abc\000abc"];
460 call "test0" [CallString "abc"; CallOptString (Some "def");
461 CallStringList ["1"]; CallBool false;
462 CallInt (-2); CallInt64 (-2L); CallString "123"; CallString "456";
463 CallBuffer "abc\000abc"];
464 call "test0" [CallString "abc"; CallOptString (Some "def");
465 CallStringList ["1"]; CallBool false;
466 CallInt 1; CallInt64 1L; CallString "123"; CallString "456";
467 CallBuffer "abc\000abc"];
468 call "test0" [CallString "abc"; CallOptString (Some "def");
469 CallStringList ["1"]; CallBool false;
470 CallInt 2; CallInt64 2L; CallString "123"; CallString "456";
471 CallBuffer "abc\000abc"];
472 call "test0" [CallString "abc"; CallOptString (Some "def");
473 CallStringList ["1"]; CallBool false;
474 CallInt 4095; CallInt64 4095L; CallString "123"; CallString "456";
475 CallBuffer "abc\000abc"];
476 call "test0" [CallString "abc"; CallOptString (Some "def");
477 CallStringList ["1"]; CallBool false;
478 CallInt 0; CallInt64 0L; CallString ""; CallString "";
479 CallBuffer "abc\000abc"]
481 (* XXX Add here tests of the return and error functions. *)