#!/usr/bin/env python3
# group: rw auto backing
#
# Tests for image streaming.
#
# Copyright (C) 2012 IBM Corp.
#
# 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, see <http://www.gnu.org/licenses/>.
#

import time
import os
import iotests
import unittest
from iotests import qemu_img, qemu_io

backing_img = os.path.join(iotests.test_dir, 'backing.img')
mid_img = os.path.join(iotests.test_dir, 'mid.img')
test_img = os.path.join(iotests.test_dir, 'test.img')

class TestSingleDrive(iotests.QMPTestCase):
    image_len = 1 * 1024 * 1024 # MB

    def setUp(self):
        iotests.create_image(backing_img, TestSingleDrive.image_len)
        qemu_img('create', '-f', iotests.imgfmt,
                 '-o', 'backing_file=%s' % backing_img,
                 '-F', 'raw', mid_img)
        qemu_img('create', '-f', iotests.imgfmt,
                 '-o', 'backing_file=%s' % mid_img,
                 '-F', iotests.imgfmt, test_img)
        qemu_io('-f', 'raw', '-c', 'write -P 0x1 0 512', backing_img)
        qemu_io('-f', iotests.imgfmt, '-c', 'write -P 0x1 524288 512', mid_img)
        self.vm = iotests.VM().add_drive("blkdebug::" + test_img,
                                         "backing.node-name=mid," +
                                         "backing.backing.node-name=base")
        self.vm.launch()

    def tearDown(self):
        self.vm.shutdown()
        os.remove(test_img)
        os.remove(mid_img)
        os.remove(backing_img)

    def test_stream(self):
        self.assert_no_active_block_jobs()

        result = self.vm.qmp('block-stream', device='drive0')
        self.assert_qmp(result, 'return', {})

        self.wait_until_completed()

        self.assert_no_active_block_jobs()
        self.vm.shutdown()

        self.assertEqual(qemu_io('-f', 'raw', '-c', 'map', backing_img),
                         qemu_io('-f', iotests.imgfmt, '-c', 'map', test_img),
                         'image file map does not match backing file after streaming')

    def test_stream_intermediate(self):
        self.assert_no_active_block_jobs()

        self.assertNotEqual(qemu_io('-f', 'raw', '-rU', '-c', 'map', backing_img),
                            qemu_io('-f', iotests.imgfmt, '-rU', '-c', 'map', mid_img),
                            'image file map matches backing file before streaming')

        result = self.vm.qmp('block-stream', device='mid', job_id='stream-mid')
        self.assert_qmp(result, 'return', {})

        self.wait_until_completed(drive='stream-mid')

        self.assert_no_active_block_jobs()
        self.vm.shutdown()

        self.assertEqual(qemu_io('-f', 'raw', '-c', 'map', backing_img),
                         qemu_io('-f', iotests.imgfmt, '-c', 'map', mid_img),
                         'image file map does not match backing file after streaming')

    def test_stream_pause(self):
        self.assert_no_active_block_jobs()

        self.vm.pause_drive('drive0')
        result = self.vm.qmp('block-stream', device='drive0')
        self.assert_qmp(result, 'return', {})

        self.pause_job('drive0', wait=False)
        self.vm.resume_drive('drive0')
        self.pause_wait('drive0')

        result = self.vm.qmp('query-block-jobs')
        offset = self.dictpath(result, 'return[0]/offset')

        time.sleep(0.5)
        result = self.vm.qmp('query-block-jobs')
        self.assert_qmp(result, 'return[0]/offset', offset)

        result = self.vm.qmp('block-job-resume', device='drive0')
        self.assert_qmp(result, 'return', {})

        self.wait_until_completed()

        self.assert_no_active_block_jobs()
        self.vm.shutdown()

        self.assertEqual(qemu_io('-f', 'raw', '-c', 'map', backing_img),
                         qemu_io('-f', iotests.imgfmt, '-c', 'map', test_img),
                         'image file map does not match backing file after streaming')

    def test_stream_no_op(self):
        self.assert_no_active_block_jobs()

        # The image map is empty before the operation
        empty_map = qemu_io('-f', iotests.imgfmt, '-rU', '-c', 'map', test_img)

        # This is a no-op: no data should ever be copied from the base image
        result = self.vm.qmp('block-stream', device='drive0', base=mid_img)
        self.assert_qmp(result, 'return', {})

        self.wait_until_completed()

        self.assert_no_active_block_jobs()
        self.vm.shutdown()

        self.assertEqual(qemu_io('-f', iotests.imgfmt, '-c', 'map', test_img),
                         empty_map, 'image file map changed after a no-op')

    def test_stream_partial(self):
        self.assert_no_active_block_jobs()

        result = self.vm.qmp('block-stream', device='drive0', base=backing_img)
        self.assert_qmp(result, 'return', {})

        self.wait_until_completed()

        self.assert_no_active_block_jobs()
        self.vm.shutdown()

        self.assertEqual(qemu_io('-f', iotests.imgfmt, '-c', 'map', mid_img),
                         qemu_io('-f', iotests.imgfmt, '-c', 'map', test_img),
                         'image file map does not match backing file after streaming')

    def test_device_not_found(self):
        result = self.vm.qmp('block-stream', device='nonexistent')
        self.assert_qmp(result, 'error/desc',
            'Cannot find device=nonexistent nor node_name=nonexistent')

    def test_job_id_missing(self):
        result = self.vm.qmp('block-stream', device='mid')
        self.assert_qmp(result, 'error/desc', "Invalid job ID ''")

    def test_read_only(self):
        # Create a new file that we can attach (we need a read-only top)
        with iotests.FilePath('ro-top.img') as ro_top_path:
            qemu_img('create', '-f', iotests.imgfmt, ro_top_path,
                     str(self.image_len))

            result = self.vm.qmp('blockdev-add',
                                 node_name='ro-top',
                                 driver=iotests.imgfmt,
                                 read_only=True,
                                 file={
                                     'driver': 'file',
                                     'filename': ro_top_path,
                                     'read-only': True
                                 },
                                 backing='mid')
            self.assert_qmp(result, 'return', {})

            result = self.vm.qmp('block-stream', job_id='stream',
                                 device='ro-top', base_node='base')
            self.assert_qmp(result, 'error/desc', 'Block node is read-only')

            result = self.vm.qmp('blockdev-del', node_name='ro-top')
            self.assert_qmp(result, 'return', {})


class TestParallelOps(iotests.QMPTestCase):
    num_ops = 4 # Number of parallel block-stream operations
    num_imgs = num_ops * 2 + 1
    image_len = num_ops * 4 * 1024 * 1024
    imgs = []

    def setUp(self):
        opts = []
        self.imgs = []

        # Initialize file names and command-line options
        for i in range(self.num_imgs):
            img_depth = self.num_imgs - i - 1
            opts.append("backing." * img_depth + "node-name=node%d" % i)
            self.imgs.append(os.path.join(iotests.test_dir, 'img-%d.img' % i))

        # Create all images
        iotests.create_image(self.imgs[0], self.image_len)
        for i in range(1, self.num_imgs):
            qemu_img('create', '-f', iotests.imgfmt,
                     '-o', 'backing_file=%s' % self.imgs[i-1],
                     '-F', 'raw' if i == 1 else iotests.imgfmt, self.imgs[i])

        # Put data into the images we are copying data from
        odd_img_indexes = [x for x in reversed(range(self.num_imgs)) if x % 2 == 1]
        for i in range(len(odd_img_indexes)):
            # Alternate between 2MB and 4MB.
            # This way jobs will not finish in the same order they were created
            num_mb = 2 + 2 * (i % 2)
            qemu_io('-f', iotests.imgfmt,
                    '-c', 'write -P 0xFF %dM %dM' % (i * 4, num_mb),
                    self.imgs[odd_img_indexes[i]])

        # Attach the drive to the VM
        self.vm = iotests.VM()
        self.vm.add_drive(self.imgs[-1], ','.join(opts))
        self.vm.launch()

    def tearDown(self):
        self.vm.shutdown()
        for img in self.imgs:
            os.remove(img)

    # Test that it's possible to run several block-stream operations
    # in parallel in the same snapshot chain
    @unittest.skipIf(os.environ.get('QEMU_CHECK_BLOCK_AUTO'), 'disabled in CI')
    def test_stream_parallel(self):
        self.assert_no_active_block_jobs()

        # Check that the maps don't match before the streaming operations
        for i in range(2, self.num_imgs, 2):
            self.assertNotEqual(qemu_io('-f', iotests.imgfmt, '-rU', '-c', 'map', self.imgs[i]),
                                qemu_io('-f', iotests.imgfmt, '-rU', '-c', 'map', self.imgs[i-1]),
                                'image file map matches backing file before streaming')

        # Create all streaming jobs
        pending_jobs = []
        for i in range(2, self.num_imgs, 2):
            node_name = 'node%d' % i
            job_id = 'stream-%s' % node_name
            pending_jobs.append(job_id)
            result = self.vm.qmp('block-stream', device=node_name, job_id=job_id, base=self.imgs[i-2], speed=1024)
            self.assert_qmp(result, 'return', {})

        for job in pending_jobs:
            result = self.vm.qmp('block-job-set-speed', device=job, speed=0)
            self.assert_qmp(result, 'return', {})

        # Wait for all jobs to be finished.
        while len(pending_jobs) > 0:
            for event in self.vm.get_qmp_events(wait=True):
                if event['event'] == 'BLOCK_JOB_COMPLETED':
                    job_id = self.dictpath(event, 'data/device')
                    self.assertTrue(job_id in pending_jobs)
                    self.assert_qmp_absent(event, 'data/error')
                    pending_jobs.remove(job_id)

        self.assert_no_active_block_jobs()
        self.vm.shutdown()

        # Check that all maps match now
        for i in range(2, self.num_imgs, 2):
            self.assertEqual(qemu_io('-f', iotests.imgfmt, '-c', 'map', self.imgs[i]),
                             qemu_io('-f', iotests.imgfmt, '-c', 'map', self.imgs[i-1]),
                             'image file map does not match backing file after streaming')

    # Test that it's not possible to perform two block-stream
    # operations if there are nodes involved in both.
    def test_overlapping_1(self):
        self.assert_no_active_block_jobs()

        # Set a speed limit to make sure that this job blocks the rest
        result = self.vm.qmp('block-stream', device='node4', job_id='stream-node4', base=self.imgs[1], speed=1024*1024)
        self.assert_qmp(result, 'return', {})

        result = self.vm.qmp('block-stream', device='node5', job_id='stream-node5', base=self.imgs[2])
        self.assert_qmp(result, 'error/desc',
            "Node 'node4' is busy: block device is in use by block job: stream")

        result = self.vm.qmp('block-stream', device='node3', job_id='stream-node3', base=self.imgs[2])
        self.assert_qmp(result, 'error/desc',
            "Node 'node3' is busy: block device is in use by block job: stream")

        result = self.vm.qmp('block-stream', device='node4', job_id='stream-node4-v2')
        self.assert_qmp(result, 'error/desc',
            "Node 'node4' is busy: block device is in use by block job: stream")

        # block-commit should also fail if it touches nodes used by the stream job
        result = self.vm.qmp('block-commit', device='drive0', base=self.imgs[4], job_id='commit-node4')
        self.assert_qmp(result, 'error/desc',
            "Node 'node4' is busy: block device is in use by block job: stream")

        result = self.vm.qmp('block-commit', device='drive0', base=self.imgs[1], top=self.imgs[3], job_id='commit-node1')
        self.assert_qmp(result, 'error/desc',
            "Node 'node3' is busy: block device is in use by block job: stream")

        # This fails because it needs to modify the backing string in node2, which is blocked
        result = self.vm.qmp('block-commit', device='drive0', base=self.imgs[0], top=self.imgs[1], job_id='commit-node0')
        self.assert_qmp(result, 'error/desc',
            "Node 'node2' is busy: block device is in use by block job: stream")

        result = self.vm.qmp('block-job-set-speed', device='stream-node4', speed=0)
        self.assert_qmp(result, 'return', {})

        self.wait_until_completed(drive='stream-node4')
        self.assert_no_active_block_jobs()

    # Similar to test_overlapping_1, but with block-commit
    # blocking the other jobs
    def test_overlapping_2(self):
        self.assertLessEqual(9, self.num_imgs)
        self.assert_no_active_block_jobs()

        # Set a speed limit to make sure that this job blocks the rest
        result = self.vm.qmp('block-commit', device='drive0', top=self.imgs[5], base=self.imgs[3], job_id='commit-node3', speed=1024*1024)
        self.assert_qmp(result, 'return', {})

        result = self.vm.qmp('block-stream', device='node3', job_id='stream-node3')
        self.assert_qmp(result, 'error/desc',
            "Node 'node3' is busy: block device is in use by block job: commit")

        result = self.vm.qmp('block-stream', device='node6', base=self.imgs[2], job_id='stream-node6')
        self.assert_qmp(result, 'error/desc',
            "Node 'node5' is busy: block device is in use by block job: commit")

        result = self.vm.qmp('block-stream', device='node4', base=self.imgs[2], job_id='stream-node4')
        self.assert_qmp(result, 'error/desc',
            "Node 'node4' is busy: block device is in use by block job: commit")

        result = self.vm.qmp('block-stream', device='node6', base=self.imgs[4], job_id='stream-node6-v2')
        self.assert_qmp(result, 'error/desc',
            "Node 'node5' is busy: block device is in use by block job: commit")

        # This fails because block-commit currently blocks the active layer even if it's not used
        result = self.vm.qmp('block-stream', device='drive0', base=self.imgs[5], job_id='stream-drive0')
        self.assert_qmp(result, 'error/desc',
            "Node 'drive0' is busy: block device is in use by block job: commit")

        result = self.vm.qmp('block-job-set-speed', device='commit-node3', speed=0)
        self.assert_qmp(result, 'return', {})

        self.wait_until_completed(drive='commit-node3')

    # Similar to test_overlapping_2, but here block-commit doesn't use the 'top' parameter.
    # Internally this uses a mirror block job, hence the separate test case.
    def test_overlapping_3(self):
        self.assertLessEqual(8, self.num_imgs)
        self.assert_no_active_block_jobs()

        # Set a speed limit to make sure that this job blocks the rest
        result = self.vm.qmp('block-commit', device='drive0', base=self.imgs[3], job_id='commit-drive0', speed=1024*1024)
        self.assert_qmp(result, 'return', {})

        result = self.vm.qmp('block-stream', device='node5', base=self.imgs[3], job_id='stream-node6')
        self.assert_qmp(result, 'error/desc',
            "Node 'node5' is busy: block device is in use by block job: commit")

        result = self.vm.qmp('block-job-set-speed', device='commit-drive0', speed=0)
        self.assert_qmp(result, 'return', {})

        event = self.vm.event_wait(name='BLOCK_JOB_READY')
        self.assert_qmp(event, 'data/device', 'commit-drive0')
        self.assert_qmp(event, 'data/type', 'commit')
        self.assert_qmp_absent(event, 'data/error')

        result = self.vm.qmp('block-job-complete', device='commit-drive0')
        self.assert_qmp(result, 'return', {})

        self.wait_until_completed(drive='commit-drive0')

    # In this case the base node of the stream job is the same as the
    # top node of commit job. Since this results in the commit filter
    # node being part of the stream chain, this is not allowed.
    def test_overlapping_4(self):
        self.assert_no_active_block_jobs()

        # Commit from node2 into node0
        result = self.vm.qmp('block-commit', device='drive0',
                             top=self.imgs[2], base=self.imgs[0],
                             filter_node_name='commit-filter', speed=1024*1024)
        self.assert_qmp(result, 'return', {})

        # Stream from node2 into node4
        result = self.vm.qmp('block-stream', device='node4', base_node='node2', job_id='node4')
        self.assert_qmp(result, 'error/desc',
            "Cannot freeze 'backing' link to 'commit-filter'")

        result = self.vm.qmp('block-job-set-speed', device='drive0', speed=0)
        self.assert_qmp(result, 'return', {})

        self.wait_until_completed()
        self.assert_no_active_block_jobs()

    # In this case the base node of the stream job is the commit job's
    # filter node.  stream does not have a real dependency on its base
    # node, so even though commit removes it when it is done, there is
    # no conflict.
    def test_overlapping_5(self):
        self.assert_no_active_block_jobs()

        # Commit from node2 into node0
        result = self.vm.qmp('block-commit', device='drive0',
                             top_node='node2', base_node='node0',
                             filter_node_name='commit-filter', speed=1024*1024)
        self.assert_qmp(result, 'return', {})

        # Stream from node2 into node4
        result = self.vm.qmp('block-stream', device='node4',
                             base_node='commit-filter', job_id='node4')
        self.assert_qmp(result, 'return', {})

        result = self.vm.qmp('block-job-set-speed', device='drive0', speed=0)
        self.assert_qmp(result, 'return', {})

        self.vm.run_job(job='drive0', auto_dismiss=True)
        self.vm.run_job(job='node4', auto_dismiss=True)
        self.assert_no_active_block_jobs()

    # Test a block-stream and a block-commit job in parallel
    # Here the stream job is supposed to finish quickly in order to reproduce
    # the scenario that triggers the bug fixed in 3d5d319e1221 and 1a63a907507
    def test_stream_commit_1(self):
        self.assertLessEqual(8, self.num_imgs)
        self.assert_no_active_block_jobs()

        # Stream from node0 into node2
        result = self.vm.qmp('block-stream', device='node2', base_node='node0', job_id='node2')
        self.assert_qmp(result, 'return', {})

        # Commit from the active layer into node3
        result = self.vm.qmp('block-commit', device='drive0', base=self.imgs[3])
        self.assert_qmp(result, 'return', {})

        # Wait for all jobs to be finished.
        pending_jobs = ['node2', 'drive0']
        while len(pending_jobs) > 0:
            for event in self.vm.get_qmp_events(wait=True):
                if event['event'] == 'BLOCK_JOB_COMPLETED':
                    node_name = self.dictpath(event, 'data/device')
                    self.assertTrue(node_name in pending_jobs)
                    self.assert_qmp_absent(event, 'data/error')
                    pending_jobs.remove(node_name)
                if event['event'] == 'BLOCK_JOB_READY':
                    self.assert_qmp(event, 'data/device', 'drive0')
                    self.assert_qmp(event, 'data/type', 'commit')
                    self.assert_qmp_absent(event, 'data/error')
                    self.assertTrue('drive0' in pending_jobs)
                    self.vm.qmp('block-job-complete', device='drive0')

        self.assert_no_active_block_jobs()

    # This is similar to test_stream_commit_1 but both jobs are slowed
    # down so they can run in parallel for a little while.
    def test_stream_commit_2(self):
        self.assertLessEqual(8, self.num_imgs)
        self.assert_no_active_block_jobs()

        # Stream from node0 into node4
        result = self.vm.qmp('block-stream', device='node4', base_node='node0', job_id='node4', speed=1024*1024)
        self.assert_qmp(result, 'return', {})

        # Commit from the active layer into node5
        result = self.vm.qmp('block-commit', device='drive0', base=self.imgs[5], speed=1024*1024)
        self.assert_qmp(result, 'return', {})

        for job in ['drive0', 'node4']:
            result = self.vm.qmp('block-job-set-speed', device=job, speed=0)
            self.assert_qmp(result, 'return', {})

        # Wait for all jobs to be finished.
        pending_jobs = ['node4', 'drive0']
        while len(pending_jobs) > 0:
            for event in self.vm.get_qmp_events(wait=True):
                if event['event'] == 'BLOCK_JOB_COMPLETED':
                    node_name = self.dictpath(event, 'data/device')
                    self.assertTrue(node_name in pending_jobs)
                    self.assert_qmp_absent(event, 'data/error')
                    pending_jobs.remove(node_name)
                if event['event'] == 'BLOCK_JOB_READY':
                    self.assert_qmp(event, 'data/device', 'drive0')
                    self.assert_qmp(event, 'data/type', 'commit')
                    self.assert_qmp_absent(event, 'data/error')
                    self.assertTrue('drive0' in pending_jobs)
                    self.vm.qmp('block-job-complete', device='drive0')

        self.assert_no_active_block_jobs()

    # Test the base_node parameter
    def test_stream_base_node_name(self):
        self.assert_no_active_block_jobs()

        self.assertNotEqual(qemu_io('-f', iotests.imgfmt, '-rU', '-c', 'map', self.imgs[4]),
                            qemu_io('-f', iotests.imgfmt, '-rU', '-c', 'map', self.imgs[3]),
                            'image file map matches backing file before streaming')

        # Error: the base node does not exist
        result = self.vm.qmp('block-stream', device='node4', base_node='none', job_id='stream')
        self.assert_qmp(result, 'error/desc',
            'Cannot find device= nor node_name=none')

        # Error: the base node is not a backing file of the top node
        result = self.vm.qmp('block-stream', device='node4', base_node='node6', job_id='stream')
        self.assert_qmp(result, 'error/desc',
            "Node 'node6' is not a backing image of 'node4'")

        # Error: the base node is the same as the top node
        result = self.vm.qmp('block-stream', device='node4', base_node='node4', job_id='stream')
        self.assert_qmp(result, 'error/desc',
            "Node 'node4' is not a backing image of 'node4'")

        # Error: cannot specify 'base' and 'base-node' at the same time
        result = self.vm.qmp('block-stream', device='node4', base=self.imgs[2], base_node='node2', job_id='stream')
        self.assert_qmp(result, 'error/desc',
            "'base' and 'base-node' cannot be specified at the same time")

        # Success: the base node is a backing file of the top node
        result = self.vm.qmp('block-stream', device='node4', base_node='node2', job_id='stream')
        self.assert_qmp(result, 'return', {})

        self.wait_until_completed(drive='stream')

        self.assert_no_active_block_jobs()
        self.vm.shutdown()

        self.assertEqual(qemu_io('-f', iotests.imgfmt, '-c', 'map', self.imgs[4]),
                         qemu_io('-f', iotests.imgfmt, '-c', 'map', self.imgs[3]),
                         'image file map matches backing file after streaming')

class TestQuorum(iotests.QMPTestCase):
    num_children = 3
    children = []
    backing = []

    @iotests.skip_if_unsupported(['quorum'])
    def setUp(self):
        opts = ['driver=quorum', 'vote-threshold=2']

        # Initialize file names and command-line options
        for i in range(self.num_children):
            child_img = os.path.join(iotests.test_dir, 'img-%d.img' % i)
            backing_img = os.path.join(iotests.test_dir, 'backing-%d.img' % i)
            self.children.append(child_img)
            self.backing.append(backing_img)
            qemu_img('create', '-f', iotests.imgfmt, backing_img, '1M')
            qemu_io('-f', iotests.imgfmt,
                    '-c', 'write -P 0x55 0 1024', backing_img)
            qemu_img('create', '-f', iotests.imgfmt,
                     '-o', 'backing_file=%s' % backing_img,
                     '-F', iotests.imgfmt, child_img)
            opts.append("children.%d.file.filename=%s" % (i, child_img))
            opts.append("children.%d.node-name=node%d" % (i, i))

        # Attach the drive to the VM
        self.vm = iotests.VM()
        self.vm.add_drive(path = None, opts = ','.join(opts))
        self.vm.launch()

    def tearDown(self):
        self.vm.shutdown()
        for img in self.children:
            os.remove(img)
        for img in self.backing:
            os.remove(img)

    def test_stream_quorum(self):
        self.assertNotEqual(qemu_io('-f', iotests.imgfmt, '-rU', '-c', 'map', self.children[0]),
                            qemu_io('-f', iotests.imgfmt, '-rU', '-c', 'map', self.backing[0]),
                            'image file map matches backing file before streaming')

        self.assert_no_active_block_jobs()

        result = self.vm.qmp('block-stream', device='node0', job_id='stream-node0')
        self.assert_qmp(result, 'return', {})

        self.wait_until_completed(drive='stream-node0')

        self.assert_no_active_block_jobs()
        self.vm.shutdown()

        self.assertEqual(qemu_io('-f', iotests.imgfmt, '-c', 'map', self.children[0]),
                         qemu_io('-f', iotests.imgfmt, '-c', 'map', self.backing[0]),
                         'image file map does not match backing file after streaming')

class TestSmallerBackingFile(iotests.QMPTestCase):
    backing_len = 1 * 1024 * 1024 # MB
    image_len = 2 * backing_len

    def setUp(self):
        iotests.create_image(backing_img, self.backing_len)
        qemu_img('create', '-f', iotests.imgfmt,
                 '-o', 'backing_file=%s' % backing_img,
                 '-F', 'raw', test_img, str(self.image_len))
        self.vm = iotests.VM().add_drive(test_img)
        self.vm.launch()

    # If this hangs, then you are missing a fix to complete streaming when the
    # end of the backing file is reached.
    def test_stream(self):
        self.assert_no_active_block_jobs()

        result = self.vm.qmp('block-stream', device='drive0')
        self.assert_qmp(result, 'return', {})

        self.wait_until_completed()

        self.assert_no_active_block_jobs()
        self.vm.shutdown()

class TestErrors(iotests.QMPTestCase):
    image_len = 2 * 1024 * 1024 # MB

    # this should match STREAM_BUFFER_SIZE/512 in block/stream.c
    STREAM_BUFFER_SIZE = 512 * 1024

    def create_blkdebug_file(self, name, event, errno):
        file = open(name, 'w')
        file.write('''
[inject-error]
state = "1"
event = "%s"
errno = "%d"
immediately = "off"
once = "on"
sector = "%d"

[set-state]
state = "1"
event = "%s"
new_state = "2"

[set-state]
state = "2"
event = "%s"
new_state = "1"
''' % (event, errno, self.STREAM_BUFFER_SIZE // 512, event, event))
        file.close()

class TestEIO(TestErrors):
    def setUp(self):
        self.blkdebug_file = backing_img + ".blkdebug"
        iotests.create_image(backing_img, TestErrors.image_len)
        self.create_blkdebug_file(self.blkdebug_file, "read_aio", 5)
        qemu_img('create', '-f', iotests.imgfmt,
                 '-o', 'backing_file=blkdebug:%s:%s,backing_fmt=raw'
                       % (self.blkdebug_file, backing_img),
                 test_img)
        self.vm = iotests.VM().add_drive(test_img)
        self.vm.launch()

    def tearDown(self):
        self.vm.shutdown()
        os.remove(test_img)
        os.remove(backing_img)
        os.remove(self.blkdebug_file)

    def test_report(self):
        self.assert_no_active_block_jobs()

        result = self.vm.qmp('block-stream', device='drive0')
        self.assert_qmp(result, 'return', {})

        completed = False
        error = False
        while not completed:
            for event in self.vm.get_qmp_events(wait=True):
                if event['event'] == 'BLOCK_JOB_ERROR':
                    self.assert_qmp(event, 'data/device', 'drive0')
                    self.assert_qmp(event, 'data/operation', 'read')
                    error = True
                elif event['event'] == 'BLOCK_JOB_COMPLETED':
                    self.assertTrue(error, 'job completed unexpectedly')
                    self.assert_qmp(event, 'data/type', 'stream')
                    self.assert_qmp(event, 'data/device', 'drive0')
                    self.assert_qmp(event, 'data/error', 'Input/output error')
                    self.assert_qmp(event, 'data/offset', self.STREAM_BUFFER_SIZE)
                    self.assert_qmp(event, 'data/len', self.image_len)
                    completed = True
                elif event['event'] == 'JOB_STATUS_CHANGE':
                    self.assert_qmp(event, 'data/id', 'drive0')

        self.assert_no_active_block_jobs()
        self.vm.shutdown()

    def test_ignore(self):
        self.assert_no_active_block_jobs()

        result = self.vm.qmp('block-stream', device='drive0', on_error='ignore')
        self.assert_qmp(result, 'return', {})

        error = False
        completed = False
        while not completed:
            for event in self.vm.get_qmp_events(wait=True):
                if event['event'] == 'BLOCK_JOB_ERROR':
                    error = True
                    self.assert_qmp(event, 'data/device', 'drive0')
                    self.assert_qmp(event, 'data/operation', 'read')
                    result = self.vm.qmp('query-block-jobs')
                    if result == {'return': []}:
                        # Job finished too quickly
                        continue
                    self.assert_qmp(result, 'return[0]/paused', False)
                elif event['event'] == 'BLOCK_JOB_COMPLETED':
                    self.assertTrue(error, 'job completed unexpectedly')
                    self.assert_qmp(event, 'data/type', 'stream')
                    self.assert_qmp(event, 'data/device', 'drive0')
                    self.assert_qmp(event, 'data/error', 'Input/output error')
                    self.assert_qmp(event, 'data/offset', self.image_len)
                    self.assert_qmp(event, 'data/len', self.image_len)
                    completed = True
                elif event['event'] == 'JOB_STATUS_CHANGE':
                    self.assert_qmp(event, 'data/id', 'drive0')

        self.assert_no_active_block_jobs()
        self.vm.shutdown()

    def test_stop(self):
        self.assert_no_active_block_jobs()

        result = self.vm.qmp('block-stream', device='drive0', on_error='stop')
        self.assert_qmp(result, 'return', {})

        error = False
        completed = False
        while not completed:
            for event in self.vm.get_qmp_events(wait=True):
                if event['event'] == 'BLOCK_JOB_ERROR':
                    error = True
                    self.assert_qmp(event, 'data/device', 'drive0')
                    self.assert_qmp(event, 'data/operation', 'read')

                    result = self.vm.qmp('query-block-jobs')
                    self.assert_qmp(result, 'return[0]/paused', True)
                    self.assert_qmp(result, 'return[0]/offset', self.STREAM_BUFFER_SIZE)
                    self.assert_qmp(result, 'return[0]/io-status', 'failed')

                    result = self.vm.qmp('block-job-resume', device='drive0')
                    self.assert_qmp(result, 'return', {})

                    result = self.vm.qmp('query-block-jobs')
                    if result == {'return': []}:
                        # Race; likely already finished. Check.
                        continue
                    self.assert_qmp(result, 'return[0]/paused', False)
                    self.assert_qmp(result, 'return[0]/io-status', 'ok')
                elif event['event'] == 'BLOCK_JOB_COMPLETED':
                    self.assertTrue(error, 'job completed unexpectedly')
                    self.assert_qmp(event, 'data/type', 'stream')
                    self.assert_qmp(event, 'data/device', 'drive0')
                    self.assert_qmp_absent(event, 'data/error')
                    self.assert_qmp(event, 'data/offset', self.image_len)
                    self.assert_qmp(event, 'data/len', self.image_len)
                    completed = True
                elif event['event'] == 'JOB_STATUS_CHANGE':
                    self.assert_qmp(event, 'data/id', 'drive0')

        self.assert_no_active_block_jobs()
        self.vm.shutdown()

    def test_enospc(self):
        self.assert_no_active_block_jobs()

        result = self.vm.qmp('block-stream', device='drive0', on_error='enospc')
        self.assert_qmp(result, 'return', {})

        completed = False
        error = False
        while not completed:
            for event in self.vm.get_qmp_events(wait=True):
                if event['event'] == 'BLOCK_JOB_ERROR':
                    self.assert_qmp(event, 'data/device', 'drive0')
                    self.assert_qmp(event, 'data/operation', 'read')
                    error = True
                elif event['event'] == 'BLOCK_JOB_COMPLETED':
                    self.assertTrue(error, 'job completed unexpectedly')
                    self.assert_qmp(event, 'data/type', 'stream')
                    self.assert_qmp(event, 'data/device', 'drive0')
                    self.assert_qmp(event, 'data/error', 'Input/output error')
                    self.assert_qmp(event, 'data/offset', self.STREAM_BUFFER_SIZE)
                    self.assert_qmp(event, 'data/len', self.image_len)
                    completed = True
                elif event['event'] == 'JOB_STATUS_CHANGE':
                    self.assert_qmp(event, 'data/id', 'drive0')

        self.assert_no_active_block_jobs()
        self.vm.shutdown()

class TestENOSPC(TestErrors):
    def setUp(self):
        self.blkdebug_file = backing_img + ".blkdebug"
        iotests.create_image(backing_img, TestErrors.image_len)
        self.create_blkdebug_file(self.blkdebug_file, "read_aio", 28)
        qemu_img('create', '-f', iotests.imgfmt,
                 '-o', 'backing_file=blkdebug:%s:%s,backing_fmt=raw'
                       % (self.blkdebug_file, backing_img),
                 test_img)
        self.vm = iotests.VM().add_drive(test_img)
        self.vm.launch()

    def tearDown(self):
        self.vm.shutdown()
        os.remove(test_img)
        os.remove(backing_img)
        os.remove(self.blkdebug_file)

    def test_enospc(self):
        self.assert_no_active_block_jobs()

        result = self.vm.qmp('block-stream', device='drive0', on_error='enospc')
        self.assert_qmp(result, 'return', {})

        error = False
        completed = False
        while not completed:
            for event in self.vm.get_qmp_events(wait=True):
                if event['event'] == 'BLOCK_JOB_ERROR':
                    self.assert_qmp(event, 'data/device', 'drive0')
                    self.assert_qmp(event, 'data/operation', 'read')
                    error = True

                    result = self.vm.qmp('query-block-jobs')
                    self.assert_qmp(result, 'return[0]/paused', True)
                    self.assert_qmp(result, 'return[0]/offset', self.STREAM_BUFFER_SIZE)
                    self.assert_qmp(result, 'return[0]/io-status', 'nospace')

                    result = self.vm.qmp('block-job-resume', device='drive0')
                    self.assert_qmp(result, 'return', {})

                    result = self.vm.qmp('query-block-jobs')
                    if result == {'return': []}:
                        # Race; likely already finished. Check.
                        continue
                    self.assert_qmp(result, 'return[0]/paused', False)
                    self.assert_qmp(result, 'return[0]/io-status', 'ok')
                elif event['event'] == 'BLOCK_JOB_COMPLETED':
                    self.assertTrue(error, 'job completed unexpectedly')
                    self.assert_qmp(event, 'data/type', 'stream')
                    self.assert_qmp(event, 'data/device', 'drive0')
                    self.assert_qmp_absent(event, 'data/error')
                    self.assert_qmp(event, 'data/offset', self.image_len)
                    self.assert_qmp(event, 'data/len', self.image_len)
                    completed = True
                elif event['event'] == 'JOB_STATUS_CHANGE':
                    self.assert_qmp(event, 'data/id', 'drive0')

        self.assert_no_active_block_jobs()
        self.vm.shutdown()

class TestStreamStop(iotests.QMPTestCase):
    image_len = 8 * 1024 * 1024 * 1024 # GB

    def setUp(self):
        qemu_img('create', backing_img, str(TestStreamStop.image_len))
        qemu_io('-f', 'raw', '-c', 'write -P 0x1 0 32M', backing_img)
        qemu_img('create', '-f', iotests.imgfmt,
                 '-o', 'backing_file=%s' % backing_img,
                 '-F', 'raw', test_img)
        qemu_io('-f', iotests.imgfmt, '-c', 'write -P 0x1 32M 32M', test_img)
        self.vm = iotests.VM().add_drive("blkdebug::" + test_img)
        self.vm.launch()

    def tearDown(self):
        self.vm.shutdown()
        os.remove(test_img)
        os.remove(backing_img)

    def test_stream_stop(self):
        self.assert_no_active_block_jobs()

        self.vm.pause_drive('drive0')
        result = self.vm.qmp('block-stream', device='drive0')
        self.assert_qmp(result, 'return', {})

        time.sleep(0.1)
        events = self.vm.get_qmp_events(wait=False)
        for e in events:
            self.assert_qmp(e, 'event', 'JOB_STATUS_CHANGE')
            self.assert_qmp(e, 'data/id', 'drive0')

        self.cancel_and_wait(resume=True)

class TestSetSpeed(iotests.QMPTestCase):
    image_len = 80 * 1024 * 1024 # MB

    def setUp(self):
        qemu_img('create', backing_img, str(TestSetSpeed.image_len))
        qemu_io('-f', 'raw', '-c', 'write -P 0x1 0 32M', backing_img)
        qemu_img('create', '-f', iotests.imgfmt,
                 '-o', 'backing_file=%s' % backing_img,
                 '-F', 'raw', test_img)
        qemu_io('-f', iotests.imgfmt, '-c', 'write -P 0x1 32M 32M', test_img)
        self.vm = iotests.VM().add_drive('blkdebug::' + test_img)
        self.vm.launch()

    def tearDown(self):
        self.vm.shutdown()
        os.remove(test_img)
        os.remove(backing_img)

    # This is a short performance test which is not run by default.
    # Invoke "IMGFMT=qed ./030 TestSetSpeed.perf_test_throughput"
    def perf_test_throughput(self):
        self.assert_no_active_block_jobs()

        result = self.vm.qmp('block-stream', device='drive0')
        self.assert_qmp(result, 'return', {})

        result = self.vm.qmp('block-job-set-speed', device='drive0', speed=8 * 1024 * 1024)
        self.assert_qmp(result, 'return', {})

        self.wait_until_completed()

        self.assert_no_active_block_jobs()

    def test_set_speed(self):
        self.assert_no_active_block_jobs()

        self.vm.pause_drive('drive0')
        result = self.vm.qmp('block-stream', device='drive0')
        self.assert_qmp(result, 'return', {})

        # Default speed is 0
        result = self.vm.qmp('query-block-jobs')
        self.assert_qmp(result, 'return[0]/device', 'drive0')
        self.assert_qmp(result, 'return[0]/speed', 0)

        result = self.vm.qmp('block-job-set-speed', device='drive0', speed=8 * 1024 * 1024)
        self.assert_qmp(result, 'return', {})

        # Ensure the speed we set was accepted
        result = self.vm.qmp('query-block-jobs')
        self.assert_qmp(result, 'return[0]/device', 'drive0')
        self.assert_qmp(result, 'return[0]/speed', 8 * 1024 * 1024)

        self.cancel_and_wait(resume=True)
        self.vm.pause_drive('drive0')

        # Check setting speed in block-stream works
        result = self.vm.qmp('block-stream', device='drive0', speed=4 * 1024 * 1024)
        self.assert_qmp(result, 'return', {})

        result = self.vm.qmp('query-block-jobs')
        self.assert_qmp(result, 'return[0]/device', 'drive0')
        self.assert_qmp(result, 'return[0]/speed', 4 * 1024 * 1024)

        self.cancel_and_wait(resume=True)

    def test_set_speed_invalid(self):
        self.assert_no_active_block_jobs()

        result = self.vm.qmp('block-stream', device='drive0', speed=-1)
        self.assert_qmp(result, 'error/desc', "Parameter 'speed' expects a non-negative value")

        self.assert_no_active_block_jobs()

        self.vm.pause_drive('drive0')
        result = self.vm.qmp('block-stream', device='drive0')
        self.assert_qmp(result, 'return', {})

        result = self.vm.qmp('block-job-set-speed', device='drive0', speed=-1)
        self.assert_qmp(result, 'error/desc', "Parameter 'speed' expects a non-negative value")

        self.cancel_and_wait(resume=True)

if __name__ == '__main__':
    iotests.main(supported_fmts=['qcow2', 'qed'],
                 supported_protocols=['file'])
