qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: Kevin Wolf <kwolf@redhat.com>
To: qemu-block@nongnu.org
Cc: kwolf@redhat.com, peter.maydell@linaro.org, qemu-devel@nongnu.org
Subject: [Qemu-devel] [PULL 20/41] iotests: test manual job dismissal
Date: Tue, 13 Mar 2018 17:17:42 +0100	[thread overview]
Message-ID: <20180313161803.1814-21-kwolf@redhat.com> (raw)
In-Reply-To: <20180313161803.1814-1-kwolf@redhat.com>

From: John Snow <jsnow@redhat.com>

Signed-off-by: John Snow <jsnow@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
 tests/qemu-iotests/056     | 187 +++++++++++++++++++++++++++++++++++++++++++++
 tests/qemu-iotests/056.out |   4 +-
 2 files changed, 189 insertions(+), 2 deletions(-)

diff --git a/tests/qemu-iotests/056 b/tests/qemu-iotests/056
index 04f2c3c841..223292175a 100755
--- a/tests/qemu-iotests/056
+++ b/tests/qemu-iotests/056
@@ -29,6 +29,26 @@ backing_img = os.path.join(iotests.test_dir, 'backing.img')
 test_img = os.path.join(iotests.test_dir, 'test.img')
 target_img = os.path.join(iotests.test_dir, 'target.img')
 
+def img_create(img, fmt=iotests.imgfmt, size='64M', **kwargs):
+    fullname = os.path.join(iotests.test_dir, '%s.%s' % (img, fmt))
+    optargs = []
+    for k,v in kwargs.iteritems():
+        optargs = optargs + ['-o', '%s=%s' % (k,v)]
+    args = ['create', '-f', fmt] + optargs + [fullname, size]
+    iotests.qemu_img(*args)
+    return fullname
+
+def try_remove(img):
+    try:
+        os.remove(img)
+    except OSError:
+        pass
+
+def io_write_patterns(img, patterns):
+    for pattern in patterns:
+        iotests.qemu_io('-c', 'write -P%s %s %s' % pattern, img)
+
+
 class TestSyncModesNoneAndTop(iotests.QMPTestCase):
     image_len = 64 * 1024 * 1024 # MB
 
@@ -108,5 +128,172 @@ class TestBeforeWriteNotifier(iotests.QMPTestCase):
         event = self.cancel_and_wait()
         self.assert_qmp(event, 'data/type', 'backup')
 
+class BackupTest(iotests.QMPTestCase):
+    def setUp(self):
+        self.vm = iotests.VM()
+        self.test_img = img_create('test')
+        self.dest_img = img_create('dest')
+        self.vm.add_drive(self.test_img)
+        self.vm.launch()
+
+    def tearDown(self):
+        self.vm.shutdown()
+        try_remove(self.test_img)
+        try_remove(self.dest_img)
+
+    def hmp_io_writes(self, drive, patterns):
+        for pattern in patterns:
+            self.vm.hmp_qemu_io(drive, 'write -P%s %s %s' % pattern)
+        self.vm.hmp_qemu_io(drive, 'flush')
+
+    def qmp_backup_and_wait(self, cmd='drive-backup', serror=None,
+                            aerror=None, **kwargs):
+        if not self.qmp_backup(cmd, serror, **kwargs):
+            return False
+        return self.qmp_backup_wait(kwargs['device'], aerror)
+
+    def qmp_backup(self, cmd='drive-backup',
+                   error=None, **kwargs):
+        self.assertTrue('device' in kwargs)
+        res = self.vm.qmp(cmd, **kwargs)
+        if error:
+            self.assert_qmp(res, 'error/desc', error)
+            return False
+        self.assert_qmp(res, 'return', {})
+        return True
+
+    def qmp_backup_wait(self, device, error=None):
+        event = self.vm.event_wait(name="BLOCK_JOB_COMPLETED",
+                                   match={'data': {'device': device}})
+        self.assertNotEqual(event, None)
+        try:
+            failure = self.dictpath(event, 'data/error')
+        except AssertionError:
+            # Backup succeeded.
+            self.assert_qmp(event, 'data/offset', event['data']['len'])
+            return True
+        else:
+            # Failure.
+            self.assert_qmp(event, 'data/error', qerror)
+            return False
+
+    def test_dismiss_false(self):
+        res = self.vm.qmp('query-block-jobs')
+        self.assert_qmp(res, 'return', [])
+        self.qmp_backup_and_wait(device='drive0', format=iotests.imgfmt,
+                                 sync='full', target=self.dest_img,
+                                 auto_dismiss=True)
+        res = self.vm.qmp('query-block-jobs')
+        self.assert_qmp(res, 'return', [])
+
+    def test_dismiss_true(self):
+        res = self.vm.qmp('query-block-jobs')
+        self.assert_qmp(res, 'return', [])
+        self.qmp_backup_and_wait(device='drive0', format=iotests.imgfmt,
+                                 sync='full', target=self.dest_img,
+                                 auto_dismiss=False)
+        res = self.vm.qmp('query-block-jobs')
+        self.assert_qmp(res, 'return[0]/status', 'concluded')
+        res = self.vm.qmp('block-job-dismiss', id='drive0')
+        self.assert_qmp(res, 'return', {})
+        res = self.vm.qmp('query-block-jobs')
+        self.assert_qmp(res, 'return', [])
+
+    def test_dismiss_bad_id(self):
+        res = self.vm.qmp('query-block-jobs')
+        self.assert_qmp(res, 'return', [])
+        res = self.vm.qmp('block-job-dismiss', id='foobar')
+        self.assert_qmp(res, 'error/class', 'DeviceNotActive')
+
+    def test_dismiss_collision(self):
+        res = self.vm.qmp('query-block-jobs')
+        self.assert_qmp(res, 'return', [])
+        self.qmp_backup_and_wait(device='drive0', format=iotests.imgfmt,
+                                 sync='full', target=self.dest_img,
+                                 auto_dismiss=False)
+        res = self.vm.qmp('query-block-jobs')
+        self.assert_qmp(res, 'return[0]/status', 'concluded')
+        # Leave zombie job un-dismissed, observe a failure:
+        res = self.qmp_backup_and_wait(serror='Need a root block node',
+                                       device='drive0', format=iotests.imgfmt,
+                                       sync='full', target=self.dest_img,
+                                       auto_dismiss=False)
+        self.assertEqual(res, False)
+        # OK, dismiss the zombie.
+        res = self.vm.qmp('block-job-dismiss', id='drive0')
+        self.assert_qmp(res, 'return', {})
+        res = self.vm.qmp('query-block-jobs')
+        self.assert_qmp(res, 'return', [])
+        # Ensure it's really gone.
+        self.qmp_backup_and_wait(device='drive0', format=iotests.imgfmt,
+                                 sync='full', target=self.dest_img,
+                                 auto_dismiss=False)
+
+    def dismissal_failure(self, dismissal_opt):
+        res = self.vm.qmp('query-block-jobs')
+        self.assert_qmp(res, 'return', [])
+        # Give blkdebug something to chew on
+        self.hmp_io_writes('drive0',
+                           (('0x9a', 0, 512),
+                           ('0x55', '8M', '352k'),
+                           ('0x78', '15872k', '1M')))
+        # Add destination node via blkdebug
+        res = self.vm.qmp('blockdev-add',
+                          node_name='target0',
+                          driver=iotests.imgfmt,
+                          file={
+                              'driver': 'blkdebug',
+                              'image': {
+                                  'driver': 'file',
+                                  'filename': self.dest_img
+                              },
+                              'inject-error': [{
+                                  'event': 'write_aio',
+                                  'errno': 5,
+                                  'immediately': False,
+                                  'once': True
+                              }],
+                          })
+        self.assert_qmp(res, 'return', {})
+
+        res = self.qmp_backup(cmd='blockdev-backup',
+                              device='drive0', target='target0',
+                              on_target_error='stop',
+                              sync='full',
+                              auto_dismiss=dismissal_opt)
+        self.assertTrue(res)
+        event = self.vm.event_wait(name="BLOCK_JOB_ERROR",
+                                   match={'data': {'device': 'drive0'}})
+        self.assertNotEqual(event, None)
+        # OK, job should be wedged
+        res = self.vm.qmp('query-block-jobs')
+        self.assert_qmp(res, 'return[0]/status', 'paused')
+        res = self.vm.qmp('block-job-dismiss', id='drive0')
+        self.assert_qmp(res, 'error/desc',
+                        "Job 'drive0' in state 'paused' cannot accept"
+                        " command verb 'dismiss'")
+        res = self.vm.qmp('query-block-jobs')
+        self.assert_qmp(res, 'return[0]/status', 'paused')
+        # OK, unstick job and move forward.
+        res = self.vm.qmp('block-job-resume', device='drive0')
+        self.assert_qmp(res, 'return', {})
+        # And now we need to wait for it to conclude;
+        res = self.qmp_backup_wait(device='drive0')
+        self.assertTrue(res)
+        if not dismissal_opt:
+            # Job should now be languishing:
+            res = self.vm.qmp('query-block-jobs')
+            self.assert_qmp(res, 'return[0]/status', 'concluded')
+            res = self.vm.qmp('block-job-dismiss', id='drive0')
+            self.assert_qmp(res, 'return', {})
+            res = self.vm.qmp('query-block-jobs')
+            self.assert_qmp(res, 'return', [])
+
+    def test_dismiss_premature(self):
+        self.dismissal_failure(False)
+
+    def test_dismiss_erroneous(self):
+        self.dismissal_failure(True)
+
 if __name__ == '__main__':
     iotests.main(supported_fmts=['qcow2', 'qed'])
diff --git a/tests/qemu-iotests/056.out b/tests/qemu-iotests/056.out
index 8d7e996700..dae404e278 100644
--- a/tests/qemu-iotests/056.out
+++ b/tests/qemu-iotests/056.out
@@ -1,5 +1,5 @@
-...
+.........
 ----------------------------------------------------------------------
-Ran 3 tests
+Ran 9 tests
 
 OK
-- 
2.13.6

  parent reply	other threads:[~2018-03-13 16:18 UTC|newest]

Thread overview: 49+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-03-13 16:17 [Qemu-devel] [PULL 00/41] Block layer patches Kevin Wolf
2018-03-13 16:17 ` [Qemu-devel] [PULL 01/41] blockjobs: fix set-speed kick Kevin Wolf
2018-03-13 16:17 ` [Qemu-devel] [PULL 02/41] blockjobs: model single jobs as transactions Kevin Wolf
2018-03-13 16:17 ` [Qemu-devel] [PULL 03/41] Blockjobs: documentation touchup Kevin Wolf
2018-03-13 16:17 ` [Qemu-devel] [PULL 04/41] blockjobs: add status enum Kevin Wolf
2018-03-13 16:17 ` [Qemu-devel] [PULL 05/41] blockjobs: add state transition table Kevin Wolf
2018-03-13 16:17 ` [Qemu-devel] [PULL 06/41] iotests: add pause_wait Kevin Wolf
2018-03-13 16:17 ` [Qemu-devel] [PULL 07/41] blockjobs: add block_job_verb permission table Kevin Wolf
2018-03-13 16:17 ` [Qemu-devel] [PULL 08/41] blockjobs: add ABORTING state Kevin Wolf
2018-03-13 16:17 ` [Qemu-devel] [PULL 09/41] blockjobs: add CONCLUDED state Kevin Wolf
2018-03-13 16:17 ` [Qemu-devel] [PULL 10/41] blockjobs: add NULL state Kevin Wolf
2018-03-13 16:17 ` [Qemu-devel] [PULL 11/41] blockjobs: add block_job_dismiss Kevin Wolf
2018-03-13 16:17 ` [Qemu-devel] [PULL 12/41] blockjobs: ensure abort is called for cancelled jobs Kevin Wolf
2018-03-13 16:17 ` [Qemu-devel] [PULL 13/41] blockjobs: add commit, abort, clean helpers Kevin Wolf
2018-03-13 16:17 ` [Qemu-devel] [PULL 14/41] blockjobs: add block_job_txn_apply function Kevin Wolf
2018-03-13 16:17 ` [Qemu-devel] [PULL 15/41] blockjobs: add prepare callback Kevin Wolf
2018-03-13 16:17 ` [Qemu-devel] [PULL 16/41] blockjobs: add waiting status Kevin Wolf
2018-03-13 16:17 ` [Qemu-devel] [PULL 17/41] blockjobs: add PENDING status and event Kevin Wolf
2018-03-13 16:17 ` [Qemu-devel] [PULL 18/41] blockjobs: add block-job-finalize Kevin Wolf
2018-03-13 18:47   ` Eric Blake
2018-03-14 20:24     ` John Snow
2018-03-13 16:17 ` [Qemu-devel] [PULL 19/41] blockjobs: Expose manual property Kevin Wolf
2018-03-13 16:17 ` Kevin Wolf [this message]
2018-03-13 16:17 ` [Qemu-devel] [PULL 21/41] tests/test-blockjob: test cancellations Kevin Wolf
2018-03-13 16:17 ` [Qemu-devel] [PULL 22/41] luks: Separate image file creation from formatting Kevin Wolf
2018-03-13 16:17 ` [Qemu-devel] [PULL 23/41] luks: Create block_crypto_co_create_generic() Kevin Wolf
2018-03-13 16:17 ` [Qemu-devel] [PULL 24/41] luks: Support .bdrv_co_create Kevin Wolf
2018-03-13 16:17 ` [Qemu-devel] [PULL 25/41] luks: Turn invalid assertion into check Kevin Wolf
2018-03-13 16:17 ` [Qemu-devel] [PULL 26/41] luks: Catch integer overflow for huge sizes Kevin Wolf
2018-03-13 16:17 ` [Qemu-devel] [PULL 27/41] qemu-iotests: Test luks QMP image creation Kevin Wolf
2018-03-13 16:17 ` [Qemu-devel] [PULL 28/41] vdi: Pull option parsing from vdi_co_create Kevin Wolf
2018-03-13 16:17 ` [Qemu-devel] [PULL 29/41] vdi: Move file creation to vdi_co_create_opts Kevin Wolf
2018-03-13 16:17 ` [Qemu-devel] [PULL 30/41] vdi: Implement .bdrv_co_create Kevin Wolf
2018-03-13 16:17 ` [Qemu-devel] [PULL 31/41] block: Fix flags in reopen queue Kevin Wolf
2018-03-13 16:17 ` [Qemu-devel] [PULL 32/41] iotests: Add regression test for commit base locking Kevin Wolf
2018-03-13 16:17 ` [Qemu-devel] [PULL 33/41] parallels: Support .bdrv_co_create Kevin Wolf
2018-03-13 16:17 ` [Qemu-devel] [PULL 34/41] qemu-iotests: Enable write tests for parallels Kevin Wolf
2018-03-13 16:17 ` [Qemu-devel] [PULL 35/41] qcow: Support .bdrv_co_create Kevin Wolf
2018-03-13 16:17 ` [Qemu-devel] [PULL 36/41] qed: " Kevin Wolf
2018-03-13 16:17 ` [Qemu-devel] [PULL 37/41] vdi: Make comments consistent with other drivers Kevin Wolf
2018-03-13 16:18 ` [Qemu-devel] [PULL 38/41] vhdx: Support .bdrv_co_create Kevin Wolf
2018-03-13 16:18 ` [Qemu-devel] [PULL 39/41] vpc: " Kevin Wolf
2018-03-13 16:18 ` [Qemu-devel] [PULL 40/41] vpc: Require aligned size in .bdrv_co_create Kevin Wolf
2018-03-13 16:18 ` [Qemu-devel] [PULL 41/41] block/mirror: change the semantic of 'force' of block-job-cancel Kevin Wolf
2018-03-13 17:13 ` [Qemu-devel] [PULL 00/41] Block layer patches no-reply
2018-03-15 16:42 ` Peter Maydell
2018-03-15 16:56   ` Kevin Wolf
2018-03-15 17:55     ` John Snow
2018-03-16 12:44       ` Kevin Wolf

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20180313161803.1814-21-kwolf@redhat.com \
    --to=kwolf@redhat.com \
    --cc=peter.maydell@linaro.org \
    --cc=qemu-block@nongnu.org \
    --cc=qemu-devel@nongnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).