Add Go (language) bindings.

This commit is contained in:
Richard W.M. Jones
2013-07-01 12:45:09 +01:00
parent 667b303c9a
commit b6f01f3260
23 changed files with 1127 additions and 0 deletions

1
.gitignore vendored
View File

@@ -173,6 +173,7 @@ Makefile.in
/gobject/Guestfs-1.0.typelib
/gobject/guestfs-gobject*.c
/gobject/guestfs-gobject*.h
/golang/pkg
/guestfs-release-notes.1
/guestfsd-in-wine.log
/haskell/Bindtests

View File

@@ -104,6 +104,9 @@ endif
if HAVE_GOBJECT
SUBDIRS += gobject
endif
if HAVE_GOLANG
SUBDIRS += golang
endif
# Unconditional because nothing is built yet.
SUBDIRS += csharp

2
README
View File

@@ -191,6 +191,8 @@ The full requirements are described below.
+--------------+-------------+---+-----------------------------------------+
| erl_interface| | O | For the Erlang bindings. |
+--------------+-------------+---+-----------------------------------------+
| golang | 1.1.1 | O | For the Go bindings. |
+--------------+-------------+---+-----------------------------------------+
| valgrind | | O | For testing for memory problems. |
+--------------+-------------+---+-----------------------------------------+
| Sys::Virt | | O | Perl bindings for libvirt. |

View File

@@ -1446,6 +1446,34 @@ AS_IF([test "x$enable_lua" != "xno"],[
])
AM_CONDITIONAL([HAVE_LUA],[test "x$LUA_LIBS" != "x"])
dnl Golang
AC_ARG_ENABLE([golang],
AS_HELP_STRING([--disable-golang], [disable Go language bindings]),
[],
[enable_golang=yes])
AS_IF([test "x$enable_golang" != "xno"],[
AC_CHECK_PROG([GOLANG],[go],[go],[no])
AS_IF([test "x$GOLANG" != "xno"],[
AC_MSG_CHECKING([if $GOLANG is usable])
AS_IF([$GOLANG run golang/config-test.go],[
AC_MSG_RESULT([yes])
# Substitute some golang environment.
GOOS=`$GOLANG env GOOS`
GOARCH=`$GOLANG env GOARCH`
GOROOT=`$GOLANG env GOROOT`
AC_SUBST([GOOS])
AC_SUBST([GOARCH])
AC_SUBST([GOROOT])
],[
AC_MSG_RESULT([no])
AC_MSG_WARN([golang ($GOLANG) is installed but not usable])
GOLANG=no
])
])
],[GOLANG=no])
AM_CONDITIONAL([HAVE_GOLANG],[test "x$GOLANG" != "xno"])
dnl Check for Perl modules needed by Perl virt tools (virt-df, etc.)
AS_IF([test "x$PERL" != "xno"],[
missing_perl_modules=no
@@ -1588,6 +1616,7 @@ AC_CONFIG_FILES([Makefile
gobject/Makefile
gobject/docs/Makefile
gobject/docs/guestfs-docs.sgml
golang/Makefile
haskell/Makefile
inspector/Makefile
java/Makefile
@@ -1687,6 +1716,8 @@ AS_ECHO_N(["Erlang bindings ..................... "])
if test "x$HAVE_ERLANG_TRUE" = "x"; then echo "yes"; else echo "no"; fi
AS_ECHO_N(["Lua bindings ........................ "])
if test "x$HAVE_LUA_TRUE" = "x"; then echo "yes"; else echo "no"; fi
AS_ECHO_N(["Go bindings ......................... "])
if test "x$HAVE_GOLANG_TRUE" = "x"; then echo "yes"; else echo "no"; fi
AS_ECHO_N(["gobject bindings .................... "])
if test "x$HAVE_GOBJECT_TRUE" = "x"; then echo "yes"; else echo "no"; fi
AS_ECHO_N(["gobject introspection ............... "])

View File

@@ -34,6 +34,7 @@ sources = \
events.ml \
fish.ml \
gobject.ml \
golang.ml \
haskell.ml \
java.ml \
lua.ml \
@@ -85,6 +86,7 @@ objects = \
erlang.cmo \
lua.cmo \
gobject.cmo \
golang.cmo \
bindtests.cmo \
errnostring.cmo \
main.cmo

508
generator/golang.ml Normal file
View File

@@ -0,0 +1,508 @@
(* libguestfs
* Copyright (C) 2013 Red Hat Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*)
(* Please read generator/README first. *)
open Printf
open Types
open Utils
open Pr
open Docstrings
open Optgroups
open Actions
open Structs
open C
open Events
let generate_golang_go () =
generate_header CStyle LGPLv2plus;
pr "\
package guestfs
/*
#cgo CFLAGS: -I../src -DGUESTFS_PRIVATE=1
#cgo LDFLAGS: -L../src/.libs -lguestfs
#include <stdio.h>
#include <stdlib.h>
#include <guestfs.h>
// cgo can't deal with variable argument functions.
static guestfs_h *
_go_guestfs_create_flags (unsigned flags)
{
return guestfs_create_flags (flags);
}
*/
import \"C\"
import (
\"fmt\"
\"runtime\"
\"syscall\"
\"unsafe\"
)
/* Handle. */
type Guestfs struct {
g *C.guestfs_h
}
/* Convert handle to string (just for debugging). */
func (g *Guestfs) String () string {
return \"&Guestfs{}\"
}
/* Create a new handle with flags. */
type CreateFlags uint
const (
CREATE_NO_ENVIRONMENT = CreateFlags (C.GUESTFS_CREATE_NO_ENVIRONMENT)
CREATE_NO_CLOSE_ON_EXIT = CreateFlags (C.GUESTFS_CREATE_NO_CLOSE_ON_EXIT)
)
func Create_flags (flags CreateFlags) (*Guestfs, error) {
c_g, err := C._go_guestfs_create_flags (C.uint (flags))
if c_g == nil {
return nil, err
}
g := &Guestfs{g : c_g}
// Finalizers aren't guaranteed to run, but try having one anyway ...
runtime.SetFinalizer (g, (*Guestfs).Close)
return g, nil
}
/* Create a new handle without flags. */
func Create () (*Guestfs, error) {
return Create_flags (0)
}
/* Apart from Create() and Create_flags() which return a (handle, error)
* pair, the other functions return a ([result,] GuestfsError) where
* GuestfsError is defined here.
*/
type GuestfsError struct {
Op string // operation which failed
Errmsg string // string (guestfs_last_error)
Errno syscall.Errno // errno (guestfs_last_errno)
}
func (e *GuestfsError) String() string {
if e.Errno != 0 {
return fmt.Sprintf (\"%%s: %%s\", e.Op, e.Errmsg);
} else {
return fmt.Sprintf (\"%%s: %%s: %%s\", e.Op, e.Errmsg, e.Errno);
}
}
func get_error_from_handle (g *Guestfs, op string) *GuestfsError {
c_errmsg := C.guestfs_last_error (g.g)
defer C.free (unsafe.Pointer (c_errmsg))
errmsg := C.GoString (c_errmsg)
errno := syscall.Errno (C.guestfs_last_errno (g.g))
return &GuestfsError{ Op : op, Errmsg : errmsg, Errno : errno }
}
func closed_handle_error (op string) *GuestfsError {
return &GuestfsError{ Op : op, Errmsg : \"handle is closed\",
Errno : syscall.Errno (0) }
}
/* Close the handle. */
func (g *Guestfs) Close () *GuestfsError {
if g.g == nil {
return closed_handle_error (\"close\")
}
C.guestfs_close (g.g)
g.g = nil
return nil
}
/* Functions for translating between NULL-terminated lists of
* C strings and golang []string.
*/
func arg_string_list (xs []string) **C.char {
r := make ([]*C.char, 1 + len (xs))
for i, x := range xs {
r[i] = C.CString (x)
}
r[len (xs)] = nil
return &r[0]
}
func count_string_list (argv **C.char) int {
var i int
for *argv != nil {
i++
argv = (**C.char) (unsafe.Pointer (uintptr (unsafe.Pointer (argv)) +
unsafe.Sizeof (*argv)))
}
return i
}
func free_string_list (argv **C.char) {
for *argv != nil {
//C.free (*argv)
argv = (**C.char) (unsafe.Pointer (uintptr (unsafe.Pointer (argv)) +
unsafe.Sizeof (*argv)))
}
}
func return_string_list (argv **C.char) []string {
r := make ([]string, count_string_list (argv))
var i int
for *argv != nil {
r[i] = C.GoString (*argv)
i++
argv = (**C.char) (unsafe.Pointer (uintptr (unsafe.Pointer (argv)) +
unsafe.Sizeof (*argv)))
}
return r
}
func return_hashtable (argv **C.char) map[string]string {
r := make (map[string]string)
for *argv != nil {
key := C.GoString (*argv)
argv = (**C.char) (unsafe.Pointer (uintptr (unsafe.Pointer (argv)) +
unsafe.Sizeof (*argv)))
if *argv == nil {
panic (\"odd number of items in hash table\")
}
r[key] = C.GoString (*argv)
argv = (**C.char) (unsafe.Pointer (uintptr (unsafe.Pointer (argv)) +
unsafe.Sizeof (*argv)))
}
return r
}
/* XXX Events/callbacks not yet implemented. */
";
(* Structures. *)
List.iter (
fun { s_camel_name = name; s_name = c_name; s_cols = cols } ->
pr "\n";
pr "type %s struct {\n" name;
List.iter (
function
| n, FChar -> pr " %s byte\n" n
| n, FString -> pr " %s string\n" n
| n, FBuffer -> pr " %s []byte\n" n
| n, FUInt32 -> pr " %s uint32\n" n
| n, FInt32 -> pr " %s int32\n" n
| n, FUInt64 -> pr " %s uint64\n" n
| n, FInt64 -> pr " %s int64\n" n
| n, FBytes -> pr " %s uint64\n" n
| n, FUUID -> pr " %s [32]byte\n" n
| n, FOptPercent -> pr " %s float32\n" n
) cols;
pr "}\n";
pr "\n";
pr "func return_%s (c *C.struct_guestfs_%s) *%s {\n" name c_name name;
pr " r := %s{}\n" name;
List.iter (
function
| n, FChar -> pr " r.%s = byte (c.%s)\n" n n
| n, FString -> pr " r.%s = C.GoString (c.%s)\n" n n
| n, FBuffer ->
pr " r.%s = C.GoBytes (unsafe.Pointer (c.%s), C.int (c.%s_len))\n"
n n n
| n, FUInt32 -> pr " r.%s = uint32 (c.%s)\n" n n
| n, FInt32 -> pr " r.%s = int32 (c.%s)\n" n n
| n, FUInt64 -> pr " r.%s = uint64 (c.%s)\n" n n
| n, FInt64 -> pr " r.%s = int64 (c.%s)\n" n n
| n, FBytes -> pr " r.%s = uint64 (c.%s)\n" n n
| n, FOptPercent -> pr " r.%s = float32 (c.%s)\n" n n
| n, FUUID ->
pr " // XXX doesn't work XXX r.%s = C.GoBytes (c.%s, len (c.%s))\n" n n n;
pr " r.%s = [32]byte{}\n" n
) cols;
pr " return &r\n";
pr "}\n";
pr "\n";
pr "func return_%s_list (c *C.struct_guestfs_%s_list) *[]%s {\n"
name c_name name;
pr " nrelems := int (c.len)\n";
pr " ptr := uintptr (unsafe.Pointer (c.val))\n";
pr " elemsize := unsafe.Sizeof (*c.val)\n";
pr " r := make ([]%s, nrelems)\n" name;
pr " for i := 0; i < nrelems; i++ {\n";
pr " r[i] = *return_%s ((*C.struct_guestfs_%s) (unsafe.Pointer (ptr)))\n"
name c_name;
pr " ptr += elemsize";
pr " }\n";
pr " return &r\n";
pr "}\n";
) external_structs;
(* Actions. *)
List.iter (
fun ({ name = name; shortdesc = shortdesc;
style = (ret, args, optargs) } as f) ->
let go_name = String.capitalize name in
(* If it has optional arguments, pass them in a struct
* after the required arguments.
*)
if optargs <> [] then (
pr "\n";
pr "/* Struct carrying optional arguments for %s */\n" go_name;
pr "type Optargs%s struct {\n" go_name;
List.iter (
fun optarg ->
let n = name_of_optargt optarg in
pr " /* %s field is ignored unless %s_is_set == true */\n" n n;
pr " %s_is_set bool\n" n;
match optarg with
| OBool n ->
pr " %s bool\n" n
| OInt n ->
pr " %s int\n" n
| OInt64 n ->
pr " %s int64\n" n
| OString n ->
pr " %s string\n" n
| OStringList n ->
pr " %s []string\n" n
) optargs;
pr "}\n";
);
pr "\n";
pr "/* %s : %s */\n" name shortdesc;
pr "func (g *Guestfs) %s" go_name;
(* Arguments. *)
pr " (";
let comma = ref false in
List.iter (
fun arg ->
if !comma then pr ", ";
comma := true;
match arg with
| Bool n -> pr "%s bool" n
| Int n -> pr "%s int" n
| Int64 n -> pr "%s int64" n
| String n
| Device n
| Mountable n
| Pathname n
| Dev_or_Path n
| Mountable_or_Path n
| OptString n
| Key n
| FileIn n | FileOut n -> pr "%s string" n
| StringList n
| DeviceList n -> pr "%s []string" n
| BufferIn n -> pr "%s []byte" n
| Pointer _ -> assert false
) args;
if optargs <> [] then (
if !comma then pr ", ";
comma := true;
pr "optargs *Optargs%s" go_name
);
pr ")";
(* Return type. *)
let noreturn =
match ret with
| RErr -> pr " *GuestfsError"; ""
| RInt _ -> pr " (int, *GuestfsError)"; "0, "
| RInt64 _ -> pr " (int64, *GuestfsError)"; "0, "
| RBool _ -> pr " (bool, *GuestfsError)"; "false, "
| RConstString _
| RString _ -> pr " (string, *GuestfsError)"; "\"\", "
| RConstOptString _ -> pr " (*string, *GuestfsError)"; "nil, "
| RStringList _ -> pr " ([]string, *GuestfsError)"; "nil, "
| RStruct (_, sn) ->
let sn = camel_name_of_struct sn in
pr " (*%s, *GuestfsError)" sn;
sprintf "&%s{}, " sn
| RStructList (_, sn) ->
let sn = camel_name_of_struct sn in
pr " (*[]%s, *GuestfsError)" sn;
"nil, "
| RHashtable _ -> pr " (map[string]string, *GuestfsError)"; "nil, "
| RBufferOut _ -> pr " ([]byte, *GuestfsError)"; "nil, " in
(* Body of the function. *)
pr " {\n";
pr " if g.g == nil {\n";
pr " return %sclosed_handle_error (\"%s\")\n" noreturn name;
pr " }\n";
List.iter (
function
| Bool n ->
pr "\n";
pr " var c_%s C.int\n" n;
pr " if %s { c_%s = 1 } else { c_%s = 0 }\n" n n n
| String n
| Device n
| Mountable n
| Pathname n
| Dev_or_Path n
| Mountable_or_Path n
| OptString n
| Key n
| FileIn n | FileOut n ->
pr "\n";
pr " c_%s := C.CString (%s)\n" n n;
pr " defer C.free (unsafe.Pointer (c_%s))\n" n
| StringList n
| DeviceList n ->
pr "\n";
pr " c_%s := arg_string_list (%s)\n" n n;
pr " defer free_string_list (c_%s)\n" n
| BufferIn n ->
pr "\n";
pr " /* string() cast here is apparently safe because\n";
pr " * \"Converting a slice of bytes to a string type yields\n";
pr " * a string whose successive bytes are the elements of\n";
pr " * the slice.\"\n";
pr " */\n";
pr " c_%s := C.CString (string (%s))\n" n n;
pr " defer C.free (unsafe.Pointer (c_%s))\n" n
| Int _
| Int64 _
| Pointer _ -> ()
) args;
if optargs <> [] then (
pr " c_optargs := C.struct_guestfs_%s_argv{}\n" f.c_name;
pr " if optargs != nil {\n";
List.iter (
fun optarg ->
let n = name_of_optargt optarg in
pr " if optargs.%s_is_set {\n" n;
pr " c_optargs.bitmask |= C.%s_%s_BITMASK\n"
f.c_optarg_prefix (String.uppercase n);
(match optarg with
| OBool n ->
pr " if optargs.%s { c_optargs.%s = 1 } else { c_optargs.%s = 0}\n" n n n
| OInt n ->
pr " c_optargs.%s = C.int (optargs.%s)\n" n n
| OInt64 n ->
pr " c_optargs.%s = C.int64_t (optargs.%s)\n" n n
| OString n ->
pr " c_optargs.%s = C.CString (optargs.%s)\n" n n;
pr " defer C.free (unsafe.Pointer (c_optargs.%s))\n" n
| OStringList n ->
pr " c_optargs.%s = arg_string_list (optargs.%s)\n" n n;
pr " defer free_string_list (c_optargs.%s)\n" n
);
pr " }\n"
) optargs;
pr " }\n"
);
(match ret with
| RBufferOut _ ->
pr "\n";
pr " var size C.size_t\n"
| _ -> ()
);
pr "\n";
pr " r := C.%s (g.g" f.c_function;
List.iter (
fun arg ->
pr ", ";
match arg with
| Bool n -> pr "c_%s" n
| Int n -> pr "C.int (%s)" n
| Int64 n -> pr "C.int64_t (%s)" n
| String n
| Device n
| Mountable n
| Pathname n
| Dev_or_Path n
| Mountable_or_Path n
| OptString n
| Key n
| FileIn n | FileOut n -> pr "c_%s" n
| StringList n
| DeviceList n -> pr "c_%s" n
| BufferIn n -> pr "c_%s, C.size_t (len (%s))" n n
| Pointer _ -> assert false
) args;
(match ret with
| RBufferOut _ -> pr ", &size"
| _ -> ()
);
if optargs <> [] then
pr ", &c_optargs";
pr ")\n";
(match errcode_of_ret ret with
| `CannotReturnError -> ()
| `ErrorIsMinusOne ->
pr "\n";
pr " if r == -1 {\n";
pr " return %sget_error_from_handle (g, \"%s\")\n" noreturn name;
pr " }\n"
| `ErrorIsNULL ->
pr "\n";
pr " if r == nil {\n";
pr " return %sget_error_from_handle (g, \"%s\")\n" noreturn name;
pr " }\n"
);
(match ret with
| RErr -> pr " return nil\n"
| RInt _ -> pr " return int (r), nil\n"
| RInt64 _ -> pr " return int64 (r), nil\n"
| RBool _ -> pr " return r != 0, nil\n"
| RConstString _ ->
pr " return C.GoString (r), nil\n"
| RString _ ->
pr " defer C.free (unsafe.Pointer (r))\n";
pr " return C.GoString (r), nil\n"
| RConstOptString _ ->
pr " if r != nil {\n";
pr " r_s := string (*r)\n";
pr " return &r_s, nil\n";
pr " } else {\n";
pr " return nil, nil\n";
pr " }\n"
| RStringList _ ->
pr " defer free_string_list (r)\n";
pr " return return_string_list (r), nil\n"
| RStruct (_, sn) ->
pr " defer C.guestfs_free_%s (r)\n" sn;
let sn = camel_name_of_struct sn in
pr " return return_%s (r), nil\n" sn
| RStructList (_, sn) ->
pr " defer C.guestfs_free_%s_list (r)\n" sn;
let sn = camel_name_of_struct sn in
pr " return return_%s_list (r), nil\n" sn
| RHashtable _ ->
pr " defer free_string_list (r)\n";
pr " return return_hashtable (r), nil\n"
| RBufferOut _ ->
pr " defer C.free (unsafe.Pointer (r))\n";
pr " return C.GoBytes (unsafe.Pointer (r), C.int (size)), nil\n"
);
pr "}\n";
) external_functions_sorted

View File

@@ -43,6 +43,7 @@ open Php
open Erlang
open Lua
open Gobject
open Golang
open Bindtests
open Errnostring
@@ -161,6 +162,7 @@ Run it from the top source directory using the command
output_to ~perm:0o555 "erlang/bindtests.erl" generate_erlang_bindtests;
output_to "lua/lua-guestfs.c" generate_lua_c;
output_to "lua/bindtests.lua" generate_lua_bindtests;
output_to "golang/src/libguestfs.org/guestfs/guestfs.go" generate_golang_go;
output_to "gobject/bindtests.js" generate_gobject_js_bindtests;
output_to "gobject/Makefile.inc" generate_gobject_makefile;

57
golang/Makefile.am Normal file
View File

@@ -0,0 +1,57 @@
# libguestfs golang bindings
# Copyright (C) 2013 Red Hat Inc.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
include $(top_srcdir)/subdir-rules.mk
# http://golang.org/doc/code.html#Organization
pkg = libguestfs.org/guestfs
source_files = \
src/$(pkg)/guestfs.go \
src/$(pkg)/guestfs_*_test.go
generator_built = \
$(source_files)
EXTRA_DIST = \
$(generator_built) \
config-test.go \
run-tests
if HAVE_GOLANG
golangpkgdir = $(GOROOT)/pkg/$(GOOS)_$(GOARCH)/$(pkg)
golangsrcdir = $(GOROOT)/src/pkg/$(pkg)
golangpkg_DATA = \
pkg/$(GOOS)_$(GOARCH)/$(pkg).a
pkg/$(GOOS)_$(GOARCH)/$(pkg).a: src/$(pkg)/guestfs.go
$(top_builddir)/run $(GOLANG) install $(pkg)
golangsrc_DATA = $(source_files)
TESTS_ENVIRONMENT = pkg=$(pkg) $(top_builddir)/run $(VG) # --test
TESTS = run-tests
endif
CLEANFILES = *~ src/$(pkg)/*~
clean-local:
rm -rf pkg

8
golang/README Normal file
View File

@@ -0,0 +1,8 @@
$GOPATH
-------
http://golang.org/doc/code.html
Note that $GOPATH is set (by the ./run script) to the
libguestfs/golang directory so that "installs" happen in the local
build tree.

5
golang/config-test.go Normal file
View File

@@ -0,0 +1,5 @@
package main
func main() {
/* XXX Check for minimum runtime.Version() >= 1.1.1 */
}

21
golang/run-tests Executable file
View File

@@ -0,0 +1,21 @@
#!/bin/sh -
# libguestfs Golang tests
# Copyright (C) 2013 Red Hat Inc.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
set -e
$GOLANG test $pkg

View File

@@ -0,0 +1 @@
/guestfs.go

View File

@@ -0,0 +1,25 @@
/* libguestfs Go tests
* Copyright (C) 2013 Red Hat Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
package guestfs
import "testing"
func Test010Load (t *testing.T) {
/* Nothing - just test that the library can be linked to. */
}

View File

@@ -0,0 +1,28 @@
/* libguestfs Go tests
* Copyright (C) 2013 Red Hat Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
package guestfs
import "testing"
func Test020Create (t *testing.T) {
_, err := Create ()
if err != nil {
t.Errorf ("could not create handle: %s", err)
}
}

View File

@@ -0,0 +1,35 @@
/* libguestfs Go tests
* Copyright (C) 2013 Red Hat Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
package guestfs
import "testing"
func Test030CreateFlags (t *testing.T) {
g, err := Create_flags (0)
if err != nil {
t.Errorf ("could not create handle: %s", err)
}
g, err = Create_flags (CREATE_NO_ENVIRONMENT)
if err != nil {
t.Errorf ("could not create handle: %s", err)
}
if err := g.Parse_environment (); err != nil {
t.Errorf ("could not parse environment: %s", err)
}
}

View File

@@ -0,0 +1,33 @@
/* libguestfs Go tests
* Copyright (C) 2013 Red Hat Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
package guestfs
import "testing"
func Test040CreateMultiple (t *testing.T) {
if _, err := Create (); err != nil {
t.Errorf ("could not create handle: %s", err)
}
if _, err := Create (); err != nil {
t.Errorf ("could not create handle: %s", err)
}
if _, err := Create (); err != nil {
t.Errorf ("could not create handle: %s", err)
}
}

View File

@@ -0,0 +1,64 @@
/* libguestfs Go tests
* Copyright (C) 2013 Red Hat Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
package guestfs
import "testing"
func Test050HandleProperties (t *testing.T) {
g, errno := Create ()
if errno != nil {
t.Errorf ("could not create handle: %s", errno)
}
v, err := g.Get_verbose ()
if err != nil {
t.Errorf ("%s", err)
}
err = g.Set_verbose (v)
if err != nil {
t.Errorf ("%s", err)
}
tr, err := g.Get_trace ()
if err != nil {
t.Errorf ("%s", err)
}
err = g.Set_trace (tr)
if err != nil {
t.Errorf ("%s", err)
}
m, err := g.Get_memsize ()
if err != nil {
t.Errorf ("%s", err)
}
err = g.Set_memsize (m)
if err != nil {
t.Errorf ("%s", err)
}
p, err := g.Get_path ()
if err != nil {
t.Errorf ("%s", err)
}
err = g.Set_path (p)
if err != nil {
t.Errorf ("%s", err)
}
}

View File

@@ -0,0 +1,32 @@
/* libguestfs Go tests
* Copyright (C) 2013 Red Hat Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
package guestfs
import "testing"
func Test060ExplicitClose (t *testing.T) {
g, errno := Create ()
if errno != nil {
t.Errorf ("could not create handle: %s", errno)
}
err := g.Close ()
if err != nil {
t.Errorf ("explicit close failed: %s", err)
}
}

View File

@@ -0,0 +1,59 @@
/* libguestfs Go tests
* Copyright (C) 2013 Red Hat Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
package guestfs
import "testing"
func Test070Optargs (t *testing.T) {
g, errno := Create ()
if errno != nil {
t.Errorf ("could not create handle: %s", errno)
}
err := g.Add_drive ("/dev/null", nil)
if err != nil {
t.Errorf ("%s", err)
}
err = g.Add_drive ("/dev/null", &OptargsAdd_drive{
readonly_is_set: true,
readonly: true,
})
if err != nil {
t.Errorf ("%s", err)
}
err = g.Add_drive ("/dev/null", &OptargsAdd_drive{
readonly_is_set: true,
readonly: true,
format_is_set: true,
format: "raw",
})
if err != nil {
t.Errorf ("%s", err)
}
err = g.Add_drive ("/dev/null", &OptargsAdd_drive{
readonly_is_set: true,
readonly: true,
format_is_set: true,
format: "raw",
iface_is_set: true,
iface: "virtio",
})
if err != nil {
t.Errorf ("%s", err)
}
}

View File

@@ -0,0 +1,128 @@
/* libguestfs Go tests
* Copyright (C) 2013 Red Hat Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
package guestfs
import (
"testing"
"os"
// "sort"
)
func Test100Launch (t *testing.T) {
g, errno := Create ()
if errno != nil {
t.Errorf ("could not create handle: %s", errno)
}
f, ferr := os.Create ("test.img")
if ferr != nil {
t.Errorf ("could not create file: %s", ferr)
}
if ferr := f.Truncate (500 * 1024 * 1024); ferr != nil {
t.Errorf ("could not truncate file: %s", ferr)
}
f.Close ()
err := g.Add_drive ("test.img", nil)
if err != nil {
t.Errorf ("%s", err)
}
err = g.Launch ()
if err != nil {
t.Errorf ("%s", err)
}
err = g.Pvcreate ("/dev/sda")
if err != nil {
t.Errorf ("%s", err)
}
err = g.Vgcreate ("VG", []string{"/dev/sda"})
if err != nil {
t.Errorf ("%s", err)
}
err = g.Lvcreate ("LV1", "VG", 200)
if err != nil {
t.Errorf ("%s", err)
}
err = g.Lvcreate ("LV2", "VG", 200)
if err != nil {
t.Errorf ("%s", err)
}
lvs, err := g.Lvs ()
if err != nil {
t.Errorf ("%s", err)
}
expected := []string{"/dev/VG/LV1", "/dev/VG/LV2"}
if !equal (lvs, expected) {
t.Errorf ("g.Lvs: %s != %s", lvs, expected)
}
err = g.Mkfs ("ext2", "/dev/VG/LV1", nil)
if err != nil {
t.Errorf ("%s", err)
}
err = g.Mount ("/dev/VG/LV1", "/")
if err != nil {
t.Errorf ("%s", err)
}
err = g.Mkdir ("/p")
if err != nil {
t.Errorf ("%s", err)
}
err = g.Touch ("/q")
if err != nil {
t.Errorf ("%s", err)
}
_ /*dirs*/, err = g.Readdir ("/")
if err != nil {
t.Errorf ("%s", err)
}
//sort.Sort (byName (dirs))
// XXX Sort interface is needlessly complicated
err = g.Shutdown ()
if err != nil {
t.Errorf ("%s", err)
}
err = g.Close ()
if err != nil {
t.Errorf ("%s", err)
}
os.Remove ("test.img")
}
/* - declared in guestfs_900_rstringlist_test.go
func equal (xs []string, ys []string) bool {
if len(xs) != len(ys) {
return false
}
for i, x := range xs {
if x != ys[i] {
return false
}
}
return true
}
*/

View File

@@ -0,0 +1,54 @@
/* libguestfs Go tests
* Copyright (C) 2013 Red Hat Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
package guestfs
import (
"testing"
)
func Test900RStringLits (t *testing.T) {
g, errno := Create ()
if errno != nil {
t.Errorf ("could not create handle: %s", errno)
}
actual, err := g.Internal_test_rstringlist ("16")
if err != nil {
t.Errorf ("unexpected error: %s", err)
}
expected := []string{
"0", "1", "2", "3", "4", "5", "6", "7",
"8", "9", "10", "11", "12", "13", "14", "15",
}
if !equal (actual, expected) {
t.Errorf ("%s != %s", actual, expected)
}
}
func equal (xs []string, ys []string) bool {
if len(xs) != len(ys) {
return false
}
for i, x := range xs {
if x != ys[i] {
return false
}
}
return true
}

9
run.in
View File

@@ -163,6 +163,15 @@ else
fi
export LUA_CPATH
# For golang.
export GOLANG=@GOLANG@
if [ -z "$GOPATH" ]; then
GOPATH="$b/golang"
else
GOPATH="$b/golang:$GOPATH"
fi
export GOPATH
# For GObject, Javascript and friends.
export GJS=@GJS@
if [ -z "$GI_TYPELIB_PATH" ]; then

View File

@@ -1090,6 +1090,23 @@ See L<guestfs-erlang(3)>.
Experimental GObject bindings (with GObject Introspection support) are
available. See the C<gobject> directory in the source.
=item B<Go>
Experimental Go bindings are available. See the C<golang> directory
in the source. These are incomplete:
=over 4
=item *
No support for L</EVENTS>.
=item *
UUIDs cannot be returned in structures.
=back
=item B<Haskell>
This language binding is working but incomplete:
@@ -4180,6 +4197,8 @@ Command line tools written in Perl (L<virt-win-reg(1)> and many others).
=item C<gobject>
=item C<golang>
=item C<haskell>
=item C<java>