Message ID | 1371209999-15579-13-git-send-email-xiawenc@linux.vnet.ibm.com |
---|---|
State | New |
Headers | show |
On Fri, Jun 14, 2013 at 07:39:59PM +0800, Wenchao Xia wrote: > Signed-off-by: Wenchao Xia <xiawenc@linux.vnet.ibm.com> > --- > tests/qemu-iotests/055 | 157 ++++++++++++++++++++++++++++++++++++++++++++ > tests/qemu-iotests/055.out | 5 ++ drive-backup already uses 055, please name it 056 to avoid conflicts. > tests/qemu-iotests/group | 1 + > 3 files changed, 163 insertions(+), 0 deletions(-) > create mode 100755 tests/qemu-iotests/055 > create mode 100644 tests/qemu-iotests/055.out > > diff --git a/tests/qemu-iotests/055 b/tests/qemu-iotests/055 > new file mode 100755 > index 0000000..7658f22 > --- /dev/null > +++ b/tests/qemu-iotests/055 > @@ -0,0 +1,157 @@ > +#!/usr/bin/env python > +# > +# Tests for internal snapshot. > +# Copyright (C) 2013 IBM ... Based on 055: > +# Copyright (C) 2012 Red Hat, Inc. > +# > +# This program is free software; you can redistribute it and/or modify > +# it under the terms of the GNU General Public License as published by > +# the Free Software Foundation; either version 2 of the License, or > +# (at your option) any later version. > +# > +# This program is distributed in the hope that it will be useful, > +# but WITHOUT ANY WARRANTY; without even the implied warranty of > +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > +# GNU General Public License for more details. > +# > +# You should have received a copy of the GNU General Public License > +# along with this program. If not, see <http://www.gnu.org/licenses/>. > +# > + > +import time > +import os > +import iotests > +from iotests import qemu_img, qemu_io > + > +test_drv_base_name = 'drive' > + > +class ImageSnapshotTestCase(iotests.QMPTestCase): > + image_len = 120 * 1024 * 1024 # MB > + > + def __init__(self, *args): > + self.expect = [] > + super(ImageSnapshotTestCase, self).__init__(*args) > + > + def _setUp(self, test_img_base_name, image_num): > + self.vm = iotests.VM() > + for i in range(0, image_num): > + filename = '%s%d' % (test_img_base_name, i) > + img = os.path.join(iotests.test_dir, filename) > + device = '%s%d' % (test_drv_base_name, i) > + qemu_img('create', '-f', iotests.imgfmt, img, str(self.image_len)) > + self.vm.add_drive(img) > + self.expect.append({'image': img, 'device': device, > + 'snapshots': [], 'snapshots_name_counter': 0}) > + self.vm.launch() > + > + def tearDown(self): > + self.vm.shutdown() > + for i in range(0, len(self.expect)): > + os.remove(self.expect[i]['image']) > + > + def createSnapshotInTransaction(self, snapshot_num): > + actions = [] > + for i in range(0, len(self.expect)): > + num = self.expect[i]['snapshots_name_counter'] > + for j in range(0, snapshot_num): > + name = '%s_sn%d' % (self.expect[i]['device'], num) > + num = num + 1 > + self.expect[i]['snapshots'].append(name) > + actions.append({ > + 'type': 'blockdev-snapshot-internal-sync', > + 'data': { 'device': self.expect[i]['device'], > + 'name': name }, > + }) > + self.expect[i]['snapshots_name_counter'] = num > + result = self.vm.qmp('transaction', actions = actions) > + self.assert_qmp(result, 'return', {}) This tests the success case. Please also use the 'Abort' action to test the error case. > + def verifySnapshotInfo(self): > + expect = self.expect > + result = self.vm.qmp('query-block') > + for i in range(0, len(expect)): > + image = None > + for device in result['return']: > + if device['device'] == expect[i]['device']: > + image = device['inserted']['image'] > + break > + self.assertTrue(image != None) > + self.assertTrue(len(image['snapshots']) == > + len(expect[i]['snapshots'])) > + for j in range(0, len(image['snapshots'])): > + try: > + expect[i]['snapshots'].index(image['snapshots'][j]['name']) > + except: > + print 'not full match, image info:\n%s\n, expect:%s\n' % \ > + (str(image), str(expect)) > + self.assertTrue(False) > + > + def deleteSnapshot(self, device, name): > + result = self.vm.qmp('blockdev-snapshot-delete-internal-sync', > + device = device, > + name = name) > + self.assert_qmp(result, 'return', {}) > + expect = self.expect > + sn_list_expect = None > + for i in range(0, len(expect)): > + if expect[i]['device'] == device : > + sn_list_expect = expect[i]['snapshots'] > + break > + self.assertTrue(sn_list_expect != None) > + try: > + sn_list_expect.remove(name) > + except: > + print 'snapshot %s not found in expect:\n%s\n' % \ > + (name, str(expect)) > + self.assertTrue(False) > + > +class TestSingleTransaction(ImageSnapshotTestCase): > + def setUp(self): > + self._setUp('test_a.img', 1) > + > + def test_create(self): > + self.createSnapshotInTransaction(1) > + self.verifySnapshotInfo() > + > + def test_error_name(self): > + actions = [{'type': 'blockdev-snapshot-internal-sync', > + 'data': { 'device': self.expect[0]['device'], > + 'name': '1234' }, > + }] > + result = self.vm.qmp('transaction', actions = actions) > + self.assert_qmp(result, 'error/class', 'GenericError') Please check that empty names error too.
于 2013-6-18 22:32, Stefan Hajnoczi 写道: > On Fri, Jun 14, 2013 at 07:39:59PM +0800, Wenchao Xia wrote: >> Signed-off-by: Wenchao Xia <xiawenc@linux.vnet.ibm.com> >> --- >> tests/qemu-iotests/055 | 157 ++++++++++++++++++++++++++++++++++++++++++++ >> tests/qemu-iotests/055.out | 5 ++ > > drive-backup already uses 055, please name it 056 to avoid conflicts. > OK. >> tests/qemu-iotests/group | 1 + >> 3 files changed, 163 insertions(+), 0 deletions(-) >> create mode 100755 tests/qemu-iotests/055 >> create mode 100644 tests/qemu-iotests/055.out >> >> diff --git a/tests/qemu-iotests/055 b/tests/qemu-iotests/055 >> new file mode 100755 >> index 0000000..7658f22 >> --- /dev/null >> +++ b/tests/qemu-iotests/055 >> @@ -0,0 +1,157 @@ >> +#!/usr/bin/env python >> +# >> +# Tests for internal snapshot. >> +# > > Copyright (C) 2013 IBM ... > > Based on 055: > oops.... >> +# Copyright (C) 2012 Red Hat, Inc. >> +# >> +# This program is free software; you can redistribute it and/or modify >> +# it under the terms of the GNU General Public License as published by >> +# the Free Software Foundation; either version 2 of the License, or >> +# (at your option) any later version. >> +# >> +# This program is distributed in the hope that it will be useful, >> +# but WITHOUT ANY WARRANTY; without even the implied warranty of >> +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the >> +# GNU General Public License for more details. >> +# >> +# You should have received a copy of the GNU General Public License >> +# along with this program. If not, see <http://www.gnu.org/licenses/>. >> +# >> + >> +import time >> +import os >> +import iotests >> +from iotests import qemu_img, qemu_io >> + >> +test_drv_base_name = 'drive' >> + >> +class ImageSnapshotTestCase(iotests.QMPTestCase): >> + image_len = 120 * 1024 * 1024 # MB >> + >> + def __init__(self, *args): >> + self.expect = [] >> + super(ImageSnapshotTestCase, self).__init__(*args) >> + >> + def _setUp(self, test_img_base_name, image_num): >> + self.vm = iotests.VM() >> + for i in range(0, image_num): >> + filename = '%s%d' % (test_img_base_name, i) >> + img = os.path.join(iotests.test_dir, filename) >> + device = '%s%d' % (test_drv_base_name, i) >> + qemu_img('create', '-f', iotests.imgfmt, img, str(self.image_len)) >> + self.vm.add_drive(img) >> + self.expect.append({'image': img, 'device': device, >> + 'snapshots': [], 'snapshots_name_counter': 0}) >> + self.vm.launch() >> + >> + def tearDown(self): >> + self.vm.shutdown() >> + for i in range(0, len(self.expect)): >> + os.remove(self.expect[i]['image']) >> + >> + def createSnapshotInTransaction(self, snapshot_num): >> + actions = [] >> + for i in range(0, len(self.expect)): >> + num = self.expect[i]['snapshots_name_counter'] >> + for j in range(0, snapshot_num): >> + name = '%s_sn%d' % (self.expect[i]['device'], num) >> + num = num + 1 >> + self.expect[i]['snapshots'].append(name) >> + actions.append({ >> + 'type': 'blockdev-snapshot-internal-sync', >> + 'data': { 'device': self.expect[i]['device'], >> + 'name': name }, >> + }) >> + self.expect[i]['snapshots_name_counter'] = num >> + result = self.vm.qmp('transaction', actions = actions) >> + self.assert_qmp(result, 'return', {}) > > This tests the success case. Please also use the 'Abort' action to test > the error case. Is "Abort" upstreamed? If yes I will add that part. > >> + def verifySnapshotInfo(self): >> + expect = self.expect >> + result = self.vm.qmp('query-block') >> + for i in range(0, len(expect)): >> + image = None >> + for device in result['return']: >> + if device['device'] == expect[i]['device']: >> + image = device['inserted']['image'] >> + break >> + self.assertTrue(image != None) >> + self.assertTrue(len(image['snapshots']) == >> + len(expect[i]['snapshots'])) >> + for j in range(0, len(image['snapshots'])): >> + try: >> + expect[i]['snapshots'].index(image['snapshots'][j]['name']) >> + except: >> + print 'not full match, image info:\n%s\n, expect:%s\n' % \ >> + (str(image), str(expect)) >> + self.assertTrue(False) >> + >> + def deleteSnapshot(self, device, name): >> + result = self.vm.qmp('blockdev-snapshot-delete-internal-sync', >> + device = device, >> + name = name) >> + self.assert_qmp(result, 'return', {}) >> + expect = self.expect >> + sn_list_expect = None >> + for i in range(0, len(expect)): >> + if expect[i]['device'] == device : >> + sn_list_expect = expect[i]['snapshots'] >> + break >> + self.assertTrue(sn_list_expect != None) >> + try: >> + sn_list_expect.remove(name) >> + except: >> + print 'snapshot %s not found in expect:\n%s\n' % \ >> + (name, str(expect)) >> + self.assertTrue(False) >> + >> +class TestSingleTransaction(ImageSnapshotTestCase): >> + def setUp(self): >> + self._setUp('test_a.img', 1) >> + >> + def test_create(self): >> + self.createSnapshotInTransaction(1) >> + self.verifySnapshotInfo() >> + >> + def test_error_name(self): >> + actions = [{'type': 'blockdev-snapshot-internal-sync', >> + 'data': { 'device': self.expect[0]['device'], >> + 'name': '1234' }, >> + }] >> + result = self.vm.qmp('transaction', actions = actions) >> + self.assert_qmp(result, 'error/class', 'GenericError') > > Please check that empty names error too. > OK.
On Wed, Jun 19, 2013 at 02:21:31PM +0800, Wenchao Xia wrote: > 于 2013-6-18 22:32, Stefan Hajnoczi 写道: > >On Fri, Jun 14, 2013 at 07:39:59PM +0800, Wenchao Xia wrote: > >>+ def createSnapshotInTransaction(self, snapshot_num): > >>+ actions = [] > >>+ for i in range(0, len(self.expect)): > >>+ num = self.expect[i]['snapshots_name_counter'] > >>+ for j in range(0, snapshot_num): > >>+ name = '%s_sn%d' % (self.expect[i]['device'], num) > >>+ num = num + 1 > >>+ self.expect[i]['snapshots'].append(name) > >>+ actions.append({ > >>+ 'type': 'blockdev-snapshot-internal-sync', > >>+ 'data': { 'device': self.expect[i]['device'], > >>+ 'name': name }, > >>+ }) > >>+ self.expect[i]['snapshots_name_counter'] = num > >>+ result = self.vm.qmp('transaction', actions = actions) > >>+ self.assert_qmp(result, 'return', {}) > > > >This tests the success case. Please also use the 'Abort' action to test > >the error case. > Is "Abort" upstreamed? If yes I will add that part. It's part of the drive-backup series which you have already cherry-picked from.
> On Wed, Jun 19, 2013 at 02:21:31PM +0800, Wenchao Xia wrote: >> 于 2013-6-18 22:32, Stefan Hajnoczi 写道: >>> On Fri, Jun 14, 2013 at 07:39:59PM +0800, Wenchao Xia wrote: >>>> + def createSnapshotInTransaction(self, snapshot_num): >>>> + actions = [] >>>> + for i in range(0, len(self.expect)): >>>> + num = self.expect[i]['snapshots_name_counter'] >>>> + for j in range(0, snapshot_num): >>>> + name = '%s_sn%d' % (self.expect[i]['device'], num) >>>> + num = num + 1 >>>> + self.expect[i]['snapshots'].append(name) >>>> + actions.append({ >>>> + 'type': 'blockdev-snapshot-internal-sync', >>>> + 'data': { 'device': self.expect[i]['device'], >>>> + 'name': name }, >>>> + }) >>>> + self.expect[i]['snapshots_name_counter'] = num >>>> + result = self.vm.qmp('transaction', actions = actions) >>>> + self.assert_qmp(result, 'return', {}) >>> >>> This tests the success case. Please also use the 'Abort' action to test >>> the error case. >> Is "Abort" upstreamed? If yes I will add that part. > > It's part of the drive-backup series which you have already > cherry-picked from. > Will you continue work on drive-backup? I'd like to rebase this serial after your v6, to reduce conflict.
On Wed, Jun 19, 2013 at 05:01:35PM +0800, Wenchao Xia wrote: > > On Wed, Jun 19, 2013 at 02:21:31PM +0800, Wenchao Xia wrote: > >>于 2013-6-18 22:32, Stefan Hajnoczi 写道: > >>>On Fri, Jun 14, 2013 at 07:39:59PM +0800, Wenchao Xia wrote: > >>>>+ def createSnapshotInTransaction(self, snapshot_num): > >>>>+ actions = [] > >>>>+ for i in range(0, len(self.expect)): > >>>>+ num = self.expect[i]['snapshots_name_counter'] > >>>>+ for j in range(0, snapshot_num): > >>>>+ name = '%s_sn%d' % (self.expect[i]['device'], num) > >>>>+ num = num + 1 > >>>>+ self.expect[i]['snapshots'].append(name) > >>>>+ actions.append({ > >>>>+ 'type': 'blockdev-snapshot-internal-sync', > >>>>+ 'data': { 'device': self.expect[i]['device'], > >>>>+ 'name': name }, > >>>>+ }) > >>>>+ self.expect[i]['snapshots_name_counter'] = num > >>>>+ result = self.vm.qmp('transaction', actions = actions) > >>>>+ self.assert_qmp(result, 'return', {}) > >>> > >>>This tests the success case. Please also use the 'Abort' action to test > >>>the error case. > >> Is "Abort" upstreamed? If yes I will add that part. > > > >It's part of the drive-backup series which you have already > >cherry-picked from. > > > Will you continue work on drive-backup? I'd like to rebase this > serial after your v6, to reduce conflict. Yep, I'll send another revision soon. Kevin has been reviewing it today. Stefan
diff --git a/tests/qemu-iotests/055 b/tests/qemu-iotests/055 new file mode 100755 index 0000000..7658f22 --- /dev/null +++ b/tests/qemu-iotests/055 @@ -0,0 +1,157 @@ +#!/usr/bin/env python +# +# Tests for internal snapshot. +# +# Copyright (C) 2012 Red Hat, Inc. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# + +import time +import os +import iotests +from iotests import qemu_img, qemu_io + +test_drv_base_name = 'drive' + +class ImageSnapshotTestCase(iotests.QMPTestCase): + image_len = 120 * 1024 * 1024 # MB + + def __init__(self, *args): + self.expect = [] + super(ImageSnapshotTestCase, self).__init__(*args) + + def _setUp(self, test_img_base_name, image_num): + self.vm = iotests.VM() + for i in range(0, image_num): + filename = '%s%d' % (test_img_base_name, i) + img = os.path.join(iotests.test_dir, filename) + device = '%s%d' % (test_drv_base_name, i) + qemu_img('create', '-f', iotests.imgfmt, img, str(self.image_len)) + self.vm.add_drive(img) + self.expect.append({'image': img, 'device': device, + 'snapshots': [], 'snapshots_name_counter': 0}) + self.vm.launch() + + def tearDown(self): + self.vm.shutdown() + for i in range(0, len(self.expect)): + os.remove(self.expect[i]['image']) + + def createSnapshotInTransaction(self, snapshot_num): + actions = [] + for i in range(0, len(self.expect)): + num = self.expect[i]['snapshots_name_counter'] + for j in range(0, snapshot_num): + name = '%s_sn%d' % (self.expect[i]['device'], num) + num = num + 1 + self.expect[i]['snapshots'].append(name) + actions.append({ + 'type': 'blockdev-snapshot-internal-sync', + 'data': { 'device': self.expect[i]['device'], + 'name': name }, + }) + self.expect[i]['snapshots_name_counter'] = num + result = self.vm.qmp('transaction', actions = actions) + self.assert_qmp(result, 'return', {}) + + def verifySnapshotInfo(self): + expect = self.expect + result = self.vm.qmp('query-block') + for i in range(0, len(expect)): + image = None + for device in result['return']: + if device['device'] == expect[i]['device']: + image = device['inserted']['image'] + break + self.assertTrue(image != None) + self.assertTrue(len(image['snapshots']) == + len(expect[i]['snapshots'])) + for j in range(0, len(image['snapshots'])): + try: + expect[i]['snapshots'].index(image['snapshots'][j]['name']) + except: + print 'not full match, image info:\n%s\n, expect:%s\n' % \ + (str(image), str(expect)) + self.assertTrue(False) + + def deleteSnapshot(self, device, name): + result = self.vm.qmp('blockdev-snapshot-delete-internal-sync', + device = device, + name = name) + self.assert_qmp(result, 'return', {}) + expect = self.expect + sn_list_expect = None + for i in range(0, len(expect)): + if expect[i]['device'] == device : + sn_list_expect = expect[i]['snapshots'] + break + self.assertTrue(sn_list_expect != None) + try: + sn_list_expect.remove(name) + except: + print 'snapshot %s not found in expect:\n%s\n' % \ + (name, str(expect)) + self.assertTrue(False) + +class TestSingleTransaction(ImageSnapshotTestCase): + def setUp(self): + self._setUp('test_a.img', 1) + + def test_create(self): + self.createSnapshotInTransaction(1) + self.verifySnapshotInfo() + + def test_error_name(self): + actions = [{'type': 'blockdev-snapshot-internal-sync', + 'data': { 'device': self.expect[0]['device'], + 'name': '1234' }, + }] + result = self.vm.qmp('transaction', actions = actions) + self.assert_qmp(result, 'error/class', 'GenericError') + + def test_error_device(self): + actions = [{'type': 'blockdev-snapshot-internal-sync', + 'data': { 'device': 'driveerror', + 'name': 'a' }, + }] + result = self.vm.qmp('transaction', actions = actions) + self.assert_qmp(result, 'error/class', 'DeviceNotFound') + + def test_error_exist(self): + self.createSnapshotInTransaction(1) + self.verifySnapshotInfo() + actions = [{'type': 'blockdev-snapshot-internal-sync', + 'data': { 'device': self.expect[0]['device'], + 'name': self.expect[0]['snapshots'][0] }, + }] + result = self.vm.qmp('transaction', actions = actions) + self.assert_qmp(result, 'error/class', 'GenericError') + +class TestMultipleTransaction(ImageSnapshotTestCase): + def setUp(self): + self._setUp('test_b.img', 2) + + def test_create(self): + self.createSnapshotInTransaction(3) + self.verifySnapshotInfo() + + def test_delete(self): + self.createSnapshotInTransaction(3) + self.verifySnapshotInfo() + self.deleteSnapshot(self.expect[0]['device'], self.expect[0]['snapshots'][1]) + self.verifySnapshotInfo() + +if __name__ == '__main__': + iotests.main(supported_fmts=['qcow2']) diff --git a/tests/qemu-iotests/055.out b/tests/qemu-iotests/055.out new file mode 100644 index 0000000..3f8a935 --- /dev/null +++ b/tests/qemu-iotests/055.out @@ -0,0 +1,5 @@ +...... +---------------------------------------------------------------------- +Ran 6 tests + +OK diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group index 387b050..e5762f9 100644 --- a/tests/qemu-iotests/group +++ b/tests/qemu-iotests/group @@ -61,3 +61,4 @@ 052 rw auto backing 053 rw auto 054 rw auto +055 rw auto
Signed-off-by: Wenchao Xia <xiawenc@linux.vnet.ibm.com> --- tests/qemu-iotests/055 | 157 ++++++++++++++++++++++++++++++++++++++++++++ tests/qemu-iotests/055.out | 5 ++ tests/qemu-iotests/group | 1 + 3 files changed, 163 insertions(+), 0 deletions(-) create mode 100755 tests/qemu-iotests/055 create mode 100644 tests/qemu-iotests/055.out