Blame SOURCES/0010-tests-Test-the-Python-plugin-thoroughly.patch

538efe
From 7cb79aef2a12f29f1286caf3858001e47214f871 Mon Sep 17 00:00:00 2001
538efe
From: "Richard W.M. Jones" <rjones@redhat.com>
538efe
Date: Thu, 21 Nov 2019 20:54:41 +0000
538efe
Subject: [PATCH 10/19] tests: Test the Python plugin thoroughly.
538efe
538efe
This tests the Python plugin thoroughly by issuing client commands
538efe
through libnbd and checking we get the expected results.
538efe
538efe
(cherry picked from commit 8ead4a82ec3227dbecb6cbfc419f1a18f2817d62)
538efe
---
538efe
 .gitignore                  |   1 +
538efe
 README                      |   2 +
538efe
 tests/Makefile.am           |  15 +--
538efe
 tests/test-lang-plugins.c   |   3 +-
538efe
 tests/test-python-plugin.py | 133 +++++++++++++++++++++
538efe
 tests/test-python.sh        |  49 ++++++++
538efe
 tests/test.py               |  60 ----------
538efe
 tests/test_python.py        | 222 ++++++++++++++++++++++++++++++++++++
538efe
 8 files changed, 413 insertions(+), 72 deletions(-)
538efe
 create mode 100644 tests/test-python-plugin.py
538efe
 create mode 100755 tests/test-python.sh
538efe
 delete mode 100644 tests/test.py
538efe
 create mode 100755 tests/test_python.py
538efe
538efe
diff --git a/.gitignore b/.gitignore
538efe
index b25ac7fe..e25bd99b 100644
538efe
--- a/.gitignore
538efe
+++ b/.gitignore
538efe
@@ -71,6 +71,7 @@ Makefile.in
538efe
 /server/synopsis.c
538efe
 /server/test-public
538efe
 /stamp-h1
538efe
+/tests/__pycache__/
538efe
 /tests/disk
538efe
 /tests/disk.gz
538efe
 /tests/disk.xz
538efe
diff --git a/README b/README
538efe
index 40f4cd37..05f1e060 100644
538efe
--- a/README
538efe
+++ b/README
538efe
@@ -130,6 +130,8 @@ For the Python plugin:
538efe
 
538efe
  - python development libraries
538efe
 
538efe
+ - python unittest to run the test suite
538efe
+
538efe
 For the OCaml plugin:
538efe
 
538efe
  - OCaml >= 4.02.2
538efe
diff --git a/tests/Makefile.am b/tests/Makefile.am
538efe
index d225cc63..09103fbb 100644
538efe
--- a/tests/Makefile.am
538efe
+++ b/tests/Makefile.am
538efe
@@ -67,6 +67,7 @@ EXTRA_PROGRAMS =
538efe
 TESTS_ENVIRONMENT = \
538efe
 	PATH=$(abs_top_builddir):$(PATH) \
538efe
 	SRCDIR=$(srcdir) \
538efe
+	PYTHON=$(PYTHON) \
538efe
 	LIBGUESTFS_ATTACH_METHOD=appliance \
538efe
 	LIBGUESTFS_DEBUG=1 \
538efe
 	LIBGUESTFS_TRACE=1 \
538efe
@@ -160,7 +161,9 @@ EXTRA_DIST = \
538efe
 	test-probe-plugin.sh \
538efe
 	test-python-exception.sh \
538efe
 	test.pl \
538efe
-	test.py \
538efe
+	test_python.py \
538efe
+	test-python-plugin.py \
538efe
+	test-python.sh \
538efe
 	test-rate.sh \
538efe
 	test-rate-dynamic.sh \
538efe
 	test.rb \
538efe
@@ -801,18 +804,10 @@ endif HAVE_PERL
538efe
 if HAVE_PYTHON
538efe
 
538efe
 TESTS += \
538efe
+	test-python.sh \
538efe
 	test-python-exception.sh \
538efe
 	test-shebang-python.sh \
538efe
 	$(NULL)
538efe
-LIBGUESTFS_TESTS += test-python
538efe
-
538efe
-test_python_SOURCES = test-lang-plugins.c test.h
538efe
-test_python_CFLAGS = \
538efe
-	-DLANG='"python"' -DSCRIPT='"$(srcdir)/test.py"' \
538efe
-	$(WARNINGS_CFLAGS) \
538efe
-	$(LIBGUESTFS_CFLAGS) \
538efe
-	$(NULL)
538efe
-test_python_LDADD = libtest.la $(LIBGUESTFS_LIBS)
538efe
 
538efe
 endif HAVE_PYTHON
538efe
 
538efe
diff --git a/tests/test-lang-plugins.c b/tests/test-lang-plugins.c
538efe
index ffb19180..93f99381 100644
538efe
--- a/tests/test-lang-plugins.c
538efe
+++ b/tests/test-lang-plugins.c
538efe
@@ -56,8 +56,7 @@ main (int argc, char *argv[])
538efe
    */
538efe
   s = getenv ("NBDKIT_VALGRIND");
538efe
   if (s && strcmp (s, "1") == 0 &&
538efe
-      (strcmp (LANG, "python") == 0 ||
538efe
-       strcmp (LANG, "ruby") == 0 ||
538efe
+      (strcmp (LANG, "ruby") == 0 ||
538efe
        strcmp (LANG, "tcl") == 0)) {
538efe
     fprintf (stderr, "%s test skipped under valgrind.\n", LANG);
538efe
     exit (77);                  /* Tells automake to skip the test. */
538efe
diff --git a/tests/test-python-plugin.py b/tests/test-python-plugin.py
538efe
new file mode 100644
538efe
index 00000000..8e90bc23
538efe
--- /dev/null
538efe
+++ b/tests/test-python-plugin.py
538efe
@@ -0,0 +1,133 @@
538efe
+# nbdkit test plugin
538efe
+# Copyright (C) 2019 Red Hat Inc.
538efe
+#
538efe
+# Redistribution and use in source and binary forms, with or without
538efe
+# modification, are permitted provided that the following conditions are
538efe
+# met:
538efe
+#
538efe
+# * Redistributions of source code must retain the above copyright
538efe
+# notice, this list of conditions and the following disclaimer.
538efe
+#
538efe
+# * Redistributions in binary form must reproduce the above copyright
538efe
+# notice, this list of conditions and the following disclaimer in the
538efe
+# documentation and/or other materials provided with the distribution.
538efe
+#
538efe
+# * Neither the name of Red Hat nor the names of its contributors may be
538efe
+# used to endorse or promote products derived from this software without
538efe
+# specific prior written permission.
538efe
+#
538efe
+# THIS SOFTWARE IS PROVIDED BY RED HAT AND CONTRIBUTORS ''AS IS'' AND
538efe
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
538efe
+# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
538efe
+# PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL RED HAT OR
538efe
+# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
538efe
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
538efe
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
538efe
+# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
538efe
+# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
538efe
+# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
538efe
+# OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
538efe
+# SUCH DAMAGE.
538efe
+
538efe
+"""See test-python.py."""
538efe
+
538efe
+import nbdkit
538efe
+import sys
538efe
+import pickle
538efe
+import base64
538efe
+
538efe
+API_VERSION = 2
538efe
+
538efe
+cfg = {}
538efe
+
538efe
+def config (k, v):
538efe
+    global cfg
538efe
+    if k == "cfg":
538efe
+        cfg = pickle.loads (base64.b64decode (v.encode()))
538efe
+
538efe
+def config_complete ():
538efe
+    print ("set_error = %r" % nbdkit.set_error)
538efe
+
538efe
+def open (readonly):
538efe
+    return {
538efe
+        'disk': bytearray (cfg.get ('size', 0))
538efe
+    }
538efe
+
538efe
+def get_size (h):
538efe
+    return len (h['disk'])
538efe
+
538efe
+def is_rotational (h):
538efe
+    return cfg.get ('is_rotational', False)
538efe
+
538efe
+def can_multi_conn (h):
538efe
+    return cfg.get ('can_multi_conn', False)
538efe
+
538efe
+def can_write (h):
538efe
+    return cfg.get ('can_write', True)
538efe
+
538efe
+def can_flush (h):
538efe
+    return cfg.get ('can_flush', False)
538efe
+
538efe
+def can_trim (h):
538efe
+    return cfg.get ('can_trim', False)
538efe
+
538efe
+def can_zero (h):
538efe
+    return cfg.get ('can_zero', False)
538efe
+
538efe
+def can_fast_zero (h):
538efe
+    return cfg.get ('can_fast_zero', False)
538efe
+
538efe
+def can_fua (h):
538efe
+    fua = cfg.get ('can_fua', "none")
538efe
+    if fua == "none":
538efe
+        return nbdkit.FUA_NONE
538efe
+    elif fua == "emulate":
538efe
+        return nbdkit.FUA_EMULATE
538efe
+    elif fua == "native":
538efe
+        return nbdkit.FUA_NATIVE
538efe
+
538efe
+def can_cache (h):
538efe
+    cache = cfg.get ('can_cache', "none")
538efe
+    if cache == "none":
538efe
+        return nbdkit.CACHE_NONE
538efe
+    elif cache == "emulate":
538efe
+        return nbdkit.CACHE_EMULATE
538efe
+    elif cache == "native":
538efe
+        return nbdkit.CACHE_NATIVE
538efe
+
538efe
+def pread (h, buf, offset, flags):
538efe
+    assert flags == 0
538efe
+    end = offset + len(buf)
538efe
+    buf[:] = h['disk'][offset:end]
538efe
+
538efe
+def pwrite (h, buf, offset, flags):
538efe
+    expect_fua = cfg.get ('pwrite_expect_fua', False)
538efe
+    actual_fua = bool (flags & nbdkit.FLAG_FUA)
538efe
+    assert expect_fua == actual_fua
538efe
+    end = offset + len(buf)
538efe
+    h['disk'][offset:end] = buf
538efe
+
538efe
+def flush (h, flags):
538efe
+    assert flags == 0
538efe
+
538efe
+def trim (h, count, offset, flags):
538efe
+    expect_fua = cfg.get ('trim_expect_fua', False)
538efe
+    actual_fua = bool (flags & nbdkit.FLAG_FUA)
538efe
+    assert expect_fua == actual_fua
538efe
+    h['disk'][offset:offset+count] = bytearray(count)
538efe
+
538efe
+def zero (h, count, offset, flags):
538efe
+    expect_fua = cfg.get ('zero_expect_fua', False)
538efe
+    actual_fua = bool (flags & nbdkit.FLAG_FUA)
538efe
+    assert expect_fua == actual_fua
538efe
+    expect_may_trim = cfg.get ('zero_expect_may_trim', False)
538efe
+    actual_may_trim = bool (flags & nbdkit.FLAG_MAY_TRIM)
538efe
+    assert expect_may_trim == actual_may_trim
538efe
+    expect_fast_zero = cfg.get ('zero_expect_fast_zero', False)
538efe
+    actual_fast_zero = bool (flags & nbdkit.FLAG_FAST_ZERO)
538efe
+    assert expect_fast_zero == actual_fast_zero
538efe
+    h['disk'][offset:offset+count] = bytearray(count)
538efe
+
538efe
+def cache (h, count, offset, flags):
538efe
+    assert flags == 0
538efe
+    # do nothing
538efe
diff --git a/tests/test-python.sh b/tests/test-python.sh
538efe
new file mode 100755
538efe
index 00000000..50324d0f
538efe
--- /dev/null
538efe
+++ b/tests/test-python.sh
538efe
@@ -0,0 +1,49 @@
538efe
+#!/usr/bin/env bash
538efe
+# nbdkit
538efe
+# Copyright (C) 2019 Red Hat Inc.
538efe
+#
538efe
+# Redistribution and use in source and binary forms, with or without
538efe
+# modification, are permitted provided that the following conditions are
538efe
+# met:
538efe
+#
538efe
+# * Redistributions of source code must retain the above copyright
538efe
+# notice, this list of conditions and the following disclaimer.
538efe
+#
538efe
+# * Redistributions in binary form must reproduce the above copyright
538efe
+# notice, this list of conditions and the following disclaimer in the
538efe
+# documentation and/or other materials provided with the distribution.
538efe
+#
538efe
+# * Neither the name of Red Hat nor the names of its contributors may be
538efe
+# used to endorse or promote products derived from this software without
538efe
+# specific prior written permission.
538efe
+#
538efe
+# THIS SOFTWARE IS PROVIDED BY RED HAT AND CONTRIBUTORS ''AS IS'' AND
538efe
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
538efe
+# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
538efe
+# PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL RED HAT OR
538efe
+# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
538efe
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
538efe
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
538efe
+# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
538efe
+# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
538efe
+# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
538efe
+# OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
538efe
+# SUCH DAMAGE.
538efe
+
538efe
+source ./functions.sh
538efe
+set -e
538efe
+set -x
538efe
+
538efe
+requires $PYTHON --version
538efe
+requires $PYTHON -c 'import unittest'
538efe
+requires $PYTHON -c 'import nbd'
538efe
+requires test -f test_python.py
538efe
+requires test -f test-python-plugin.py
538efe
+
538efe
+# Python has proven very difficult to valgrind, therefore it is disabled.
538efe
+if [ "$NBDKIT_VALGRIND" = "1" ]; then
538efe
+    echo "$0: skipping Python test under valgrind."
538efe
+    exit 77
538efe
+fi
538efe
+
538efe
+$PYTHON -m unittest test_python
538efe
diff --git a/tests/test.py b/tests/test.py
538efe
deleted file mode 100644
538efe
index 4db56623..00000000
538efe
--- a/tests/test.py
538efe
+++ /dev/null
538efe
@@ -1,60 +0,0 @@
538efe
-import nbdkit
538efe
-
538efe
-disk = bytearray(1024*1024)
538efe
-
538efe
-
538efe
-API_VERSION = 2
538efe
-
538efe
-
538efe
-def config_complete():
538efe
-    print ("set_error = %r" % nbdkit.set_error)
538efe
-
538efe
-
538efe
-def open(readonly):
538efe
-    return 1
538efe
-
538efe
-
538efe
-def get_size(h):
538efe
-    global disk
538efe
-    return len(disk)
538efe
-
538efe
-
538efe
-def can_write(h):
538efe
-    return True
538efe
-
538efe
-
538efe
-def can_flush(h):
538efe
-    return True
538efe
-
538efe
-
538efe
-def is_rotational(h):
538efe
-    return False
538efe
-
538efe
-
538efe
-def can_trim(h):
538efe
-    return True
538efe
-
538efe
-
538efe
-def pread(h, buf, offset, flags):
538efe
-    global disk
538efe
-    end = offset + len(buf)
538efe
-    buf[:] = disk[offset:end]
538efe
-
538efe
-
538efe
-def pwrite(h, buf, offset, flags):
538efe
-    global disk
538efe
-    end = offset + len(buf)
538efe
-    disk[offset:end] = buf
538efe
-
538efe
-
538efe
-def flush(h, flags):
538efe
-    pass
538efe
-
538efe
-
538efe
-def trim(h, count, offset, flags):
538efe
-    pass
538efe
-
538efe
-
538efe
-def zero(h, count, offset, flags):
538efe
-    global disk
538efe
-    disk[offset:offset+count] = bytearray(count)
538efe
diff --git a/tests/test_python.py b/tests/test_python.py
538efe
new file mode 100755
538efe
index 00000000..6b9f2979
538efe
--- /dev/null
538efe
+++ b/tests/test_python.py
538efe
@@ -0,0 +1,222 @@
538efe
+#!/usr/bin/env python3
538efe
+# nbdkit
538efe
+# Copyright (C) 2019 Red Hat Inc.
538efe
+#
538efe
+# Redistribution and use in source and binary forms, with or without
538efe
+# modification, are permitted provided that the following conditions are
538efe
+# met:
538efe
+#
538efe
+# * Redistributions of source code must retain the above copyright
538efe
+# notice, this list of conditions and the following disclaimer.
538efe
+#
538efe
+# * Redistributions in binary form must reproduce the above copyright
538efe
+# notice, this list of conditions and the following disclaimer in the
538efe
+# documentation and/or other materials provided with the distribution.
538efe
+#
538efe
+# * Neither the name of Red Hat nor the names of its contributors may be
538efe
+# used to endorse or promote products derived from this software without
538efe
+# specific prior written permission.
538efe
+#
538efe
+# THIS SOFTWARE IS PROVIDED BY RED HAT AND CONTRIBUTORS ''AS IS'' AND
538efe
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
538efe
+# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
538efe
+# PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL RED HAT OR
538efe
+# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
538efe
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
538efe
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
538efe
+# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
538efe
+# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
538efe
+# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
538efe
+# OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
538efe
+# SUCH DAMAGE.
538efe
+
538efe
+"""
538efe
+This tests the Python plugin thoroughly by issuing client commands
538efe
+through libnbd and checking we get the expected results.  It uses an
538efe
+associated plugin (test-python-plugin.sh).
538efe
+"""
538efe
+
538efe
+import os
538efe
+import sys
538efe
+import nbd
538efe
+import unittest
538efe
+import pickle
538efe
+import base64
538efe
+
538efe
+class Test (unittest.TestCase):
538efe
+    def setUp (self):
538efe
+        self.h = nbd.NBD ()
538efe
+
538efe
+    def tearDown (self):
538efe
+        del self.h
538efe
+
538efe
+    def connect (self, cfg):
538efe
+        cfg = base64.b64encode (pickle.dumps (cfg)).decode()
538efe
+        cmd = ["nbdkit", "-v", "-s", "--exit-with-parent",
538efe
+               "python", "test-python-plugin.py", "cfg=" + cfg]
538efe
+        self.h.connect_command (cmd)
538efe
+
538efe
+    def test_none (self):
538efe
+        """
538efe
+        Test we can send an empty pickled test configuration and do
538efe
+        nothing else.  This is just to ensure the machinery of the
538efe
+        test works.
538efe
+        """
538efe
+        self.connect ({})
538efe
+
538efe
+    def test_size_512 (self):
538efe
+        """Test the size."""
538efe
+        self.connect ({"size": 512})
538efe
+        assert self.h.get_size() == 512
538efe
+
538efe
+    def test_size_1m (self):
538efe
+        """Test the size."""
538efe
+        self.connect ({"size": 1024*1024})
538efe
+        assert self.h.get_size() == 1024*1024
538efe
+
538efe
+    # Test each flag call.
538efe
+    def test_is_rotational_true (self):
538efe
+        self.connect ({"size": 512, "is_rotational": True})
538efe
+        assert self.h.is_rotational()
538efe
+
538efe
+    def test_is_rotational_false (self):
538efe
+        self.connect ({"size": 512, "is_rotational": False})
538efe
+        assert not self.h.is_rotational()
538efe
+
538efe
+    def test_can_multi_conn_true (self):
538efe
+        self.connect ({"size": 512, "can_multi_conn": True})
538efe
+        assert self.h.can_multi_conn()
538efe
+
538efe
+    def test_can_multi_conn_false (self):
538efe
+        self.connect ({"size": 512, "can_multi_conn": False})
538efe
+        assert not self.h.can_multi_conn()
538efe
+
538efe
+    def test_read_write (self):
538efe
+        self.connect ({"size": 512, "can_write": True})
538efe
+        assert not self.h.is_read_only()
538efe
+
538efe
+    def test_read_only (self):
538efe
+        self.connect ({"size": 512, "can_write": False})
538efe
+        assert self.h.is_read_only()
538efe
+
538efe
+    def test_can_flush_true (self):
538efe
+        self.connect ({"size": 512, "can_flush": True})
538efe
+        assert self.h.can_flush()
538efe
+
538efe
+    def test_can_flush_false (self):
538efe
+        self.connect ({"size": 512, "can_flush": False})
538efe
+        assert not self.h.can_flush()
538efe
+
538efe
+    def test_can_trim_true (self):
538efe
+        self.connect ({"size": 512, "can_trim": True})
538efe
+        assert self.h.can_trim()
538efe
+
538efe
+    def test_can_trim_false (self):
538efe
+        self.connect ({"size": 512, "can_trim": False})
538efe
+        assert not self.h.can_trim()
538efe
+
538efe
+    # nbdkit can always zero because it emulates it.
538efe
+    #self.connect ({"size": 512, "can_zero": True})
538efe
+    #assert self.h.can_zero()
538efe
+    #self.connect ({"size": 512, "can_zero": False})
538efe
+    #assert not self.h.can_zero()
538efe
+
538efe
+    def test_can_fast_zero_true (self):
538efe
+        self.connect ({"size": 512, "can_fast_zero": True})
538efe
+        assert self.h.can_fast_zero()
538efe
+
538efe
+    def test_can_fast_zero_false (self):
538efe
+        self.connect ({"size": 512, "can_fast_zero": False})
538efe
+        assert not self.h.can_fast_zero()
538efe
+
538efe
+    def test_can_fua_none (self):
538efe
+        self.connect ({"size": 512, "can_fua": "none"})
538efe
+        assert not self.h.can_fua()
538efe
+
538efe
+    def test_can_fua_emulate (self):
538efe
+        self.connect ({"size": 512, "can_fua": "emulate"})
538efe
+        assert self.h.can_fua()
538efe
+
538efe
+    def test_can_fua_native (self):
538efe
+        self.connect ({"size": 512, "can_fua": "native"})
538efe
+        assert self.h.can_fua()
538efe
+
538efe
+    def test_can_cache_none (self):
538efe
+        self.connect ({"size": 512, "can_cache": "none"})
538efe
+        assert not self.h.can_cache()
538efe
+
538efe
+    def test_can_cache_emulate (self):
538efe
+        self.connect ({"size": 512, "can_cache": "emulate"})
538efe
+        assert self.h.can_cache()
538efe
+
538efe
+    def test_can_cache_native (self):
538efe
+        self.connect ({"size": 512, "can_cache": "native"})
538efe
+        assert self.h.can_cache()
538efe
+
538efe
+    # Not yet implemented: can_extents.
538efe
+
538efe
+    def test_pread (self):
538efe
+        """Test pread."""
538efe
+        self.connect ({"size": 512})
538efe
+        buf = self.h.pread (512, 0)
538efe
+        assert buf == bytearray (512)
538efe
+
538efe
+    # Test pwrite + flags.
538efe
+    def test_pwrite (self):
538efe
+        self.connect ({"size": 512})
538efe
+        buf = bytearray (512)
538efe
+        self.h.pwrite (buf, 0)
538efe
+
538efe
+    def test_pwrite_fua (self):
538efe
+        self.connect ({"size": 512,
538efe
+                       "can_fua": "native",
538efe
+                       "pwrite_expect_fua": True})
538efe
+        buf = bytearray (512)
538efe
+        self.h.pwrite (buf, 0, nbd.CMD_FLAG_FUA)
538efe
+
538efe
+    def test_flush (self):
538efe
+        """Test flush."""
538efe
+        self.connect ({"size": 512, "can_flush": True})
538efe
+        self.h.flush ()
538efe
+
538efe
+    # Test trim + flags.
538efe
+    def test_trim (self):
538efe
+        self.connect ({"size": 512, "can_trim": True})
538efe
+        self.h.trim (512, 0)
538efe
+
538efe
+    def test_trim_fua (self):
538efe
+        self.connect ({"size": 512,
538efe
+                       "can_trim": True,
538efe
+                       "can_fua": "native",
538efe
+                       "trim_expect_fua": True})
538efe
+        self.h.trim (512, 0, nbd.CMD_FLAG_FUA)
538efe
+
538efe
+    # Test zero + flags.
538efe
+    def test_zero (self):
538efe
+        self.connect ({"size": 512, "can_zero": True})
538efe
+        self.h.zero (512, 0, nbd.CMD_FLAG_NO_HOLE)
538efe
+
538efe
+    def test_zero_fua (self):
538efe
+        self.connect ({"size": 512,
538efe
+                       "can_zero": True,
538efe
+                       "can_fua": "native",
538efe
+                       "zero_expect_fua": True})
538efe
+        self.h.zero (512, 0, nbd.CMD_FLAG_NO_HOLE | nbd.CMD_FLAG_FUA)
538efe
+
538efe
+    def test_zero_may_trim (self):
538efe
+        self.connect ({"size": 512,
538efe
+                       "can_zero": True,
538efe
+                       "zero_expect_may_trim": True})
538efe
+        self.h.zero (512, 0, 0) # absence of nbd.CMD_FLAG_NO_HOLE
538efe
+
538efe
+    def test_zero_fast_zero (self):
538efe
+        self.connect ({"size": 512,
538efe
+                       "can_zero": True,
538efe
+                       "can_fast_zero": True,
538efe
+                       "zero_expect_fast_zero": True})
538efe
+        self.h.zero (512, 0, nbd.CMD_FLAG_NO_HOLE | nbd.CMD_FLAG_FAST_ZERO)
538efe
+
538efe
+    def test_cache (self):
538efe
+        """Test cache."""
538efe
+        self.connect ({"size": 512, "can_cache": "native"})
538efe
+        self.h.cache (512, 0)
538efe
-- 
538efe
2.18.2
538efe