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\"
46 #define error guestfs_error
47 #define safe_calloc guestfs_safe_calloc
48 #define safe_malloc guestfs_safe_malloc
51 print_strings (char *const *argv)
56 for (argc = 0; argv[argc] != NULL; ++argc) {
57 if (argc > 0) printf (\", \");
58 printf (\"\\\"%%s\\\"\", argv[argc]);
63 /* The test0 function prints its parameters to stdout. */
67 match test_functions with
69 | test0 :: tests -> test0, tests in
72 let (name, style, _, _, _, _, _) = test0 in
73 generate_prototype ~extern:false ~semicolon:false ~newline:true
74 ~handle:"g" ~prefix:"guestfs__" name style;
79 | Device n | Dev_or_Path n
83 | Key n -> pr " printf (\"%%s\\n\", %s);\n" n
87 pr " for (i = 0; i < %s_size; ++i)\n" n;
88 pr " printf (\"<%%02x>\", %s[i]);\n" n;
89 pr " printf (\"\\n\");\n";
91 | OptString n -> pr " printf (\"%%s\\n\", %s ? %s : \"null\");\n" n n
92 | StringList n | DeviceList n -> pr " print_strings (%s);\n" n
93 | Bool n -> pr " printf (\"%%s\\n\", %s ? \"true\" : \"false\");\n" n
94 | Int n -> pr " printf (\"%%d\\n\", %s);\n" n
95 | Int64 n -> pr " printf (\"%%\" PRIi64 \"\\n\", %s);\n" n
97 pr " /* Java changes stdout line buffering so we need this: */\n";
98 pr " fflush (stdout);\n";
104 fun (name, style, _, _, _, _, _) ->
105 if String.sub name (String.length name - 3) 3 <> "err" then (
106 pr "/* Test normal return. */\n";
107 generate_prototype ~extern:false ~semicolon:false ~newline:true
108 ~handle:"g" ~prefix:"guestfs__" name style;
110 (match fst style with
115 pr " sscanf (val, \"%%d\", &r);\n";
119 pr " sscanf (val, \"%%\" SCNi64, &r);\n";
122 pr " return STREQ (val, \"true\");\n"
124 | RConstOptString _ ->
125 (* Can't return the input string here. Return a static
126 * string so we ensure we get a segfault if the caller
129 pr " return \"static string\";\n"
131 pr " return strdup (val);\n"
133 pr " char **strs;\n";
135 pr " sscanf (val, \"%%d\", &n);\n";
136 pr " strs = safe_malloc (g, (n+1) * sizeof (char *));\n";
137 pr " for (i = 0; i < n; ++i) {\n";
138 pr " strs[i] = safe_malloc (g, 16);\n";
139 pr " snprintf (strs[i], 16, \"%%d\", i);\n";
141 pr " strs[n] = NULL;\n";
143 | RStruct (_, typ) ->
144 pr " struct guestfs_%s *r;\n" typ;
145 pr " r = safe_calloc (g, sizeof *r, 1);\n";
147 | RStructList (_, typ) ->
148 pr " struct guestfs_%s_list *r;\n" typ;
149 pr " r = safe_calloc (g, sizeof *r, 1);\n";
150 pr " sscanf (val, \"%%d\", &r->len);\n";
151 pr " r->val = safe_calloc (g, r->len, sizeof *r->val);\n";
154 pr " char **strs;\n";
156 pr " sscanf (val, \"%%d\", &n);\n";
157 pr " strs = safe_malloc (g, (n*2+1) * sizeof (*strs));\n";
158 pr " for (i = 0; i < n; ++i) {\n";
159 pr " strs[i*2] = safe_malloc (g, 16);\n";
160 pr " strs[i*2+1] = safe_malloc (g, 16);\n";
161 pr " snprintf (strs[i*2], 16, \"%%d\", i);\n";
162 pr " snprintf (strs[i*2+1], 16, \"%%d\", i);\n";
164 pr " strs[n*2] = NULL;\n";
167 pr " return strdup (val);\n"
172 pr "/* Test error return. */\n";
173 generate_prototype ~extern:false ~semicolon:false ~newline:true
174 ~handle:"g" ~prefix:"guestfs__" name style;
176 pr " error (g, \"error\");\n";
177 (match fst style with
178 | RErr | RInt _ | RInt64 _ | RBool _ ->
180 | RConstString _ | RConstOptString _
181 | RString _ | RStringList _ | RStruct _
192 and generate_ocaml_bindtests () =
193 generate_header OCamlStyle GPLv2plus;
197 let g = Guestfs.create () in
204 | CallString s -> "\"" ^ s ^ "\""
205 | CallOptString None -> "None"
206 | CallOptString (Some s) -> sprintf "(Some \"%s\")" s
207 | CallStringList xs ->
208 "[|" ^ String.concat ";" (List.map (sprintf "\"%s\"") xs) ^ "|]"
209 | CallInt i when i >= 0 -> string_of_int i
210 | CallInt i (* when i < 0 *) -> "(" ^ string_of_int i ^ ")"
211 | CallInt64 i when i >= 0L -> Int64.to_string i ^ "L"
212 | CallInt64 i (* when i < 0L *) -> "(" ^ Int64.to_string i ^ "L)"
213 | CallBool b -> string_of_bool b
214 | CallBuffer s -> sprintf "%S" s
219 generate_lang_bindtests (
220 fun f args -> pr " Guestfs.%s g %s;\n" f (mkargs args)
223 pr "print_endline \"EOF\"\n"
225 and generate_perl_bindtests () =
226 pr "#!/usr/bin/perl -w\n";
227 generate_header HashStyle GPLv2plus;
234 my $g = Sys::Guestfs->new ();
241 | CallString s -> "\"" ^ s ^ "\""
242 | CallOptString None -> "undef"
243 | CallOptString (Some s) -> sprintf "\"%s\"" s
244 | CallStringList xs ->
245 "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
246 | CallInt i -> string_of_int i
247 | CallInt64 i -> Int64.to_string i
248 | CallBool b -> if b then "1" else "0"
249 | CallBuffer s -> "\"" ^ c_quote s ^ "\""
254 generate_lang_bindtests (
255 fun f args -> pr "$g->%s (%s);\n" f (mkargs args)
258 pr "print \"EOF\\n\"\n"
260 and generate_python_bindtests () =
261 generate_header HashStyle GPLv2plus;
266 g = guestfs.GuestFS ()
273 | CallString s -> "\"" ^ s ^ "\""
274 | CallOptString None -> "None"
275 | CallOptString (Some s) -> sprintf "\"%s\"" s
276 | CallStringList xs ->
277 "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
278 | CallInt i -> string_of_int i
279 | CallInt64 i -> Int64.to_string i
280 | CallBool b -> if b then "1" else "0"
281 | CallBuffer s -> "\"" ^ c_quote s ^ "\""
286 generate_lang_bindtests (
287 fun f args -> pr "g.%s (%s)\n" f (mkargs args)
292 and generate_ruby_bindtests () =
293 generate_header HashStyle GPLv2plus;
298 g = Guestfs::create()
305 | CallString s -> "\"" ^ s ^ "\""
306 | CallOptString None -> "nil"
307 | CallOptString (Some s) -> sprintf "\"%s\"" s
308 | CallStringList xs ->
309 "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
310 | CallInt i -> string_of_int i
311 | CallInt64 i -> Int64.to_string i
312 | CallBool b -> string_of_bool b
313 | CallBuffer s -> "\"" ^ c_quote s ^ "\""
318 generate_lang_bindtests (
319 fun f args -> pr "g.%s(%s)\n" f (mkargs args)
322 pr "print \"EOF\\n\"\n"
324 and generate_java_bindtests () =
325 generate_header CStyle GPLv2plus;
328 import com.redhat.et.libguestfs.*;
330 public class Bindtests {
331 public static void main (String[] argv)
334 GuestFS g = new GuestFS ();
341 | CallString s -> "\"" ^ s ^ "\""
342 | CallOptString None -> "null"
343 | CallOptString (Some s) -> sprintf "\"%s\"" s
344 | CallStringList xs ->
346 String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "}"
347 | CallInt i -> string_of_int i
348 | CallInt64 i -> Int64.to_string i
349 | CallBool b -> string_of_bool b
351 "new byte[] { " ^ String.concat "," (
352 map_chars (fun c -> string_of_int (Char.code c)) s
358 generate_lang_bindtests (
359 fun f args -> pr " g.%s (%s);\n" f (mkargs args)
363 System.out.println (\"EOF\");
365 catch (Exception exn) {
366 System.err.println (exn);
373 and generate_haskell_bindtests () =
374 generate_header HaskellStyle GPLv2plus;
377 module Bindtests where
378 import qualified Guestfs
388 | CallString s -> "\"" ^ s ^ "\""
389 | CallOptString None -> "Nothing"
390 | CallOptString (Some s) -> sprintf "(Just \"%s\")" s
391 | CallStringList xs ->
392 "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
393 | CallInt i when i < 0 -> "(" ^ string_of_int i ^ ")"
394 | CallInt i -> string_of_int i
395 | CallInt64 i when i < 0L -> "(" ^ Int64.to_string i ^ ")"
396 | CallInt64 i -> Int64.to_string i
397 | CallBool true -> "True"
398 | CallBool false -> "False"
399 | CallBuffer s -> "\"" ^ c_quote s ^ "\""
404 generate_lang_bindtests (
405 fun f args -> pr " Guestfs.%s g %s\n" f (mkargs args)
408 pr " putStrLn \"EOF\"\n"
410 (* Language-independent bindings tests - we do it this way to
411 * ensure there is parity in testing bindings across all languages.
413 and generate_lang_bindtests call =
414 call "test0" [CallString "abc"; CallOptString (Some "def");
415 CallStringList []; CallBool false;
416 CallInt 0; CallInt64 0L; CallString "123"; CallString "456";
417 CallBuffer "abc\000abc"];
418 call "test0" [CallString "abc"; CallOptString None;
419 CallStringList []; CallBool false;
420 CallInt 0; CallInt64 0L; CallString "123"; CallString "456";
421 CallBuffer "abc\000abc"];
422 call "test0" [CallString ""; CallOptString (Some "def");
423 CallStringList []; CallBool false;
424 CallInt 0; CallInt64 0L; CallString "123"; CallString "456";
425 CallBuffer "abc\000abc"];
426 call "test0" [CallString ""; CallOptString (Some "");
427 CallStringList []; CallBool false;
428 CallInt 0; CallInt64 0L; CallString "123"; CallString "456";
429 CallBuffer "abc\000abc"];
430 call "test0" [CallString "abc"; CallOptString (Some "def");
431 CallStringList ["1"]; CallBool false;
432 CallInt 0; CallInt64 0L; CallString "123"; CallString "456";
433 CallBuffer "abc\000abc"];
434 call "test0" [CallString "abc"; CallOptString (Some "def");
435 CallStringList ["1"; "2"]; CallBool false;
436 CallInt 0; CallInt64 0L; CallString "123"; CallString "456";
437 CallBuffer "abc\000abc"];
438 call "test0" [CallString "abc"; CallOptString (Some "def");
439 CallStringList ["1"]; CallBool true;
440 CallInt 0; CallInt64 0L; CallString "123"; CallString "456";
441 CallBuffer "abc\000abc"];
442 call "test0" [CallString "abc"; CallOptString (Some "def");
443 CallStringList ["1"]; CallBool false;
444 CallInt (-1); CallInt64 (-1L); CallString "123"; CallString "456";
445 CallBuffer "abc\000abc"];
446 call "test0" [CallString "abc"; CallOptString (Some "def");
447 CallStringList ["1"]; CallBool false;
448 CallInt (-2); CallInt64 (-2L); CallString "123"; CallString "456";
449 CallBuffer "abc\000abc"];
450 call "test0" [CallString "abc"; CallOptString (Some "def");
451 CallStringList ["1"]; CallBool false;
452 CallInt 1; CallInt64 1L; CallString "123"; CallString "456";
453 CallBuffer "abc\000abc"];
454 call "test0" [CallString "abc"; CallOptString (Some "def");
455 CallStringList ["1"]; CallBool false;
456 CallInt 2; CallInt64 2L; CallString "123"; CallString "456";
457 CallBuffer "abc\000abc"];
458 call "test0" [CallString "abc"; CallOptString (Some "def");
459 CallStringList ["1"]; CallBool false;
460 CallInt 4095; CallInt64 4095L; CallString "123"; CallString "456";
461 CallBuffer "abc\000abc"];
462 call "test0" [CallString "abc"; CallOptString (Some "def");
463 CallStringList ["1"]; CallBool false;
464 CallInt 0; CallInt64 0L; CallString ""; CallString "";
465 CallBuffer "abc\000abc"]
467 (* XXX Add here tests of the return and error functions. *)