On Wed, Aug 02, 2023 at 08:50:31PM -0500, Eric Blake wrote:
Add unit test coverage to prove that the new API works in each of C,
Python, OCaml, and Go bindings.
Signed-off-by: Eric Blake <eblake(a)redhat.com>
---
v4: new patch, split out from API addition itself
---
python/t/465-block-status-64.py | 56 ++++++++++
ocaml/tests/Makefile.am | 1 +
ocaml/tests/test_465_block_status_64.ml | 58 +++++++++++
tests/meta-base-allocation.c | 104 ++++++++++++++++---
golang/Makefile.am | 1 +
golang/libnbd_465_block_status_64_test.go | 119 ++++++++++++++++++++++
6 files changed, 326 insertions(+), 13 deletions(-)
create mode 100644 python/t/465-block-status-64.py
create mode 100644 ocaml/tests/test_465_block_status_64.ml
create mode 100644 golang/libnbd_465_block_status_64_test.go
diff --git a/python/t/465-block-status-64.py b/python/t/465-block-status-64.py
new file mode 100644
index 00000000..a8a8eaea
--- /dev/null
+++ b/python/t/465-block-status-64.py
@@ -0,0 +1,56 @@
+# libnbd Python bindings
+# Copyright Red Hat
+#
+# 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
+
+import os
+
+import nbd
+
+script = "%s/../tests/meta-base-allocation.sh" % os.getenv("srcdir",
".")
+
+h = nbd.NBD()
+h.add_meta_context("base:allocation")
+h.connect_command(["nbdkit", "-s", "--exit-with-parent",
"-v", "sh", script])
+
+entries = []
+
+
+def f(user_data, metacontext, offset, e, err):
+ global entries
+ assert user_data == 42
+ assert err.value == 0
+ if metacontext != "base:allocation":
+ return
+ entries = e
+
+
+h.block_status_64(65536, 0, lambda *args: f(42, *args))
+print("entries = %r" % entries)
+assert entries == [(8192, 0),
+ (8192, 1),
+ (16384, 3),
+ (16384, 2),
+ (16384, 0)]
+
+h.block_status_64(1024, 32256, lambda *args: f(42, *args))
+print("entries = %r" % entries)
+assert entries == [(512, 3),
+ (16384, 2)]
+
+h.block_status_64(1024, 32256, lambda *args: f(42, *args),
+ nbd.CMD_FLAG_REQ_ONE)
+print("entries = %r" % entries)
+assert entries == [(512, 3)]
diff --git a/ocaml/tests/Makefile.am b/ocaml/tests/Makefile.am
index 20546350..4ddd0f9f 100644
--- a/ocaml/tests/Makefile.am
+++ b/ocaml/tests/Makefile.am
@@ -40,6 +40,7 @@ ML_TESTS = \
test_405_pread_structured.ml \
test_410_pwrite.ml \
test_460_block_status.ml \
+ test_465_block_status_64.ml \
test_500_aio_pread.ml \
test_505_aio_pread_structured_callback.ml \
test_510_aio_pwrite.ml \
diff --git a/ocaml/tests/test_465_block_status_64.ml
b/ocaml/tests/test_465_block_status_64.ml
new file mode 100644
index 00000000..0634a025
--- /dev/null
+++ b/ocaml/tests/test_465_block_status_64.ml
@@ -0,0 +1,58 @@
+(* hey emacs, this is OCaml code: -*- tuareg -*- *)
+(* libnbd OCaml test case
+ * Copyright Red Hat
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *)
+
+open Printf
+
+let script =
+ try
+ let srcdir = Sys.getenv "srcdir" in
+ sprintf "%s/../../tests/meta-base-allocation.sh" srcdir
+ with
+ Not_found -> failwith "error: srcdir is not defined"
+
+let entries = ref [||]
+let f user_data metacontext offset e err =
+ assert (user_data = 42);
+ assert (!err = 0);
+ if metacontext = "base:allocation" then
+ entries := e;
+ 0
+
+let () =
+ let nbd = NBD.create () in
+ NBD.add_meta_context nbd "base:allocation";
+ NBD.connect_command nbd ["nbdkit"; "-s";
"--exit-with-parent"; "-v";
+ "sh"; script];
+
+ NBD.block_status_64 nbd 65536_L 0_L (f 42);
+ assert (!entries = [| 8192_L, 0_L;
+ 8192_L, 1_L;
+ 16384_L, 3_L;
+ 16384_L, 2_L;
+ 16384_L, 0_L |]);
+
+ NBD.block_status_64 nbd 1024_L 32256_L (f 42);
+ assert (!entries = [| 512_L, 3_L;
+ 16384_L, 2_L |]);
+
+ let flags = let open NBD.CMD_FLAG in [REQ_ONE] in
+ NBD.block_status_64 nbd 1024_L 32256_L (f 42) ~flags;
+ assert (!entries = [| 512_L, 3_L |])
+
+let () = Gc.compact ()
diff --git a/tests/meta-base-allocation.c b/tests/meta-base-allocation.c
index a7b3af09..7697b5da 100644
--- a/tests/meta-base-allocation.c
+++ b/tests/meta-base-allocation.c
@@ -32,10 +32,13 @@
#define BOGUS_CONTEXT "x-libnbd:nosuch"
-static int check_extent (void *data,
- const char *metacontext,
- uint64_t offset,
- uint32_t *entries, size_t nr_entries, int *error);
+static int check_extent32 (void *data, const char *metacontext,
+ uint64_t offset,
+ uint32_t *entries, size_t nr_entries, int *error);
+
+static int check_extent64 (void *data, const char *metacontext,
+ uint64_t offset,
+ nbd_extent *entries, size_t nr_entries, int *error);
int
main (int argc, char *argv[])
@@ -43,8 +46,10 @@ main (int argc, char *argv[])
struct nbd_handle *nbd;
char plugin_path[256];
int id;
- nbd_extent_callback extent_callback = { .callback = check_extent,
- .user_data = &id };
+ nbd_extent_callback extent32_callback = { .callback = check_extent32,
+ .user_data = &id };
+ nbd_extent64_callback extent64_callback = { .callback = check_extent64,
+ .user_data = &id };
int r;
const char *s;
char *tmp;
@@ -150,23 +155,36 @@ main (int argc, char *argv[])
/* Read the block status. */
id = 1;
- if (nbd_block_status (nbd, 65536, 0, extent_callback, 0) == -1) {
+ if (nbd_block_status (nbd, 65536, 0, extent32_callback, 0) == -1) {
+ fprintf (stderr, "%s\n", nbd_get_error ());
+ exit (EXIT_FAILURE);
+ }
+ if (nbd_block_status_64 (nbd, 65536, 0, extent64_callback, 0) == -1) {
fprintf (stderr, "%s\n", nbd_get_error ());
exit (EXIT_FAILURE);
}
id = 2;
- if (nbd_block_status (nbd, 1024, 32768-512, extent_callback, 0) == -1) {
+ if (nbd_block_status (nbd, 1024, 32768-512, extent32_callback, 0) == -1) {
+ fprintf (stderr, "%s\n", nbd_get_error ());
+ exit (EXIT_FAILURE);
+ }
+ if (nbd_block_status_64 (nbd, 1024, 32768-512, extent64_callback, 0) == -1) {
fprintf (stderr, "%s\n", nbd_get_error ());
exit (EXIT_FAILURE);
}
id = 3;
- if (nbd_block_status (nbd, 1024, 32768-512, extent_callback,
+ if (nbd_block_status (nbd, 1024, 32768-512, extent32_callback,
LIBNBD_CMD_FLAG_REQ_ONE) == -1) {
fprintf (stderr, "%s\n", nbd_get_error ());
exit (EXIT_FAILURE);
}
+ if (nbd_block_status_64 (nbd, 1024, 32768-512, extent64_callback,
+ LIBNBD_CMD_FLAG_REQ_ONE) == -1) {
+ fprintf (stderr, "%s\n", nbd_get_error ());
+ exit (EXIT_FAILURE);
+ }
if (nbd_shutdown (nbd, 0) == -1) {
fprintf (stderr, "%s\n", nbd_get_error ());
@@ -178,10 +196,8 @@ main (int argc, char *argv[])
}
static int
-check_extent (void *data,
- const char *metacontext,
- uint64_t offset,
- uint32_t *entries, size_t nr_entries, int *error)
+check_extent32 (void *data, const char *metacontext, uint64_t offset,
+ uint32_t *entries, size_t nr_entries, int *error)
{
size_t i;
int id;
@@ -235,3 +251,65 @@ check_extent (void *data,
return 0;
}
+
+static int
+check_extent64 (void *data, const char *metacontext, uint64_t offset,
+ nbd_extent *entries, size_t nr_entries, int *error)
+{
+ size_t i;
+ int id;
+
+ id = * (int *)data;
+
+ printf ("extent: id=%d, metacontext=%s, offset=%" PRIu64 ", "
+ "nr_entries=%zu, error=%d\n",
+ id, metacontext, offset, nr_entries, *error);
+
+ assert (*error == 0);
+ if (strcmp (metacontext, LIBNBD_CONTEXT_BASE_ALLOCATION) == 0) {
+ for (i = 0; i < nr_entries; i++) {
+ printf ("\t%zu\tlength=%" PRIu64 ", status=%" PRIu64
"\n",
+ i, entries[i].length, entries[i].flags);
+ }
+ fflush (stdout);
+
+ switch (id) {
+ case 1:
+ assert (nr_entries == 5);
+ assert (entries[0].length == 8192);
+ assert (entries[0].flags == 0);
+ assert (entries[1].length == 8192);
+ assert (entries[1].flags == LIBNBD_STATE_HOLE);
+ assert (entries[2].length == 16384);
+ assert (entries[2].flags == (LIBNBD_STATE_HOLE|LIBNBD_STATE_ZERO));
+ assert (entries[3].length == 16384);
+ assert (entries[3].flags == LIBNBD_STATE_ZERO);
+ assert (entries[4].length == 16384);
+ assert (entries[4].flags == 0);
+ break;
+
+ case 2:
+ assert (nr_entries == 2);
+ assert (entries[0].length == 512);
+ assert (entries[0].flags == (LIBNBD_STATE_HOLE|LIBNBD_STATE_ZERO));
+ assert (entries[1].length == 16384);
+ assert (entries[1].flags == LIBNBD_STATE_ZERO);
+ break;
+
+ case 3:
+ assert (nr_entries == 1);
+ assert (entries[0].length == 512);
+ assert (entries[0].flags == (LIBNBD_STATE_HOLE|LIBNBD_STATE_ZERO));
+ break;
+
+ default:
+ abort ();
+ }
+
+ }
+ else
+ fprintf (stderr, "warning: ignored unexpected meta context %s\n",
+ metacontext);
+
+ return 0;
+}
diff --git a/golang/Makefile.am b/golang/Makefile.am
index fac65248..b4151250 100644
--- a/golang/Makefile.am
+++ b/golang/Makefile.am
@@ -43,6 +43,7 @@ source_files = \
libnbd_405_pread_structured_test.go \
libnbd_410_pwrite_test.go \
libnbd_460_block_status_test.go \
+ libnbd_465_block_status_64_test.go \
libnbd_500_aio_pread_test.go \
libnbd_510_aio_pwrite_test.go \
libnbd_590_aio_copy_test.go \
diff --git a/golang/libnbd_465_block_status_64_test.go
b/golang/libnbd_465_block_status_64_test.go
new file mode 100644
index 00000000..7659a21d
--- /dev/null
+++ b/golang/libnbd_465_block_status_64_test.go
@@ -0,0 +1,119 @@
+/* libnbd golang tests
+ * Copyright Red Hat
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+package libnbd
+
+import (
+ "fmt"
+ "os"
+ "strings"
+ "testing"
+)
+
+var entries64 []LibnbdExtent
+
+func mcf64(metacontext string, offset uint64, e []LibnbdExtent, error *int) int {
+ if *error != 0 {
+ panic("expected *error == 0")
+ }
+ if metacontext == "base:allocation" {
+ entries64 = e
+ }
+ return 0
+}
+
+// Seriously WTF?
+func mc64_compare(a1 []LibnbdExtent, a2 []LibnbdExtent) bool {
+ if len(a1) != len(a2) {
+ return false
+ }
+ for i := 0; i < len(a1); i++ {
+ if a1[i] != a2[i] {
+ return false
+ }
+ }
+ return true
+}
+
+func mc64_to_string(a []LibnbdExtent) string {
+ ss := make([]string, len(a))
+ for i := 0; i < len(a); i++ {
+ ss[i] = fmt.Sprintf("%#v", a[i])
+ }
+ return strings.Join(ss, ", ")
+}
+
+func Test465BlockStatus64(t *testing.T) {
+ srcdir := os.Getenv("abs_top_srcdir")
+ script := srcdir + "/tests/meta-base-allocation.sh"
+
+ h, err := Create()
+ if err != nil {
+ t.Fatalf("could not create handle: %s", err)
+ }
+ defer h.Close()
+
+ err = h.AddMetaContext("base:allocation")
+ if err != nil {
+ t.Fatalf("%s", err)
+ }
+ err = h.ConnectCommand([]string{
+ "nbdkit", "-s", "--exit-with-parent", "-v",
+ "sh", script,
+ })
+ if err != nil {
+ t.Fatalf("%s", err)
+ }
+
+ err = h.BlockStatus64(65536, 0, mcf64, nil)
+ if err != nil {
+ t.Fatalf("%s", err)
+ }
+ if !mc64_compare(entries64, []LibnbdExtent{
+ {8192, 0},
+ {8192, 1},
+ {16384, 3},
+ {16384, 2},
+ {16384, 0},
+ }) {
+ t.Fatalf("unexpected entries (1): %s", mc64_to_string(entries64))
+ }
+
+ err = h.BlockStatus64(1024, 32256, mcf64, nil)
+ if err != nil {
+ t.Fatalf("%s", err)
+ }
+ if !mc64_compare(entries64, []LibnbdExtent{
+ {512, 3},
+ {16384, 2},
+ }) {
+ t.Fatalf("unexpected entries (2): %s", mc64_to_string(entries64))
+ }
+
+ var optargs BlockStatus64Optargs
+ optargs.FlagsSet = true
+ optargs.Flags = CMD_FLAG_REQ_ONE
+ err = h.BlockStatus64(1024, 32256, mcf64, &optargs)
+ if err != nil {
+ t.Fatalf("%s", err)
+ }
+ if !mc64_compare(entries64, []LibnbdExtent{{512, 3}}) {
+ t.Fatalf("unexpected entries (3): %s", mc64_to_string(entries64))
+ }
+
+}
Reviewed-by: Richard W.M. Jones <rjones(a)redhat.com>
--
Richard Jones, Virtualization Group, Red Hat
http://people.redhat.com/~rjones
Read my programming and virtualization blog:
http://rwmj.wordpress.com
libguestfs lets you edit virtual machines. Supports shell scripting,
bindings from many languages.
http://libguestfs.org