[Libguestfs] [libnbd PATCH v4 11/25] api: Add tests for [aio_]nbd_block_status_64
Richard W.M. Jones
rjones at redhat.com
Fri Aug 4 09:50:16 UTC 2023
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 at 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 at 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
More information about the Libguestfs
mailing list