[Libguestfs] [libnbd PATCH v2 08/12] tests: Add coverage for stateless nbd_opt_list_meta_context

Eric Blake
Wed, 31 Aug 2022 14:39:24 -0000

Add test coverage for the previous patch not wiping state during
nbd_opt_list_meta_context.  The change is logically identical in each
language that has the same unit test.
---
 python/t/240-opt-list-meta.py           | 29 +++++++++-
 ocaml/tests/test_240_opt_list_meta.ml   | 34 ++++++++++-
 tests/opt-list-meta.c                   | 76 +++++++++++++++++++++++--
 golang/libnbd_240_opt_list_meta_test.go | 64 ++++++++++++++++++++-
 4 files changed, 193 insertions(+), 10 deletions(-)

diff --git a/python/t/240-opt-list-meta.py b/python/t/240-opt-list-meta.py
index 8341f9c..591703a 100644
--- a/python/t/240-opt-list-meta.py
+++ b/python/t/240-opt-list-meta.py
@@ -1,5 +1,5 @@
 # libnbd Python bindings
-# Copyright (C) 2010-2020 Red Hat Inc.
+# 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
@@ -31,6 +31,14 @@ def f(user_data, name):
         seen = True


+def must_fail(f, *args, **kwds):
+    try:
+        f(*args, **kwds)
+        assert False
+    except nbd.Error:
+        pass
+
+
 h = nbd.NBD()
 h.set_opt_mode(True)
 h.connect_command(["nbdkit", "-s",
"--exit-with-parent", "-v",
@@ -65,10 +73,27 @@ assert r == 1
 assert count == 1
 assert seen

-# Final pass: "base:" query should get at least
"base:allocation"
+# Fourth pass: opt_list_meta_context is stateless, so it should
+# not wipe status learned during opt_info
 count = 0
 seen = False
+must_fail(h.can_meta_context, nbd.CONTEXT_BASE_ALLOCATION)
+must_fail(h.get_size)
+h.opt_info()
+assert h.get_size() == 1024*1024
+assert h.can_meta_context(nbd.CONTEXT_BASE_ALLOCATION) is True
 h.clear_meta_contexts()
+h.add_meta_context("x-nosuch:")
+r = h.opt_list_meta_context(lambda *args: f(42, *args))
+assert r == 0
+assert count == 0
+assert not seen
+assert h.get_size() == 1048576
+assert h.can_meta_context(nbd.CONTEXT_BASE_ALLOCATION) is True
+
+# Final pass: "base:" query should get at least
"base:allocation"
+count = 0
+seen = False
 h.add_meta_context("base:")
 r = h.opt_list_meta_context(lambda *args: f(42, *args))
 assert r >= 1
diff --git a/ocaml/tests/test_240_opt_list_meta.ml
b/ocaml/tests/test_240_opt_list_meta.ml
index 639d33c..afab084 100644
--- a/ocaml/tests/test_240_opt_list_meta.ml
+++ b/ocaml/tests/test_240_opt_list_meta.ml
@@ -64,10 +64,42 @@ let
   assert (r = !count);
   assert !seen;

-  (* Final pass: "base:" query should get at least
"base:allocation" *)
+  (* Fourth pass: opt_list_meta_context is stateless, so it should
+   * not wipe status learned during opt_info
+   *)
   count := 0;
   seen := false;
+  (try
+     let _ = NBD.can_meta_context nbd NBD.context_base_allocation in
+     assert false
+   with
+     NBD.Error (errstr, errno) -> ()
+  );
+  (try
+     let _ = NBD.get_size nbd in
+     assert false
+   with
+     NBD.Error (errstr, errno) -> ()
+  );
+  NBD.opt_info nbd;
+  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.clear_meta_contexts nbd;
+  NBD.add_meta_context nbd "x-nosuch:";
+  let r = NBD.opt_list_meta_context nbd (f 42) in
+  assert (r = 0);
+  assert (r = !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;
+
+  (* Final pass: "base:" query should get at least
"base:allocation" *)
+  count := 0;
+  seen := false;
   NBD.add_meta_context nbd "base:";
   let r = NBD.opt_list_meta_context nbd (f 42) in
   assert (r >= 1);
diff --git a/tests/opt-list-meta.c b/tests/opt-list-meta.c
index ccf58fc..12d6f51 100644
--- a/tests/opt-list-meta.c
+++ b/tests/opt-list-meta.c
@@ -138,13 +138,79 @@ main (int argc, char *argv[])
     exit (EXIT_FAILURE);
   }

+  /* Fourth pass: nbd_opt_list_meta_context is stateless, so it should
+   * not wipe status learned during nbd_opt_info().
+   */
+  r = nbd_get_size (nbd);
+  if (r != -1) {
+    fprintf (stderr, "expecting get_size to fail, got %d\n", r);
+    exit (EXIT_FAILURE);
+  }
+  r = nbd_can_meta_context (nbd, LIBNBD_CONTEXT_BASE_ALLOCATION);
+  if (r != -1) {
+    fprintf (stderr, "expecting can_meta_context to fail, got %d\n",
r);
+    exit (EXIT_FAILURE);
+  }
+  if (nbd_opt_info (nbd) == -1) {
+    fprintf (stderr, "%s\n", nbd_get_error ());
+    exit (EXIT_FAILURE);
+  }
+  r = nbd_get_size (nbd);
+  if (r == -1) {
+    fprintf (stderr, "%s\n", nbd_get_error ());
+    exit (EXIT_FAILURE);
+  }
+  if (r != 1024*1024) {
+    fprintf (stderr, "expecting get_size of 1M, got %d\n", r);
+    exit (EXIT_FAILURE);
+  }
+  r = nbd_can_meta_context (nbd, LIBNBD_CONTEXT_BASE_ALLOCATION);
+  if (r == -1) {
+    fprintf (stderr, "%s\n", nbd_get_error ());
+    exit (EXIT_FAILURE);
+  }
+  if (r != 1) {
+    fprintf (stderr, "expecting can_meta_context to succeed, got
%d\n", r);
+    exit (EXIT_FAILURE);
+  }
+  if (nbd_clear_meta_contexts (nbd) == -1 ||
+      nbd_add_meta_context (nbd, "x-nosuch:") == -1) {
+    fprintf (stderr, "%s\n", nbd_get_error ());
+    exit (EXIT_FAILURE);
+  }
+  p = (struct progress) { .count = 0 };
+  r = nbd_opt_list_meta_context (nbd,
+                                 (nbd_context_callback) { .callback = check,
+                                                          .user_data =
&p});
+  if (r == -1) {
+    fprintf (stderr, "%s\n", nbd_get_error ());
+    exit (EXIT_FAILURE);
+  }
+  if (r != 0 || p.count != 0 || p.seen) {
+    fprintf (stderr, "expecting no contexts, got %d\n", r);
+    exit (EXIT_FAILURE);
+  }
+  r = nbd_get_size (nbd);
+  if (r == -1) {
+    fprintf (stderr, "%s\n", nbd_get_error ());
+    exit (EXIT_FAILURE);
+  }
+  if (r != 1048576) {
+    fprintf (stderr, "expecting get_size of 1M, got %d\n", r);
+    exit (EXIT_FAILURE);
+  }
+  r = nbd_can_meta_context (nbd, LIBNBD_CONTEXT_BASE_ALLOCATION);
+  if (r == -1) {
+    fprintf (stderr, "%s\n", nbd_get_error ());
+    exit (EXIT_FAILURE);
+  }
+  if (r != 1) {
+    fprintf (stderr, "expecting can_meta_context to succeed, got
%d\n", r);
+    exit (EXIT_FAILURE);
+  }
+
   /* Final pass: "base:" query should get at least
"base:allocation" */
   p = (struct progress) { .count = 0 };
-  r = nbd_clear_meta_contexts (nbd);
-  if (r == -1) {
-    fprintf (stderr, "%s\n", nbd_get_error ());
-    exit (EXIT_FAILURE);
-  }
   r = nbd_add_meta_context (nbd, "base:");
   if (r == -1) {
     fprintf (stderr, "%s\n", nbd_get_error ());
diff --git a/golang/libnbd_240_opt_list_meta_test.go
b/golang/libnbd_240_opt_list_meta_test.go
index d732275..47df787 100644
--- a/golang/libnbd_240_opt_list_meta_test.go
+++ b/golang/libnbd_240_opt_list_meta_test.go
@@ -1,5 +1,5 @@
 /* libnbd golang tests
- * Copyright (C) 2013-2021 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
@@ -118,13 +118,73 @@ func Test240OptListMeta(t *testing.T) {
 		t.Fatalf("unexpected count after opt_list_meta_context")
 	}

-	/* Final pass: "base:" query should get at least
"base:allocation" */
+	/* Fourth pass: opt_list_meta_context is stateless, so it should
+     * not wipe status learned during opt_info
+	 */
 	count = 0
 	seen = false
+        _, err = h.GetSize()
+	if err == nil {
+		t.Fatalf("expected error")
+	}
+	_, err = h.CanMetaContext(context_base_allocation)
+	if err == nil {
+		t.Fatalf("expected error")
+	}
+	err = h.OptInfo()
+	if err != nil {
+		t.Fatalf("opt_info failed unexpectedly: %s", err)
+	}
+        size, err := h.GetSize()
+	if err != nil {
+		t.Fatalf("get_size failed unexpectedly: %s", err)
+	}
+        if size != 1048576 {
+		t.Fatalf("get_size gave wrong size")
+        }
+	meta, err := h.CanMetaContext(context_base_allocation)
+	if err != nil {
+		t.Fatalf("can_meta_context failed unexpectedly: %s", err)
+	}
+	if !meta {
+		t.Fatalf("unexpected count after can_meta_context")
+	}
 	err = h.ClearMetaContexts()
 	if err != nil {
 		t.Fatalf("could not request clear_meta_contexts: %s", err)
 	}
+	err = h.AddMetaContext("x-nosuch:")
+	if err != nil {
+		t.Fatalf("could not request add_meta_context: %s", err)
+	}
+	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 != 0 || r != count || seen {
+		t.Fatalf("unexpected count after opt_list_meta_context")
+	}
+        size, err = h.GetSize()
+	if err != nil {
+		t.Fatalf("get_size failed unexpectedly: %s", err)
+	}
+        if size != 1048576 {
+		t.Fatalf("get_size gave wrong size")
+        }
+	meta, err = h.CanMetaContext(context_base_allocation)
+	if err != nil {
+		t.Fatalf("can_meta_context failed unexpectedly: %s", err)
+	}
+	if !meta {
+		t.Fatalf("unexpected count after can_meta_context")
+	}
+	err = h.ClearMetaContexts()
+
+	/* Final pass: "base:" query should get at least
"base:allocation" */
+	count = 0
+	seen = false
 	err = h.AddMetaContext("base:")
 	if err != nil {
 		t.Fatalf("could not request add_meta_context: %s", err)
--
2.37.2