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")
> +     }
> +}
> 

_______________________________________________
Libguestfs mailing list
Libguestfs@redhat.com
https://listman.redhat.com/mailman/listinfo/libguestfs

Reply via email to