Eric Blake
2022-Sep-02 22:14 UTC
[Libguestfs] [libnbd PATCH 4/4] tests: Add language binding tests for stats reception
This proves that the stat counters increment as desired, as well as
proving that our RUInt32 generator type works.
This commit is also a showcase of whether I can do 64-bit math in
various languages (C's terseness in 'a == b + (c > d)' is
annoying to
replicate in languages that don't like playing fast and loose with
types). :)
---
python/t/620-stats.py | 77 +++++++++++++++
ocaml/tests/Makefile.am | 1 +
ocaml/tests/test_620_stats.ml | 77 +++++++++++++++
golang/Makefile.am | 3 +-
golang/libnbd_620_stats.go | 181 ++++++++++++++++++++++++++++++++++
5 files changed, 338 insertions(+), 1 deletion(-)
create mode 100644 python/t/620-stats.py
create mode 100644 ocaml/tests/test_620_stats.ml
create mode 100644 golang/libnbd_620_stats.go
diff --git a/python/t/620-stats.py b/python/t/620-stats.py
new file mode 100644
index 00000000..62f8443f
--- /dev/null
+++ b/python/t/620-stats.py
@@ -0,0 +1,77 @@
+# 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
+
+h = nbd.NBD()
+
+# Pre-connection, stats start out at 0
+bs0 = h.stats_bytes_sent()
+cs0 = h.stats_chunks_sent()
+br0 = h.stats_bytes_received()
+cr0 = h.stats_chunks_received()
+
+assert bs0 == 0
+assert cs0 == 0
+assert br0 == 0
+assert cr0 == 0
+
+# Connection performs handshaking, which increments stats.
+# The number of bytes/chunks here may grow over time as more features get
+# automatically negotiated, so merely check that they are non-zero.
+h.connect_command(["nbdkit", "-s",
"--exit-with-parent", "null"])
+
+bs1 = h.stats_bytes_sent()
+cs1 = h.stats_chunks_sent()
+br1 = h.stats_bytes_received()
+cr1 = h.stats_chunks_received()
+
+assert cs1 > 0
+assert bs1 > cs1
+assert cr1 > 0
+assert br1 > cr1
+
+# A flush command should be one chunk out, one chunk back (even if
+# structured replies are in use)
+h.flush()
+
+bs2 = h.stats_bytes_sent()
+cs2 = h.stats_chunks_sent()
+br2 = h.stats_bytes_received()
+cr2 = h.stats_chunks_received()
+
+assert bs2 == bs1 + 28
+assert cs2 == cs1 + 1
+assert br2 == br1 + 16 # assumes nbdkit uses simple reply
+assert cr2 == cr1 + 1
+
+# Stats are still readable after the connection closes; we don't know if
+# the server sent reply bytes to our NBD_CMD_DISC, so don't insist on it.
+h.shutdown()
+
+bs3 = h.stats_bytes_sent()
+cs3 = h.stats_chunks_sent()
+br3 = h.stats_bytes_received()
+cr3 = h.stats_chunks_received()
+
+assert bs3 > bs2
+assert cs3 == cs2 + 1
+assert br3 >= br2
+assert cr3 == cr2 + (br3 > br2)
+
+# Try to trigger garbage collection of h
+h = None
diff --git a/ocaml/tests/Makefile.am b/ocaml/tests/Makefile.am
index 22cefb4d..c4751ad3 100644
--- a/ocaml/tests/Makefile.am
+++ b/ocaml/tests/Makefile.am
@@ -42,6 +42,7 @@ ML_TESTS = \
test_590_aio_copy.ml \
test_600_debug_callback.ml \
test_610_exception.ml \
+ test_620_stats.ml \
$(NULL)
EXTRA_DIST = $(ML_TESTS)
diff --git a/ocaml/tests/test_620_stats.ml b/ocaml/tests/test_620_stats.ml
new file mode 100644
index 00000000..648096fd
--- /dev/null
+++ b/ocaml/tests/test_620_stats.ml
@@ -0,0 +1,77 @@
+(* 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 () + let nbd = NBD.create () in
+
+ (* Pre-connection, stats start out at 0 *)
+ let bs0 = NBD.stats_bytes_sent nbd in
+ let cs0 = NBD.stats_chunks_sent nbd in
+ let br0 = NBD.stats_bytes_received nbd in
+ let cr0 = NBD.stats_chunks_received nbd in
+ assert (bs0 = 0L);
+ assert (cs0 = 0L);
+ assert (br0 = 0L);
+ assert (cr0 = 0L);
+
+ (* Connection performs handshaking, which increments stats.
+ * The number of bytes/chunks here may grow over time as more features get
+ * automatically negotiated, so merely check that they are non-zero.
+ *)
+ NBD.connect_command nbd ["nbdkit"; "-s";
"--exit-with-parent"; "null"];
+
+ let bs1 = NBD.stats_bytes_sent nbd in
+ let cs1 = NBD.stats_chunks_sent nbd in
+ let br1 = NBD.stats_bytes_received nbd in
+ let cr1 = NBD.stats_chunks_received nbd in
+ assert (cs1 > 0L);
+ assert (bs1 > cs1);
+ assert (cr1 > 0L);
+ assert (br1 > cr1);
+
+ (* A flush command should be one chunk out, one chunk back (even if
+ * structured replies are in use)
+ *)
+ NBD.flush nbd;
+
+ let bs2 = NBD.stats_bytes_sent nbd in
+ let cs2 = NBD.stats_chunks_sent nbd in
+ let br2 = NBD.stats_bytes_received nbd in
+ let cr2 = NBD.stats_chunks_received nbd in
+ assert (bs2 = (Int64.add bs1 28L));
+ assert (cs2 = (Int64.succ cs1));
+ assert (br2 = (Int64.add br1 16L)); (* assumes nbdkit uses simple reply *)
+ assert (cr2 = (Int64.succ cr1));
+
+ (* Stats are still readable after the connection closes; we don't know if
+ * the server sent reply bytes to our NBD_CMD_DISC, so don't insist on
it.
+ *)
+ NBD.shutdown nbd;
+
+ let bs3 = NBD.stats_bytes_sent nbd in
+ let cs3 = NBD.stats_chunks_sent nbd in
+ let br3 = NBD.stats_bytes_received nbd in
+ let cr3 = NBD.stats_chunks_received nbd in
+ let fudge = if cr2 = cr3 then 0L else 1L in
+ assert (bs3 > bs2);
+ assert (cs3 = (Int64.succ cs2));
+ assert (br3 >= br2);
+ assert (cr3 = (Int64.add cr2 fudge))
+
+let () = Gc.compact ()
diff --git a/golang/Makefile.am b/golang/Makefile.am
index f170cbc4..765382d4 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
@@ -45,6 +45,7 @@ source_files = \
libnbd_590_aio_copy_test.go \
libnbd_600_debug_callback_test.go \
libnbd_610_error_test.go \
+ libnbd_620_stats.go \
$(NULL)
generator_built = \
diff --git a/golang/libnbd_620_stats.go b/golang/libnbd_620_stats.go
new file mode 100644
index 00000000..8d566198
--- /dev/null
+++ b/golang/libnbd_620_stats.go
@@ -0,0 +1,181 @@
+/* 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"
+
+func Test620Stats(t *testing.T) {
+ h, err := Create()
+ if err != nil {
+ t.Fatalf("could not create handle: %s", err)
+ }
+ defer h.Close()
+
+ /* Pre-connection, stats start out at 0 */
+ bs0, err := h.StatsBytesSent()
+ if err != nil {
+ t.Fatalf("%s", err)
+ }
+ cs0, err := h.StatsChunksSent()
+ if err != nil {
+ t.Fatalf("%s", err)
+ }
+ br0, err := h.StatsBytesReceived()
+ if err != nil {
+ t.Fatalf("%s", err)
+ }
+ cr0, err := h.StatsChunksReceived()
+ if err != nil {
+ t.Fatalf("%s", err)
+ }
+
+ if bs0 != 0 {
+ t.Fatalf("unexpected value for bs0")
+ }
+ if cs0 != 0 {
+ t.Fatalf("unexpected value for cs0")
+ }
+ if br0 != 0 {
+ t.Fatalf("unexpected value for br0")
+ }
+ if cr0 != 0 {
+ t.Fatalf("unexpected value for cr0")
+ }
+
+ /* Connection performs handshaking, which increments stats.
+ * The number of bytes/chunks here may grow over time as more features
+ * get automatically negotiated, so merely check that they are non-zero.
+ */
+ err = h.ConnectCommand([]string{
+ "nbdkit", "-s", "--exit-with-parent",
"null",
+ })
+ if err != nil {
+ t.Fatalf("%s", err)
+ }
+
+ bs1, err := h.StatsBytesSent()
+ if err != nil {
+ t.Fatalf("%s", err)
+ }
+ cs1, err := h.StatsChunksSent()
+ if err != nil {
+ t.Fatalf("%s", err)
+ }
+ br1, err := h.StatsBytesReceived()
+ if err != nil {
+ t.Fatalf("%s", err)
+ }
+ cr1, err := h.StatsChunksReceived()
+ if err != nil {
+ t.Fatalf("%s", err)
+ }
+
+ if cs1 == 0 {
+ t.Fatalf("unexpected value for cs1")
+ }
+ if bs1 <= cs1 {
+ t.Fatalf("unexpected value for bs1")
+ }
+ if cr1 == 0 {
+ t.Fatalf("unexpected value for cr1")
+ }
+ if br1 <= cr1 {
+ t.Fatalf("unexpected value for br1")
+ }
+
+ /* A flush command should be one chunk out, one chunk back (even if
+ * structured replies are in use)
+ */
+ err = h.Flush(nil)
+ if err != nil {
+ t.Fatalf("%s", err)
+ }
+
+ bs2, err := h.StatsBytesSent()
+ if err != nil {
+ t.Fatalf("%s", err)
+ }
+ cs2, err := h.StatsChunksSent()
+ if err != nil {
+ t.Fatalf("%s", err)
+ }
+ br2, err := h.StatsBytesReceived()
+ if err != nil {
+ t.Fatalf("%s", err)
+ }
+ cr2, err := h.StatsChunksReceived()
+ if err != nil {
+ t.Fatalf("%s", err)
+ }
+
+ if bs2 != bs1 + 28 {
+ t.Fatalf("unexpected value for bs2")
+ }
+ if cs2 != cs1 + 1 {
+ t.Fatalf("unexpected value for cs2")
+ }
+ if br2 != br1 + 16 { /* assumes nbdkit uses simple reply */
+ t.Fatalf("unexpected value for br2")
+ }
+ if cr2 != cr1 + 1 {
+ t.Fatalf("unexpected value for cr2")
+ }
+
+ /* Stats are still readable after the connection closes; we don't know if
+ * the server sent reply bytes to our NBD_CMD_DISC, so don't insist on it.
+ */
+ err = h.Shutdown(nil)
+ if err != nil {
+ t.Fatalf("%s", err)
+ }
+
+ bs3, err := h.StatsBytesSent()
+ if err != nil {
+ t.Fatalf("%s", err)
+ }
+ cs3, err := h.StatsChunksSent()
+ if err != nil {
+ t.Fatalf("%s", err)
+ }
+ br3, err := h.StatsBytesReceived()
+ if err != nil {
+ t.Fatalf("%s", err)
+ }
+ cr3, err := h.StatsChunksReceived()
+ if err != nil {
+ t.Fatalf("%s", err)
+ }
+ slop := uint64(1)
+ if br2 == br3 {
+ slop = uint64(0)
+ }
+
+ if bs3 <= bs2 {
+ t.Fatalf("unexpected value for bs3")
+ }
+ if cs3 != cs2 + 1 {
+ t.Fatalf("unexpected value for cs3")
+ }
+ if br3 < br2 {
+ t.Fatalf("unexpected value for br3")
+ }
+ if cr3 != cr2 + slop {
+ t.Fatalf("unexpected value for cr3")
+ }
+}
--
2.37.2
Richard W.M. Jones
2022-Sep-03 16:32 UTC
[Libguestfs] [libnbd PATCH 4/4] tests: Add language binding tests for stats reception
So the patch series is OK, modulo my comments. But I think it'd be better not to bind our future selves to complicated guarantees about what are basically internal details of the library and protocol. Rich. -- Richard Jones, Virtualization Group, Red Hat http://people.redhat.com/~rjones Read my programming and virtualization blog: http://rwmj.wordpress.com virt-top is 'top' for virtual machines. Tiny program with many powerful monitoring features, net stats, disk stats, logging, etc. http://people.redhat.com/~rjones/virt-top
Laszlo Ersek
2022-Sep-05 12:10 UTC
[Libguestfs] [libnbd PATCH 4/4] tests: Add language binding tests for stats reception
On 09/03/22 00:14, Eric Blake wrote:> This proves that the stat counters increment as desired, as well as > proving that our RUInt32 generator type works.How is this related to RUint32?> > This commit is also a showcase of whether I can do 64-bit math in > various languages (C's terseness in 'a == b + (c > d)' is annoying to > replicate in languages that don't like playing fast and loose with > types). :)I don't understand; please elaborate. Thanks Laszlo> --- > python/t/620-stats.py | 77 +++++++++++++++ > ocaml/tests/Makefile.am | 1 + > ocaml/tests/test_620_stats.ml | 77 +++++++++++++++ > golang/Makefile.am | 3 +- > golang/libnbd_620_stats.go | 181 ++++++++++++++++++++++++++++++++++ > 5 files changed, 338 insertions(+), 1 deletion(-) > create mode 100644 python/t/620-stats.py > create mode 100644 ocaml/tests/test_620_stats.ml > create mode 100644 golang/libnbd_620_stats.go > > diff --git a/python/t/620-stats.py b/python/t/620-stats.py > new file mode 100644 > index 00000000..62f8443f > --- /dev/null > +++ b/python/t/620-stats.py > @@ -0,0 +1,77 @@ > +# 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 > + > +h = nbd.NBD() > + > +# Pre-connection, stats start out at 0 > +bs0 = h.stats_bytes_sent() > +cs0 = h.stats_chunks_sent() > +br0 = h.stats_bytes_received() > +cr0 = h.stats_chunks_received() > + > +assert bs0 == 0 > +assert cs0 == 0 > +assert br0 == 0 > +assert cr0 == 0 > + > +# Connection performs handshaking, which increments stats. > +# The number of bytes/chunks here may grow over time as more features get > +# automatically negotiated, so merely check that they are non-zero. > +h.connect_command(["nbdkit", "-s", "--exit-with-parent", "null"]) > + > +bs1 = h.stats_bytes_sent() > +cs1 = h.stats_chunks_sent() > +br1 = h.stats_bytes_received() > +cr1 = h.stats_chunks_received() > + > +assert cs1 > 0 > +assert bs1 > cs1 > +assert cr1 > 0 > +assert br1 > cr1 > + > +# A flush command should be one chunk out, one chunk back (even if > +# structured replies are in use) > +h.flush() > + > +bs2 = h.stats_bytes_sent() > +cs2 = h.stats_chunks_sent() > +br2 = h.stats_bytes_received() > +cr2 = h.stats_chunks_received() > + > +assert bs2 == bs1 + 28 > +assert cs2 == cs1 + 1 > +assert br2 == br1 + 16 # assumes nbdkit uses simple reply > +assert cr2 == cr1 + 1 > + > +# Stats are still readable after the connection closes; we don't know if > +# the server sent reply bytes to our NBD_CMD_DISC, so don't insist on it. > +h.shutdown() > + > +bs3 = h.stats_bytes_sent() > +cs3 = h.stats_chunks_sent() > +br3 = h.stats_bytes_received() > +cr3 = h.stats_chunks_received() > + > +assert bs3 > bs2 > +assert cs3 == cs2 + 1 > +assert br3 >= br2 > +assert cr3 == cr2 + (br3 > br2) > + > +# Try to trigger garbage collection of h > +h = None > diff --git a/ocaml/tests/Makefile.am b/ocaml/tests/Makefile.am > index 22cefb4d..c4751ad3 100644 > --- a/ocaml/tests/Makefile.am > +++ b/ocaml/tests/Makefile.am > @@ -42,6 +42,7 @@ ML_TESTS = \ > test_590_aio_copy.ml \ > test_600_debug_callback.ml \ > test_610_exception.ml \ > + test_620_stats.ml \ > $(NULL) > > EXTRA_DIST = $(ML_TESTS) > diff --git a/ocaml/tests/test_620_stats.ml b/ocaml/tests/test_620_stats.ml > new file mode 100644 > index 00000000..648096fd > --- /dev/null > +++ b/ocaml/tests/test_620_stats.ml > @@ -0,0 +1,77 @@ > +(* 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 () > + let nbd = NBD.create () in > + > + (* Pre-connection, stats start out at 0 *) > + let bs0 = NBD.stats_bytes_sent nbd in > + let cs0 = NBD.stats_chunks_sent nbd in > + let br0 = NBD.stats_bytes_received nbd in > + let cr0 = NBD.stats_chunks_received nbd in > + assert (bs0 = 0L); > + assert (cs0 = 0L); > + assert (br0 = 0L); > + assert (cr0 = 0L); > + > + (* Connection performs handshaking, which increments stats. > + * The number of bytes/chunks here may grow over time as more features get > + * automatically negotiated, so merely check that they are non-zero. > + *) > + NBD.connect_command nbd ["nbdkit"; "-s"; "--exit-with-parent"; "null"]; > + > + let bs1 = NBD.stats_bytes_sent nbd in > + let cs1 = NBD.stats_chunks_sent nbd in > + let br1 = NBD.stats_bytes_received nbd in > + let cr1 = NBD.stats_chunks_received nbd in > + assert (cs1 > 0L); > + assert (bs1 > cs1); > + assert (cr1 > 0L); > + assert (br1 > cr1); > + > + (* A flush command should be one chunk out, one chunk back (even if > + * structured replies are in use) > + *) > + NBD.flush nbd; > + > + let bs2 = NBD.stats_bytes_sent nbd in > + let cs2 = NBD.stats_chunks_sent nbd in > + let br2 = NBD.stats_bytes_received nbd in > + let cr2 = NBD.stats_chunks_received nbd in > + assert (bs2 = (Int64.add bs1 28L)); > + assert (cs2 = (Int64.succ cs1)); > + assert (br2 = (Int64.add br1 16L)); (* assumes nbdkit uses simple reply *) > + assert (cr2 = (Int64.succ cr1)); > + > + (* Stats are still readable after the connection closes; we don't know if > + * the server sent reply bytes to our NBD_CMD_DISC, so don't insist on it. > + *) > + NBD.shutdown nbd; > + > + let bs3 = NBD.stats_bytes_sent nbd in > + let cs3 = NBD.stats_chunks_sent nbd in > + let br3 = NBD.stats_bytes_received nbd in > + let cr3 = NBD.stats_chunks_received nbd in > + let fudge = if cr2 = cr3 then 0L else 1L in > + assert (bs3 > bs2); > + assert (cs3 = (Int64.succ cs2)); > + assert (br3 >= br2); > + assert (cr3 = (Int64.add cr2 fudge)) > + > +let () = Gc.compact () > diff --git a/golang/Makefile.am b/golang/Makefile.am > index f170cbc4..765382d4 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 > @@ -45,6 +45,7 @@ source_files = \ > libnbd_590_aio_copy_test.go \ > libnbd_600_debug_callback_test.go \ > libnbd_610_error_test.go \ > + libnbd_620_stats.go \ > $(NULL) > > generator_built = \ > diff --git a/golang/libnbd_620_stats.go b/golang/libnbd_620_stats.go > new file mode 100644 > index 00000000..8d566198 > --- /dev/null > +++ b/golang/libnbd_620_stats.go > @@ -0,0 +1,181 @@ > +/* 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" > + > +func Test620Stats(t *testing.T) { > + h, err := Create() > + if err != nil { > + t.Fatalf("could not create handle: %s", err) > + } > + defer h.Close() > + > + /* Pre-connection, stats start out at 0 */ > + bs0, err := h.StatsBytesSent() > + if err != nil { > + t.Fatalf("%s", err) > + } > + cs0, err := h.StatsChunksSent() > + if err != nil { > + t.Fatalf("%s", err) > + } > + br0, err := h.StatsBytesReceived() > + if err != nil { > + t.Fatalf("%s", err) > + } > + cr0, err := h.StatsChunksReceived() > + if err != nil { > + t.Fatalf("%s", err) > + } > + > + if bs0 != 0 { > + t.Fatalf("unexpected value for bs0") > + } > + if cs0 != 0 { > + t.Fatalf("unexpected value for cs0") > + } > + if br0 != 0 { > + t.Fatalf("unexpected value for br0") > + } > + if cr0 != 0 { > + t.Fatalf("unexpected value for cr0") > + } > + > + /* Connection performs handshaking, which increments stats. > + * The number of bytes/chunks here may grow over time as more features > + * get automatically negotiated, so merely check that they are non-zero. > + */ > + err = h.ConnectCommand([]string{ > + "nbdkit", "-s", "--exit-with-parent", "null", > + }) > + if err != nil { > + t.Fatalf("%s", err) > + } > + > + bs1, err := h.StatsBytesSent() > + if err != nil { > + t.Fatalf("%s", err) > + } > + cs1, err := h.StatsChunksSent() > + if err != nil { > + t.Fatalf("%s", err) > + } > + br1, err := h.StatsBytesReceived() > + if err != nil { > + t.Fatalf("%s", err) > + } > + cr1, err := h.StatsChunksReceived() > + if err != nil { > + t.Fatalf("%s", err) > + } > + > + if cs1 == 0 { > + t.Fatalf("unexpected value for cs1") > + } > + if bs1 <= cs1 { > + t.Fatalf("unexpected value for bs1") > + } > + if cr1 == 0 { > + t.Fatalf("unexpected value for cr1") > + } > + if br1 <= cr1 { > + t.Fatalf("unexpected value for br1") > + } > + > + /* A flush command should be one chunk out, one chunk back (even if > + * structured replies are in use) > + */ > + err = h.Flush(nil) > + if err != nil { > + t.Fatalf("%s", err) > + } > + > + bs2, err := h.StatsBytesSent() > + if err != nil { > + t.Fatalf("%s", err) > + } > + cs2, err := h.StatsChunksSent() > + if err != nil { > + t.Fatalf("%s", err) > + } > + br2, err := h.StatsBytesReceived() > + if err != nil { > + t.Fatalf("%s", err) > + } > + cr2, err := h.StatsChunksReceived() > + if err != nil { > + t.Fatalf("%s", err) > + } > + > + if bs2 != bs1 + 28 { > + t.Fatalf("unexpected value for bs2") > + } > + if cs2 != cs1 + 1 { > + t.Fatalf("unexpected value for cs2") > + } > + if br2 != br1 + 16 { /* assumes nbdkit uses simple reply */ > + t.Fatalf("unexpected value for br2") > + } > + if cr2 != cr1 + 1 { > + t.Fatalf("unexpected value for cr2") > + } > + > + /* Stats are still readable after the connection closes; we don't know if > + * the server sent reply bytes to our NBD_CMD_DISC, so don't insist on it. > + */ > + err = h.Shutdown(nil) > + if err != nil { > + t.Fatalf("%s", err) > + } > + > + bs3, err := h.StatsBytesSent() > + if err != nil { > + t.Fatalf("%s", err) > + } > + cs3, err := h.StatsChunksSent() > + if err != nil { > + t.Fatalf("%s", err) > + } > + br3, err := h.StatsBytesReceived() > + if err != nil { > + t.Fatalf("%s", err) > + } > + cr3, err := h.StatsChunksReceived() > + if err != nil { > + t.Fatalf("%s", err) > + } > + slop := uint64(1) > + if br2 == br3 { > + slop = uint64(0) > + } > + > + if bs3 <= bs2 { > + t.Fatalf("unexpected value for bs3") > + } > + if cs3 != cs2 + 1 { > + t.Fatalf("unexpected value for cs3") > + } > + if br3 < br2 { > + t.Fatalf("unexpected value for br3") > + } > + if cr3 != cr2 + slop { > + t.Fatalf("unexpected value for cr3") > + } > +} >