[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