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 <ebl...@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 <rjo...@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 _______________________________________________ Libguestfs mailing list Libguestfs@redhat.com https://listman.redhat.com/mailman/listinfo/libguestfs