On 08/31/22 16:39, Eric Blake wrote:
> As promised in the previous patch, also test the new
> nbd_opt_set_meta_context() API in Python, OCaml, and Golang.
>
> The fact that Go slams all unit tests into the same namespace is
> somewhat annoying; it required munging test 240 now that 250 wants to
> use similar global variables.
> ---
> python/t/250-opt-set-meta.py | 126 ++++++++++++
> ocaml/tests/Makefile.am | 5 +-
> ocaml/tests/test_250_opt_set_meta.ml | 150 ++++++++++++++
> tests/opt-set-meta.c | 1 +
> golang/Makefile.am | 3 +-
> golang/libnbd_240_opt_list_meta_test.go | 54 +++---
> golang/libnbd_250_opt_set_meta_test.go | 248 ++++++++++++++++++++++++
> 7 files changed, 558 insertions(+), 29 deletions(-)
> create mode 100644 python/t/250-opt-set-meta.py
> create mode 100644 ocaml/tests/test_250_opt_set_meta.ml
> create mode 100644 golang/libnbd_250_opt_set_meta_test.go
>
> diff --git a/python/t/250-opt-set-meta.py b/python/t/250-opt-set-meta.py
> new file mode 100644
> index 0000000..eb27998
> --- /dev/null
> +++ b/python/t/250-opt-set-meta.py
> @@ -0,0 +1,126 @@
> +# libnbd Python bindings
> +# Copyright (C) 2010-2022 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
> +
> +import nbd
> +
> +
> +count = 0
> +seen = False
> +
> +
> +def f(user_data, name):
> + global count
> + global seen
> + assert user_data == 42
> + count = count + 1
> + if name == nbd.CONTEXT_BASE_ALLOCATION:
> + seen = True
> +
> +
> +def must_fail(f, *args, **kwds):
> + try:
> + f(*args, **kwds)
> + assert False
> + except nbd.Error:
> + pass
> +
> +
> +# First process, with structured replies. Get into negotiating state.
> +h = nbd.NBD()
> +h.set_opt_mode(True)
> +h.connect_command(["nbdkit", "-s", "--exit-with-parent", "-v",
> + "memory", "size=1M"])
> +
> +# No contexts negotiated yet; can_meta should be error if any requested */
I think the "*/" at the end of the line may be a remnant from the C code.
> +assert h.get_structured_replies_negotiated() is True
> +assert h.can_meta_context(nbd.CONTEXT_BASE_ALLOCATION) is False
> +h.add_meta_context(nbd.CONTEXT_BASE_ALLOCATION)
> +must_fail(h.can_meta_context, nbd.CONTEXT_BASE_ALLOCATION)
(I had to re-read the docs on can_meta_context.) Non-intuitive, but
valid, as far as I can tell.
> +
> +# FIXME: Once nbd_opt_structured_reply exists, check that set before
> +# SR fails server-side, then enable SR for rest of process.
> +
> +# nbdkit does not match wildcard for SET, even though it does for LIST
> +count = 0
> +seen = False
> +h.clear_meta_contexts()
> +h.add_meta_context("base:")
> +r = h.opt_set_meta_context(lambda *args: f(42, *args))
> +assert r == count
> +assert r == 0
> +assert not seen
> +assert h.can_meta_context(nbd.CONTEXT_BASE_ALLOCATION) is False
> +
> +# Negotiating with no contexts is not an error, but selects nothing
> +count = 0
> +seen = False
> +h.clear_meta_contexts()
> +r = h.opt_set_meta_context(lambda *args: f(42, *args))
> +assert r == 0
> +assert r == count
> +assert not seen
> +assert h.can_meta_context(nbd.CONTEXT_BASE_ALLOCATION) is False
> +
> +# Request 2 with expectation of 1; with set_request_meta_context off
> +count = 0
> +seen = False
> +h.add_meta_context("x-nosuch:context")
> +h.add_meta_context(nbd.CONTEXT_BASE_ALLOCATION)
> +h.set_request_meta_context(False)
> +r = h.opt_set_meta_context(lambda *args: f(42, *args))
> +assert r == 1
> +assert count == 1
> +assert seen
> +assert h.can_meta_context(nbd.CONTEXT_BASE_ALLOCATION) is True
> +
> +# Transition to transmission phase; our last set should remain active
> +h.clear_meta_contexts()
> +h.add_meta_context("x-nosuch:context")
> +h.opt_go()
> +assert h.can_meta_context(nbd.CONTEXT_BASE_ALLOCATION) is True
> +
> +# Now too late to set; but should not lose earlier state
> +count = 0
> +seen = False
> +must_fail(h.opt_set_meta_context, lambda *args: f(42, *args))
> +assert count == 0
> +assert not seen
> +assert h.can_meta_context(nbd.CONTEXT_BASE_ALLOCATION) is True
> +
> +h.shutdown()
> +
> +# Second process, this time without structured replies server-side.
> +h = nbd.NBD()
> +h.set_opt_mode(True)
> +h.add_meta_context(nbd.CONTEXT_BASE_ALLOCATION)
> +h.connect_command(["nbdkit", "-s", "--exit-with-parent", "-v",
> + "memory", "size=1M", "--no-sr"])
> +assert h.get_structured_replies_negotiated() is False
> +
> +# Expect server-side failure here
> +count = 0
> +seen = False
> +must_fail(h.opt_set_meta_context, lambda *args: f(42, *args))
> +assert count == 0
> +assert not seen
> +must_fail(h.can_meta_context, nbd.CONTEXT_BASE_ALLOCATION)
> +
> +# Even though can_meta fails after failed SET, it returns 0 after go
> +h.opt_go()
> +assert h.can_meta_context(nbd.CONTEXT_BASE_ALLOCATION) is False
> +
> +h.shutdown()
Acked-by: Laszlo Ersek <[email protected]>
Laszlo
> diff --git a/ocaml/tests/Makefile.am b/ocaml/tests/Makefile.am
> index 24f626d..f8ce810 100644
> --- a/ocaml/tests/Makefile.am
> +++ b/ocaml/tests/Makefile.am
> @@ -1,5 +1,5 @@
> # nbd client library in userspace
> -# Copyright (C) 2013-2020 Red Hat Inc.
> +# Copyright (C) 2013-2022 Red Hat Inc.
> #
> # This library is free software; you can redistribute it and/or
> # modify it under the terms of the GNU Lesser General Public
> @@ -31,6 +31,7 @@ EXTRA_DIST = \
> test_220_opt_list.ml \
> test_230_opt_info.ml \
> test_240_opt_list_meta.ml \
> + test_250_opt_set_meta.ml \
> test_300_get_size.ml \
> test_400_pread.ml \
> test_405_pread_structured.ml \
> @@ -59,6 +60,7 @@ tests_bc = \
> test_220_opt_list.bc \
> test_230_opt_info.bc \
> test_240_opt_list_meta.bc \
> + test_250_opt_set_meta.bc \
> test_300_get_size.bc \
> test_400_pread.bc \
> test_405_pread_structured.bc \
> @@ -84,6 +86,7 @@ tests_opt = \
> test_220_opt_list.opt \
> test_230_opt_info.opt \
> test_240_opt_list_meta.opt \
> + test_250_opt_set_meta.opt \
> test_300_get_size.opt \
> test_400_pread.opt \
> test_405_pread_structured.opt \
> diff --git a/ocaml/tests/test_250_opt_set_meta.ml
> b/ocaml/tests/test_250_opt_set_meta.ml
> new file mode 100644
> index 0000000..d74e9e0
> --- /dev/null
> +++ b/ocaml/tests/test_250_opt_set_meta.ml
> @@ -0,0 +1,150 @@
> +(* hey emacs, this is OCaml code: -*- tuareg -*- *)
> +(* libnbd OCaml test case
> + * Copyright (C) 2013-2022 Red Hat Inc.
> + *
> + * 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
> + *)
> +
> +let count = ref 0
> +let seen = ref false
> +let f user_data name =
> + assert (user_data = 42);
> + count := !count + 1;
> + if name = NBD.context_base_allocation then
> + seen := true;
> + 0
> +
> +let () =
> + let nbd = NBD.create () in
> + NBD.set_opt_mode nbd true;
> + NBD.connect_command nbd
> + ["nbdkit"; "-s"; "--exit-with-parent"; "-v";
> + "memory"; "size=1M"];
> +
> + (* No contexts negotiated yet; can_meta should be error if any requested *)
> + let sr = NBD.get_structured_replies_negotiated nbd in
> + assert sr;
> + let m = NBD.can_meta_context nbd NBD.context_base_allocation in
> + assert (not m);
> + NBD.add_meta_context nbd NBD.context_base_allocation;
> + (try
> + let _ = NBD.can_meta_context nbd NBD.context_base_allocation in
> + assert false
> + with
> + NBD.Error (errstr, errno) -> ()
> + );
> +
> + (* FIXME: Once nbd_opt_structured_reply exists, check that set before
> + * SR fails server-side, then enable SR for rest of process.
> + *)
> +
> + (* nbdkit does not match wildcard for SET, even though it does for LIST *)
> + count := 0;
> + seen := false;
> + NBD.clear_meta_contexts nbd;
> + NBD.add_meta_context nbd "base:";
> + let r = NBD.opt_set_meta_context nbd (f 42) in
> + assert (r = !count);
> + assert (r = 0);
> + assert (not !seen);
> + let m = NBD.can_meta_context nbd NBD.context_base_allocation in
> + assert (not m);
> +
> + (* Negotiating with no contexts is not an error, but selects nothing *)
> + count := 0;
> + seen := false;
> + NBD.clear_meta_contexts nbd;
> + let r = NBD.opt_set_meta_context nbd (f 42) in
> + assert (r = 0);
> + assert (r = !count);
> + assert (not !seen);
> + let m = NBD.can_meta_context nbd NBD.context_base_allocation in
> + assert (not m);
> +
> + (* Request 2 with expectation of 1; with set_request_meta_context off *)
> + count := 0;
> + seen := false;
> + NBD.add_meta_context nbd "x-nosuch:context";
> + NBD.add_meta_context nbd NBD.context_base_allocation;
> + NBD.set_request_meta_context nbd false;
> + let r = NBD.opt_set_meta_context nbd (f 42) in
> + assert (r = 1);
> + assert (r = !count);
> + assert !seen;
> + let m = NBD.can_meta_context nbd NBD.context_base_allocation in
> + assert m;
> +
> + (* Transition to transmission phase; our last set should remain active *)
> + NBD.clear_meta_contexts nbd;
> + NBD.add_meta_context nbd "x-nosuch:context";
> + NBD.opt_go nbd;
> + let m = NBD.can_meta_context nbd NBD.context_base_allocation in
> + assert m;
> +
> + (* Now too late to set; but should not lose earlier state *)
> + count := 0;
> + seen := false;
> + (try
> + let _ = NBD.opt_set_meta_context nbd (f 42) in
> + assert false
> + with
> + NBD.Error (errstr, errno) -> ()
> + );
> + assert (0 = !count);
> + assert (not !seen);
> + let s = NBD.get_size nbd in
> + assert (s = 1048576_L);
> + let m = NBD.can_meta_context nbd NBD.context_base_allocation in
> + assert m;
> +
> + NBD.shutdown nbd;
> +
> + (* Second process, this time without structured replies server-side. *)
> + let nbd = NBD.create () in
> + NBD.set_opt_mode nbd true;
> + NBD.add_meta_context nbd NBD.context_base_allocation;
> + NBD.connect_command nbd
> + ["nbdkit"; "-s"; "--exit-with-parent"; "-v";
> + "memory"; "size=1M"; "--no-sr"];
> + let sr = NBD.get_structured_replies_negotiated nbd in
> + assert (not sr);
> +
> + (* Expect server-side failure here *)
> + count := 0;
> + seen := false;
> + NBD.add_meta_context nbd "base:";
> + (try
> + let _ = NBD.opt_set_meta_context nbd (f 42) in
> + assert false
> + with
> + NBD.Error (errstr, errno) -> ()
> + );
> + assert (0 = !count);
> + assert (not !seen);
> + (try
> + let _ = NBD.can_meta_context nbd NBD.context_base_allocation in
> + assert false
> + with
> + NBD.Error (errstr, errno) -> ()
> + );
> +
> + (* Even though can_meta fails after failed SET, it returns 0 after go *)
> + NBD.opt_go nbd;
> + let m = NBD.can_meta_context nbd NBD.context_base_allocation in
> + assert (not m);
> +
> + NBD.shutdown nbd
> +
> +let () = Gc.compact ()
> diff --git a/tests/opt-set-meta.c b/tests/opt-set-meta.c
> index 01c9604..bd00276 100644
> --- a/tests/opt-set-meta.c
> +++ b/tests/opt-set-meta.c
> @@ -17,6 +17,7 @@
> */
>
> /* Test behavior of nbd_opt_set_meta_context. */
> +/* See also unit test 250 in the various language ports. */
>
> #include <config.h>
>
> diff --git a/golang/Makefile.am b/golang/Makefile.am
> index f170cbc..f6e6f91 100644
> --- a/golang/Makefile.am
> +++ b/golang/Makefile.am
> @@ -1,5 +1,5 @@
> # nbd client library in userspace
> -# Copyright (C) 2013-2020 Red Hat Inc.
> +# Copyright (C) 2013-2022 Red Hat Inc.
> #
> # This library is free software; you can redistribute it and/or
> # modify it under the terms of the GNU Lesser General Public
> @@ -35,6 +35,7 @@ source_files = \
> libnbd_220_opt_list_test.go \
> libnbd_230_opt_info_test.go \
> libnbd_240_opt_list_meta_test.go \
> + libnbd_250_opt_set_meta_test.go \
> libnbd_300_get_size_test.go \
> libnbd_400_pread_test.go \
> libnbd_405_pread_structured_test.go \
> diff --git a/golang/libnbd_240_opt_list_meta_test.go
> b/golang/libnbd_240_opt_list_meta_test.go
> index 47df787..4af1008 100644
> --- a/golang/libnbd_240_opt_list_meta_test.go
> +++ b/golang/libnbd_240_opt_list_meta_test.go
> @@ -22,16 +22,16 @@ import (
> "testing"
> )
>
> -var count uint
> -var seen bool
> +var list_count uint
> +var list_seen bool
>
> func listmetaf(user_data int, name string) int {
> if user_data != 42 {
> panic("expected user_data == 42")
> }
> - count++
> + list_count++
> if (name == context_base_allocation) {
> - seen = true
> + list_seen = true
> }
> return 0
> }
> @@ -57,22 +57,22 @@ func Test240OptListMeta(t *testing.T) {
> }
>
> /* First pass: empty query should give at least "base:allocation". */
> - count = 0
> - seen = false
> + list_count = 0
> + list_seen = false
> r, err := h.OptListMetaContext(func(name string) int {
> return listmetaf(42, name)
> })
> if err != nil {
> t.Fatalf("could not request opt_list_meta_context: %s", err)
> }
> - if r != count || r < 1 || !seen {
> - t.Fatalf("unexpected count after opt_list_meta_context")
> + if r != list_count || r < 1 || !list_seen {
> + t.Fatalf("unexpected list_count after opt_list_meta_context")
> }
> - max := count
> + max := list_count
>
> /* Second pass: bogus query has no response. */
> - count = 0
> - seen = false
> + list_count = 0
> + list_seen = false
> err = h.AddMetaContext("x-nosuch:")
> if err != nil {
> t.Fatalf("could not request add_meta_context: %s", err)
> @@ -83,13 +83,13 @@ func Test240OptListMeta(t *testing.T) {
> if err != nil {
> t.Fatalf("could not request opt_list_meta_context: %s", err)
> }
> - if r != 0 || r != count || seen {
> - t.Fatalf("unexpected count after opt_list_meta_context")
> + if r != 0 || r != list_count || list_seen {
> + t.Fatalf("unexpected list_count after opt_list_meta_context")
> }
>
> /* Third pass: specific query should have one match. */
> - count = 0
> - seen = false
> + list_count = 0
> + list_seen = false
> err = h.AddMetaContext(context_base_allocation)
> if err != nil {
> t.Fatalf("could not request add_meta_context: %s", err)
> @@ -114,15 +114,15 @@ func Test240OptListMeta(t *testing.T) {
> if err != nil {
> t.Fatalf("could not request opt_list_meta_context: %s", err)
> }
> - if r != 1 || r != count || !seen {
> - t.Fatalf("unexpected count after opt_list_meta_context")
> + if r != 1 || r != list_count || !list_seen {
> + t.Fatalf("unexpected list_count after opt_list_meta_context")
> }
>
> /* Fourth pass: opt_list_meta_context is stateless, so it should
> * not wipe status learned during opt_info
> */
> - count = 0
> - seen = false
> + list_count = 0
> + list_seen = false
> _, err = h.GetSize()
> if err == nil {
> t.Fatalf("expected error")
> @@ -147,7 +147,7 @@ func Test240OptListMeta(t *testing.T) {
> t.Fatalf("can_meta_context failed unexpectedly: %s", err)
> }
> if !meta {
> - t.Fatalf("unexpected count after can_meta_context")
> + t.Fatalf("unexpected list_count after can_meta_context")
> }
> err = h.ClearMetaContexts()
> if err != nil {
> @@ -163,8 +163,8 @@ func Test240OptListMeta(t *testing.T) {
> if err != nil {
> t.Fatalf("could not request opt_list_meta_context: %s", err)
> }
> - if r != 0 || r != count || seen {
> - t.Fatalf("unexpected count after opt_list_meta_context")
> + if r != 0 || r != list_count || list_seen {
> + t.Fatalf("unexpected list_count after opt_list_meta_context")
> }
> size, err = h.GetSize()
> if err != nil {
> @@ -178,13 +178,13 @@ func Test240OptListMeta(t *testing.T) {
> t.Fatalf("can_meta_context failed unexpectedly: %s", err)
> }
> if !meta {
> - t.Fatalf("unexpected count after can_meta_context")
> + t.Fatalf("unexpected list_count after can_meta_context")
> }
> err = h.ClearMetaContexts()
>
> /* Final pass: "base:" query should get at least "base:allocation" */
> - count = 0
> - seen = false
> + list_count = 0
> + list_seen = false
> err = h.AddMetaContext("base:")
> if err != nil {
> t.Fatalf("could not request add_meta_context: %s", err)
> @@ -195,8 +195,8 @@ func Test240OptListMeta(t *testing.T) {
> if err != nil {
> t.Fatalf("could not request opt_list_meta_context: %s", err)
> }
> - if r < 1 || r > max || r != count || !seen {
> - t.Fatalf("unexpected count after opt_list_meta_context")
> + if r < 1 || r > max || r != list_count || !list_seen {
> + t.Fatalf("unexpected list_count after opt_list_meta_context")
> }
>
> err = h.OptAbort()
> diff --git a/golang/libnbd_250_opt_set_meta_test.go
> b/golang/libnbd_250_opt_set_meta_test.go
> new file mode 100644
> index 0000000..c29b7f4
> --- /dev/null
> +++ b/golang/libnbd_250_opt_set_meta_test.go
> @@ -0,0 +1,248 @@
> +/* libnbd golang tests
> + * Copyright (C) 2013-2022 Red Hat Inc.
> + *
> + * 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 (
> + "testing"
> +)
> +
> +var set_count uint
> +var set_seen bool
> +
> +func setmetaf(user_data int, name string) int {
> + if user_data != 42 {
> + panic("expected user_data == 42")
> + }
> + set_count++
> + if (name == context_base_allocation) {
> + set_seen = true
> + }
> + return 0
> +}
> +
> +func Test250OptSetMeta(t *testing.T) {
> + h, err := Create()
> + if err != nil {
> + t.Fatalf("could not create handle: %s", err)
> + }
> + defer h.Close()
> +
> + err = h.SetOptMode(true)
> + if err != nil {
> + t.Fatalf("could not set opt mode: %s", err)
> + }
> +
> + err = h.ConnectCommand([]string{
> + "nbdkit", "-s", "--exit-with-parent", "-v",
> + "memory", "size=1M",
> + })
> + if err != nil {
> + t.Fatalf("could not connect: %s", err)
> + }
> +
> + /* No contexts negotiated yet; CanMeta should be error if any
> requested */
> + sr, err := h.GetStructuredRepliesNegotiated()
> + if err != nil {
> + t.Fatalf("could not check structured replies negotiated: %s",
> err)
> + }
> + if !sr {
> + t.Fatalf("unexpected structured replies state")
> + }
> + meta, err := h.CanMetaContext(context_base_allocation)
> + if err != nil {
> + t.Fatalf("could not check can meta context: %s", err)
> + }
> + if meta {
> + t.Fatalf("unexpected can meta context state")
> + }
> + err = h.AddMetaContext(context_base_allocation)
> + if err != nil {
> + t.Fatalf("could not request add_meta_context: %s", err)
> + }
> + _, err = h.CanMetaContext(context_base_allocation)
> + if err == nil {
> + t.Fatalf("expected error")
> + }
> +
> + /* FIXME: Once OptStructuredReply exists, check that set before
> + * SR fails server-side, then enable SR for rest of process.
> + */
> +
> + /* nbdkit does not match wildcard for SET, even though it does for LIST
> */
> + set_count = 0
> + set_seen = false
> + err = h.ClearMetaContexts()
> + if err != nil {
> + t.Fatalf("could not request clear_meta_contexts: %s", err)
> + }
> + err = h.AddMetaContext("base:")
> + if err != nil {
> + t.Fatalf("could not request add_meta_context: %s", err)
> + }
> + r, err := h.OptSetMetaContext(func(name string) int {
> + return setmetaf(42, name)
> + })
> + if err != nil {
> + t.Fatalf("could not request opt_set_meta_context: %s", err)
> + }
> + if r != set_count || r != 0 || set_seen {
> + t.Fatalf("unexpected set_count after opt_set_meta_context")
> + }
> +
> + /* Request 2 with expectation of 1; with SetRequestMetaContext off */
> + set_count = 0
> + set_seen = false
> + err = h.AddMetaContext("x-nosuch:context")
> + if err != nil {
> + t.Fatalf("could not request add_meta_context: %s", err)
> + }
> + err = h.AddMetaContext(context_base_allocation)
> + if err != nil {
> + t.Fatalf("could not request add_meta_context: %s", err)
> + }
> + err = h.SetRequestMetaContext(false)
> + if err != nil {
> + t.Fatalf("could not set_request_meta_context: %s", err)
> + }
> + r, err = h.OptSetMetaContext(func(name string) int {
> + return setmetaf(42, name)
> + })
> + if err != nil {
> + t.Fatalf("could not request opt_set_meta_context: %s", err)
> + }
> + if r != 1 || r != set_count || !set_seen {
> + t.Fatalf("unexpected set_count after opt_set_meta_context")
> + }
> + meta, err = h.CanMetaContext(context_base_allocation)
> + if err != nil {
> + t.Fatalf("could not check can meta context: %s", err)
> + }
> + if !meta {
> + t.Fatalf("unexpected can meta context state")
> + }
> +
> + /* Transition to transmission phase; our last set should remain active
> */
> + err = h.ClearMetaContexts()
> + if err != nil {
> + t.Fatalf("could not request clear_meta_contexts: %s", err)
> + }
> + err = h.AddMetaContext("x-nosuch:context")
> + if err != nil {
> + t.Fatalf("could not request add_meta_context: %s", err)
> + }
> + err = h.OptGo()
> + if err != nil {
> + t.Fatalf("could not request opt_go: %s", err)
> + }
> + meta, err = h.CanMetaContext(context_base_allocation)
> + if err != nil {
> + t.Fatalf("could not check can meta context: %s", err)
> + }
> + if !meta {
> + t.Fatalf("unexpected can meta context state")
> + }
> +
> + /* Now too late to set; but should not lose earlier state */
> + set_count = 0
> + set_seen = false
> + _, err = h.OptSetMetaContext(func(name string) int {
> + return setmetaf(42, name)
> + })
> + if err == nil {
> + t.Fatalf("expected error")
> + }
> + if set_count != 0 || set_seen {
> + t.Fatalf("unexpected set_count after opt_set_meta_context")
> + }
> + meta, err = h.CanMetaContext(context_base_allocation)
> + if err != nil {
> + t.Fatalf("could not check can meta context: %s", err)
> + }
> + if !meta {
> + t.Fatalf("unexpected can meta context state")
> + }
> +
> + err = h.Shutdown(nil)
> + if err != nil {
> + t.Fatalf("could not request shutdown: %s", err)
> + }
> +
> + /* Second process, this time without structured replies server-side.
> */
> + h, err = Create()
> + if err != nil {
> + t.Fatalf("could not create handle: %s", err)
> + }
> + defer h.Close()
> +
> + err = h.SetOptMode(true)
> + if err != nil {
> + t.Fatalf("could not set opt mode: %s", err)
> + }
> +
> + err = h.AddMetaContext(context_base_allocation)
> + if err != nil {
> + t.Fatalf("could not request add_meta_context: %s", err)
> + }
> +
> + err = h.ConnectCommand([]string{
> + "nbdkit", "-s", "--exit-with-parent", "-v",
> + "memory", "size=1M", "--no-sr",
> + })
> + if err != nil {
> + t.Fatalf("could not connect: %s", err)
> + }
> +
> + sr, err = h.GetStructuredRepliesNegotiated()
> + if err != nil {
> + t.Fatalf("could not check structured replies negotiated: %s",
> err)
> + }
> + if sr {
> + t.Fatalf("unexpected structured replies state")
> + }
> +
> + /* Expect server-side failure here */
> + set_count = 0
> + set_seen = false
> + _, err = h.OptSetMetaContext(func(name string) int {
> + return setmetaf(42, name)
> + })
> + if err == nil {
> + t.Fatalf("expected error")
> + }
> + if set_count != 0 || set_seen {
> + t.Fatalf("unexpected set_count after opt_set_meta_context")
> + }
> + _, err = h.CanMetaContext(context_base_allocation)
> + if err == nil {
> + t.Fatalf("expected error")
> + }
> +
> + /* Even though CanMeta fails after failed SET, it returns 0 after go
> */
> + err = h.OptGo()
> + if err != nil {
> + t.Fatalf("could not request opt_go: %s", err)
> + }
> + meta, err = h.CanMetaContext(context_base_allocation)
> + if err != nil {
> + t.Fatalf("could not check can meta context: %s", err)
> + }
> + if meta {
> + t.Fatalf("unexpected can meta context state")
> + }
> +}
>
_______________________________________________
Libguestfs mailing list
[email protected]
https://listman.redhat.com/mailman/listinfo/libguestfs