diff mbox

[v3] qemu-iotests: use blkdebug to make test deterministic

Message ID 1383185888-8131-1-git-send-email-famz@redhat.com
State New
Headers show

Commit Message

Fam Zheng Oct. 31, 2013, 2:18 a.m. UTC
This patch suspends the test image IO before starting block stream job
so that it doesn't complete before we could check the status.

Signed-off-by: Fam Zheng <famz@redhat.com>
---
 tests/qemu-iotests/030        | 10 ++++++----
 tests/qemu-iotests/iotests.py |  5 ++++-
 2 files changed, 10 insertions(+), 5 deletions(-)

Comments

Stefan Hajnoczi Nov. 6, 2013, 12:03 p.m. UTC | #1
On Thu, Oct 31, 2013 at 10:18:08AM +0800, Fam Zheng wrote:
> This patch suspends the test image IO before starting block stream job
> so that it doesn't complete before we could check the status.
> 
> Signed-off-by: Fam Zheng <famz@redhat.com>
> ---
>  tests/qemu-iotests/030        | 10 ++++++----
>  tests/qemu-iotests/iotests.py |  5 ++++-
>  2 files changed, 10 insertions(+), 5 deletions(-)

./check -qcow2 030 hangs with this patch applied.

Can you reproduce it or am I missing something?

Stefan
Paolo Bonzini Nov. 6, 2013, 12:10 p.m. UTC | #2
Il 31/10/2013 03:18, Fam Zheng ha scritto:
> This patch suspends the test image IO before starting block stream job
> so that it doesn't complete before we could check the status.
> 
> Signed-off-by: Fam Zheng <famz@redhat.com>
> ---
>  tests/qemu-iotests/030        | 10 ++++++----
>  tests/qemu-iotests/iotests.py |  5 ++++-
>  2 files changed, 10 insertions(+), 5 deletions(-)
> 
> diff --git a/tests/qemu-iotests/030 b/tests/qemu-iotests/030
> index d0f96ea..bc66e6f 100755
> --- a/tests/qemu-iotests/030
> +++ b/tests/qemu-iotests/030
> @@ -391,7 +391,7 @@ class TestStreamStop(iotests.QMPTestCase):
>          qemu_io('-c', 'write -P 0x1 0 32M', backing_img)
>          qemu_img('create', '-f', iotests.imgfmt, '-o', 'backing_file=%s' % backing_img, test_img)
>          qemu_io('-c', 'write -P 0x1 32M 32M', test_img)
> -        self.vm = iotests.VM().add_drive(test_img)
> +        self.vm = iotests.VM().add_drive("blkdebug::" + test_img)
>          self.vm.launch()
>  
>      def tearDown(self):
> @@ -402,6 +402,7 @@ class TestStreamStop(iotests.QMPTestCase):
>      def test_stream_stop(self):
>          self.assert_no_active_block_jobs()
>  
> +        self.vm.qmp('human-monitor-command', command_line='qemu-io drive0 "break write_aio a"')
>          result = self.vm.qmp('block-stream', device='drive0')
>          self.assert_qmp(result, 'return', {})
>  
> @@ -409,7 +410,7 @@ class TestStreamStop(iotests.QMPTestCase):
>          events = self.vm.get_qmp_events(wait=False)
>          self.assertEqual(events, [], 'unexpected QMP event: %s' % events)
>  
> -        self.cancel_and_wait()
> +        self.cancel_and_wait(resume='a')
>  
>  class TestSetSpeed(iotests.QMPTestCase):
>      image_len = 80 * 1024 * 1024 # MB
> @@ -419,7 +420,7 @@ class TestSetSpeed(iotests.QMPTestCase):
>          qemu_io('-c', 'write -P 0x1 0 32M', backing_img)
>          qemu_img('create', '-f', iotests.imgfmt, '-o', 'backing_file=%s' % backing_img, test_img)
>          qemu_io('-c', 'write -P 0x1 32M 32M', test_img)
> -        self.vm = iotests.VM().add_drive(test_img)
> +        self.vm = iotests.VM().add_drive('blkdebug::' + test_img)
>          self.vm.launch()
>  
>      def tearDown(self):
> @@ -453,6 +454,7 @@ class TestSetSpeed(iotests.QMPTestCase):
>      def test_set_speed(self):
>          self.assert_no_active_block_jobs()
>  
> +        self.vm.qmp('human-monitor-command', command_line='qemu-io drive0 "break write_aio a"')
>          result = self.vm.qmp('block-stream', device='drive0')
>          self.assert_qmp(result, 'return', {})
>  
> @@ -469,7 +471,7 @@ class TestSetSpeed(iotests.QMPTestCase):
>          self.assert_qmp(result, 'return[0]/device', 'drive0')
>          self.assert_qmp(result, 'return[0]/speed', 8 * 1024 * 1024)
>  
> -        self.cancel_and_wait()
> +        self.cancel_and_wait(resume='a')
>  
>          # Check setting speed in block-stream works
>          result = self.vm.qmp('block-stream', device='drive0', speed=4 * 1024 * 1024)
> diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py
> index fb10ff4..de45079 100644
> --- a/tests/qemu-iotests/iotests.py
> +++ b/tests/qemu-iotests/iotests.py
> @@ -222,11 +222,14 @@ class QMPTestCase(unittest.TestCase):
>          result = self.vm.qmp('query-block-jobs')
>          self.assert_qmp(result, 'return', [])
>  
> -    def cancel_and_wait(self, drive='drive0', force=False):
> +    def cancel_and_wait(self, drive='drive0', force=False, resume=""):
>          '''Cancel a block job and wait for it to finish, returning the event'''
>          result = self.vm.qmp('block-job-cancel', device=drive, force=force)
>          self.assert_qmp(result, 'return', {})
>  
> +        if resume:
> +            self.vm.qmp('human-monitor-command', command_line='qemu-io %s "resume %s"' % (drive, resume))
> +
>          cancelled = False
>          result = None
>          while not cancelled:
> 

Can you do the same for the mirror test too?

Paolo
Fam Zheng Nov. 7, 2013, 7:58 a.m. UTC | #3
On 11/06/2013 08:03 PM, Stefan Hajnoczi wrote:
> On Thu, Oct 31, 2013 at 10:18:08AM +0800, Fam Zheng wrote:
>> This patch suspends the test image IO before starting block stream job
>> so that it doesn't complete before we could check the status.
>>
>> Signed-off-by: Fam Zheng <famz@redhat.com>
>> ---
>>   tests/qemu-iotests/030        | 10 ++++++----
>>   tests/qemu-iotests/iotests.py |  5 ++++-
>>   2 files changed, 10 insertions(+), 5 deletions(-)
>
> ./check -qcow2 030 hangs with this patch applied.
>
> Can you reproduce it or am I missing something?
>

Yes, Occasionally. I'll look into it.

Fam
Fam Zheng Nov. 7, 2013, 10:51 a.m. UTC | #4
On 11/06/2013 08:10 PM, Paolo Bonzini wrote:
> Il 31/10/2013 03:18, Fam Zheng ha scritto:
>> This patch suspends the test image IO before starting block stream job
>> so that it doesn't complete before we could check the status.
>>
>> Signed-off-by: Fam Zheng <famz@redhat.com>
>> ---
>>   tests/qemu-iotests/030        | 10 ++++++----
>>   tests/qemu-iotests/iotests.py |  5 ++++-
>>   2 files changed, 10 insertions(+), 5 deletions(-)
>>
>> diff --git a/tests/qemu-iotests/030 b/tests/qemu-iotests/030
>> index d0f96ea..bc66e6f 100755
>> --- a/tests/qemu-iotests/030
>> +++ b/tests/qemu-iotests/030
>> @@ -391,7 +391,7 @@ class TestStreamStop(iotests.QMPTestCase):
>>           qemu_io('-c', 'write -P 0x1 0 32M', backing_img)
>>           qemu_img('create', '-f', iotests.imgfmt, '-o', 'backing_file=%s' % backing_img, test_img)
>>           qemu_io('-c', 'write -P 0x1 32M 32M', test_img)
>> -        self.vm = iotests.VM().add_drive(test_img)
>> +        self.vm = iotests.VM().add_drive("blkdebug::" + test_img)
>>           self.vm.launch()
>>
>>       def tearDown(self):
>> @@ -402,6 +402,7 @@ class TestStreamStop(iotests.QMPTestCase):
>>       def test_stream_stop(self):
>>           self.assert_no_active_block_jobs()
>>
>> +        self.vm.qmp('human-monitor-command', command_line='qemu-io drive0 "break write_aio a"')
>>           result = self.vm.qmp('block-stream', device='drive0')
>>           self.assert_qmp(result, 'return', {})
>>
>> @@ -409,7 +410,7 @@ class TestStreamStop(iotests.QMPTestCase):
>>           events = self.vm.get_qmp_events(wait=False)
>>           self.assertEqual(events, [], 'unexpected QMP event: %s' % events)
>>
>> -        self.cancel_and_wait()
>> +        self.cancel_and_wait(resume='a')
>>
>>   class TestSetSpeed(iotests.QMPTestCase):
>>       image_len = 80 * 1024 * 1024 # MB
>> @@ -419,7 +420,7 @@ class TestSetSpeed(iotests.QMPTestCase):
>>           qemu_io('-c', 'write -P 0x1 0 32M', backing_img)
>>           qemu_img('create', '-f', iotests.imgfmt, '-o', 'backing_file=%s' % backing_img, test_img)
>>           qemu_io('-c', 'write -P 0x1 32M 32M', test_img)
>> -        self.vm = iotests.VM().add_drive(test_img)
>> +        self.vm = iotests.VM().add_drive('blkdebug::' + test_img)
>>           self.vm.launch()
>>
>>       def tearDown(self):
>> @@ -453,6 +454,7 @@ class TestSetSpeed(iotests.QMPTestCase):
>>       def test_set_speed(self):
>>           self.assert_no_active_block_jobs()
>>
>> +        self.vm.qmp('human-monitor-command', command_line='qemu-io drive0 "break write_aio a"')
>>           result = self.vm.qmp('block-stream', device='drive0')
>>           self.assert_qmp(result, 'return', {})
>>
>> @@ -469,7 +471,7 @@ class TestSetSpeed(iotests.QMPTestCase):
>>           self.assert_qmp(result, 'return[0]/device', 'drive0')
>>           self.assert_qmp(result, 'return[0]/speed', 8 * 1024 * 1024)
>>
>> -        self.cancel_and_wait()
>> +        self.cancel_and_wait(resume='a')
>>
>>           # Check setting speed in block-stream works
>>           result = self.vm.qmp('block-stream', device='drive0', speed=4 * 1024 * 1024)
>> diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py
>> index fb10ff4..de45079 100644
>> --- a/tests/qemu-iotests/iotests.py
>> +++ b/tests/qemu-iotests/iotests.py
>> @@ -222,11 +222,14 @@ class QMPTestCase(unittest.TestCase):
>>           result = self.vm.qmp('query-block-jobs')
>>           self.assert_qmp(result, 'return', [])
>>
>> -    def cancel_and_wait(self, drive='drive0', force=False):
>> +    def cancel_and_wait(self, drive='drive0', force=False, resume=""):
>>           '''Cancel a block job and wait for it to finish, returning the event'''
>>           result = self.vm.qmp('block-job-cancel', device=drive, force=force)
>>           self.assert_qmp(result, 'return', {})
>>
>> +        if resume:
>> +            self.vm.qmp('human-monitor-command', command_line='qemu-io %s "resume %s"' % (drive, resume))
>> +
>>           cancelled = False
>>           result = None
>>           while not cancelled:
>>
>
> Can you do the same for the mirror test too?

Yes, of course.

Fam
Fam Zheng Nov. 7, 2013, 11:25 a.m. UTC | #5
On 11/06/2013 08:10 PM, Paolo Bonzini wrote:
> Il 31/10/2013 03:18, Fam Zheng ha scritto:
>> This patch suspends the test image IO before starting block stream job
>> so that it doesn't complete before we could check the status.
>>
>> Signed-off-by: Fam Zheng <famz@redhat.com>
>> ---
>>   tests/qemu-iotests/030        | 10 ++++++----
>>   tests/qemu-iotests/iotests.py |  5 ++++-
>>   2 files changed, 10 insertions(+), 5 deletions(-)
>>
>> diff --git a/tests/qemu-iotests/030 b/tests/qemu-iotests/030
>> index d0f96ea..bc66e6f 100755
>> --- a/tests/qemu-iotests/030
>> +++ b/tests/qemu-iotests/030
>> @@ -391,7 +391,7 @@ class TestStreamStop(iotests.QMPTestCase):
>>           qemu_io('-c', 'write -P 0x1 0 32M', backing_img)
>>           qemu_img('create', '-f', iotests.imgfmt, '-o', 'backing_file=%s' % backing_img, test_img)
>>           qemu_io('-c', 'write -P 0x1 32M 32M', test_img)
>> -        self.vm = iotests.VM().add_drive(test_img)
>> +        self.vm = iotests.VM().add_drive("blkdebug::" + test_img)
>>           self.vm.launch()
>>
>>       def tearDown(self):
>> @@ -402,6 +402,7 @@ class TestStreamStop(iotests.QMPTestCase):
>>       def test_stream_stop(self):
>>           self.assert_no_active_block_jobs()
>>
>> +        self.vm.qmp('human-monitor-command', command_line='qemu-io drive0 "break write_aio a"')
>>           result = self.vm.qmp('block-stream', device='drive0')
>>           self.assert_qmp(result, 'return', {})
>>
>> @@ -409,7 +410,7 @@ class TestStreamStop(iotests.QMPTestCase):
>>           events = self.vm.get_qmp_events(wait=False)
>>           self.assertEqual(events, [], 'unexpected QMP event: %s' % events)
>>
>> -        self.cancel_and_wait()
>> +        self.cancel_and_wait(resume='a')
>>
>>   class TestSetSpeed(iotests.QMPTestCase):
>>       image_len = 80 * 1024 * 1024 # MB
>> @@ -419,7 +420,7 @@ class TestSetSpeed(iotests.QMPTestCase):
>>           qemu_io('-c', 'write -P 0x1 0 32M', backing_img)
>>           qemu_img('create', '-f', iotests.imgfmt, '-o', 'backing_file=%s' % backing_img, test_img)
>>           qemu_io('-c', 'write -P 0x1 32M 32M', test_img)
>> -        self.vm = iotests.VM().add_drive(test_img)
>> +        self.vm = iotests.VM().add_drive('blkdebug::' + test_img)
>>           self.vm.launch()
>>
>>       def tearDown(self):
>> @@ -453,6 +454,7 @@ class TestSetSpeed(iotests.QMPTestCase):
>>       def test_set_speed(self):
>>           self.assert_no_active_block_jobs()
>>
>> +        self.vm.qmp('human-monitor-command', command_line='qemu-io drive0 "break write_aio a"')
>>           result = self.vm.qmp('block-stream', device='drive0')
>>           self.assert_qmp(result, 'return', {})
>>
>> @@ -469,7 +471,7 @@ class TestSetSpeed(iotests.QMPTestCase):
>>           self.assert_qmp(result, 'return[0]/device', 'drive0')
>>           self.assert_qmp(result, 'return[0]/speed', 8 * 1024 * 1024)
>>
>> -        self.cancel_and_wait()
>> +        self.cancel_and_wait(resume='a')
>>
>>           # Check setting speed in block-stream works
>>           result = self.vm.qmp('block-stream', device='drive0', speed=4 * 1024 * 1024)
>> diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py
>> index fb10ff4..de45079 100644
>> --- a/tests/qemu-iotests/iotests.py
>> +++ b/tests/qemu-iotests/iotests.py
>> @@ -222,11 +222,14 @@ class QMPTestCase(unittest.TestCase):
>>           result = self.vm.qmp('query-block-jobs')
>>           self.assert_qmp(result, 'return', [])
>>
>> -    def cancel_and_wait(self, drive='drive0', force=False):
>> +    def cancel_and_wait(self, drive='drive0', force=False, resume=""):
>>           '''Cancel a block job and wait for it to finish, returning the event'''
>>           result = self.vm.qmp('block-job-cancel', device=drive, force=force)
>>           self.assert_qmp(result, 'return', {})
>>
>> +        if resume:
>> +            self.vm.qmp('human-monitor-command', command_line='qemu-io %s "resume %s"' % (drive, resume))
>> +
>>           cancelled = False
>>           result = None
>>           while not cancelled:
>>
>
> Can you do the same for the mirror test too?
>

Paolo,

Mirror doesn't complete automatically, so we don't need the sequence:

1) Pause IO on device.
2) Start job.
3) Send block job cancel/complete command to wire.
4) Resume IO.

Block stream/commit/backup need because without step 1) the job could 
complete after 2) but before 3), so the block-job-complete may get an 
error return (no job no device).

Is it?

So I'll review commit and backup cases then.

Fam
Paolo Bonzini Nov. 7, 2013, 11:33 a.m. UTC | #6
Il 07/11/2013 12:25, Fam Zheng ha scritto:
> Mirror doesn't complete automatically, so we don't need the sequence:
> 
> 1) Pause IO on device.
> 2) Start job.
> 3) Send block job cancel/complete command to wire.
> 4) Resume IO.
> 
> Block stream/commit/backup need because without step 1) the job could
> complete after 2) but before 3), so the block-job-complete may get an
> error return (no job no device).
> 
> Is it?

Yes.

> So I'll review commit and backup cases then.

Yes.

Paolo
diff mbox

Patch

diff --git a/tests/qemu-iotests/030 b/tests/qemu-iotests/030
index d0f96ea..bc66e6f 100755
--- a/tests/qemu-iotests/030
+++ b/tests/qemu-iotests/030
@@ -391,7 +391,7 @@  class TestStreamStop(iotests.QMPTestCase):
         qemu_io('-c', 'write -P 0x1 0 32M', backing_img)
         qemu_img('create', '-f', iotests.imgfmt, '-o', 'backing_file=%s' % backing_img, test_img)
         qemu_io('-c', 'write -P 0x1 32M 32M', test_img)
-        self.vm = iotests.VM().add_drive(test_img)
+        self.vm = iotests.VM().add_drive("blkdebug::" + test_img)
         self.vm.launch()
 
     def tearDown(self):
@@ -402,6 +402,7 @@  class TestStreamStop(iotests.QMPTestCase):
     def test_stream_stop(self):
         self.assert_no_active_block_jobs()
 
+        self.vm.qmp('human-monitor-command', command_line='qemu-io drive0 "break write_aio a"')
         result = self.vm.qmp('block-stream', device='drive0')
         self.assert_qmp(result, 'return', {})
 
@@ -409,7 +410,7 @@  class TestStreamStop(iotests.QMPTestCase):
         events = self.vm.get_qmp_events(wait=False)
         self.assertEqual(events, [], 'unexpected QMP event: %s' % events)
 
-        self.cancel_and_wait()
+        self.cancel_and_wait(resume='a')
 
 class TestSetSpeed(iotests.QMPTestCase):
     image_len = 80 * 1024 * 1024 # MB
@@ -419,7 +420,7 @@  class TestSetSpeed(iotests.QMPTestCase):
         qemu_io('-c', 'write -P 0x1 0 32M', backing_img)
         qemu_img('create', '-f', iotests.imgfmt, '-o', 'backing_file=%s' % backing_img, test_img)
         qemu_io('-c', 'write -P 0x1 32M 32M', test_img)
-        self.vm = iotests.VM().add_drive(test_img)
+        self.vm = iotests.VM().add_drive('blkdebug::' + test_img)
         self.vm.launch()
 
     def tearDown(self):
@@ -453,6 +454,7 @@  class TestSetSpeed(iotests.QMPTestCase):
     def test_set_speed(self):
         self.assert_no_active_block_jobs()
 
+        self.vm.qmp('human-monitor-command', command_line='qemu-io drive0 "break write_aio a"')
         result = self.vm.qmp('block-stream', device='drive0')
         self.assert_qmp(result, 'return', {})
 
@@ -469,7 +471,7 @@  class TestSetSpeed(iotests.QMPTestCase):
         self.assert_qmp(result, 'return[0]/device', 'drive0')
         self.assert_qmp(result, 'return[0]/speed', 8 * 1024 * 1024)
 
-        self.cancel_and_wait()
+        self.cancel_and_wait(resume='a')
 
         # Check setting speed in block-stream works
         result = self.vm.qmp('block-stream', device='drive0', speed=4 * 1024 * 1024)
diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py
index fb10ff4..de45079 100644
--- a/tests/qemu-iotests/iotests.py
+++ b/tests/qemu-iotests/iotests.py
@@ -222,11 +222,14 @@  class QMPTestCase(unittest.TestCase):
         result = self.vm.qmp('query-block-jobs')
         self.assert_qmp(result, 'return', [])
 
-    def cancel_and_wait(self, drive='drive0', force=False):
+    def cancel_and_wait(self, drive='drive0', force=False, resume=""):
         '''Cancel a block job and wait for it to finish, returning the event'''
         result = self.vm.qmp('block-job-cancel', device=drive, force=force)
         self.assert_qmp(result, 'return', {})
 
+        if resume:
+            self.vm.qmp('human-monitor-command', command_line='qemu-io %s "resume %s"' % (drive, resume))
+
         cancelled = False
         result = None
         while not cancelled: