1903cb1bfSPhilippe Mathieu-Daudé#!/usr/bin/env python3 29dd003a9SVladimir Sementsov-Ogievskiy# group: rw quick 33677e6f6SMax Reitz# 43677e6f6SMax Reitz# Test for additional information emitted by qemu-img info on qcow2 53677e6f6SMax Reitz# images 63677e6f6SMax Reitz# 73677e6f6SMax Reitz# Copyright (C) 2013 Red Hat, Inc. 83677e6f6SMax Reitz# 93677e6f6SMax Reitz# This program is free software; you can redistribute it and/or modify 103677e6f6SMax Reitz# it under the terms of the GNU General Public License as published by 113677e6f6SMax Reitz# the Free Software Foundation; either version 2 of the License, or 123677e6f6SMax Reitz# (at your option) any later version. 133677e6f6SMax Reitz# 143677e6f6SMax Reitz# This program is distributed in the hope that it will be useful, 153677e6f6SMax Reitz# but WITHOUT ANY WARRANTY; without even the implied warranty of 163677e6f6SMax Reitz# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 173677e6f6SMax Reitz# GNU General Public License for more details. 183677e6f6SMax Reitz# 193677e6f6SMax Reitz# You should have received a copy of the GNU General Public License 203677e6f6SMax Reitz# along with this program. If not, see <http://www.gnu.org/licenses/>. 213677e6f6SMax Reitz# 223677e6f6SMax Reitz 233677e6f6SMax Reitzimport os 243677e6f6SMax Reitzimport re 253677e6f6SMax Reitzimport json 263677e6f6SMax Reitzimport iotests 277253a570SHanna Reitzfrom iotests import qemu_img, qemu_img_info, supports_qcow2_zstd_compression 283677e6f6SMax Reitzimport unittest 293677e6f6SMax Reitz 303677e6f6SMax Reitztest_img = os.path.join(iotests.test_dir, 'test.img') 313677e6f6SMax Reitz 323677e6f6SMax Reitzclass TestImageInfoSpecific(iotests.QMPTestCase): 333677e6f6SMax Reitz '''Abstract base class for ImageInfoSpecific tests''' 343677e6f6SMax Reitz 353677e6f6SMax Reitz def setUp(self): 363677e6f6SMax Reitz if self.img_options is None: 373677e6f6SMax Reitz self.skipTest('Skipping abstract test class') 383677e6f6SMax Reitz qemu_img('create', '-f', iotests.imgfmt, '-o', self.img_options, 393677e6f6SMax Reitz test_img, '128K') 403677e6f6SMax Reitz 413677e6f6SMax Reitz def tearDown(self): 423677e6f6SMax Reitz os.remove(test_img) 433677e6f6SMax Reitz 443677e6f6SMax Reitzclass TestQemuImgInfo(TestImageInfoSpecific): 453677e6f6SMax Reitz '''Abstract base class for qemu-img info tests''' 463677e6f6SMax Reitz 473677e6f6SMax Reitz img_options = None 483677e6f6SMax Reitz json_compare = None 493677e6f6SMax Reitz human_compare = None 503677e6f6SMax Reitz 513677e6f6SMax Reitz def test_json(self): 529ebb2b76SJohn Snow data = qemu_img_info(test_img)['format-specific'] 533677e6f6SMax Reitz self.assertEqual(data['type'], iotests.imgfmt) 543677e6f6SMax Reitz self.assertEqual(data['data'], self.json_compare) 553677e6f6SMax Reitz 563677e6f6SMax Reitz def test_human(self): 574cf661f2SJohn Snow data = qemu_img('info', '--output=human', test_img).stdout.split('\n') 583677e6f6SMax Reitz data = data[(data.index('Format specific information:') + 1) 59*c04d0ab0SHanna Reitz :data.index("Child node '/file':")] 603677e6f6SMax Reitz for field in data: 613677e6f6SMax Reitz self.assertTrue(re.match('^ {4}[^ ]', field) is not None) 6268474776SMax Reitz data = [line.strip() for line in data] 633677e6f6SMax Reitz self.assertEqual(data, self.human_compare) 643677e6f6SMax Reitz 653677e6f6SMax Reitzclass TestQMP(TestImageInfoSpecific): 663677e6f6SMax Reitz '''Abstract base class for qemu QMP tests''' 673677e6f6SMax Reitz 683677e6f6SMax Reitz img_options = None 693677e6f6SMax Reitz qemu_options = '' 703677e6f6SMax Reitz TestImageInfoSpecific = TestImageInfoSpecific 713677e6f6SMax Reitz 723677e6f6SMax Reitz def setUp(self): 733677e6f6SMax Reitz self.TestImageInfoSpecific.setUp(self) 743677e6f6SMax Reitz self.vm = iotests.VM().add_drive(test_img, self.qemu_options) 753677e6f6SMax Reitz self.vm.launch() 763677e6f6SMax Reitz 773677e6f6SMax Reitz def tearDown(self): 783677e6f6SMax Reitz self.vm.shutdown() 793677e6f6SMax Reitz self.TestImageInfoSpecific.tearDown(self) 803677e6f6SMax Reitz 813677e6f6SMax Reitz def test_qmp(self): 823677e6f6SMax Reitz result = self.vm.qmp('query-block')['return'] 8368474776SMax Reitz drive = next(drive for drive in result if drive['device'] == 'drive0') 843677e6f6SMax Reitz data = drive['inserted']['image']['format-specific'] 853677e6f6SMax Reitz self.assertEqual(data['type'], iotests.imgfmt) 863677e6f6SMax Reitz self.assertEqual(data['data'], self.compare) 873677e6f6SMax Reitz 883677e6f6SMax Reitzclass TestQCow2(TestQemuImgInfo): 893677e6f6SMax Reitz '''Testing a qcow2 version 2 image''' 9012a93617SVladimir Sementsov-Ogievskiy img_options = 'compat=0.10,compression_type=zlib' 91572ad978SDenis Plotnikov json_compare = { 'compat': '0.10', 'refcount-bits': 16, 92572ad978SDenis Plotnikov 'compression-type': 'zlib' } 93572ad978SDenis Plotnikov human_compare = [ 'compat: 0.10', 'compression type: zlib', 94572ad978SDenis Plotnikov 'refcount bits: 16' ] 953677e6f6SMax Reitz 963677e6f6SMax Reitzclass TestQCow3NotLazy(TestQemuImgInfo): 973677e6f6SMax Reitz '''Testing a qcow2 version 3 image with lazy refcounts disabled''' 987253a570SHanna Reitz if supports_qcow2_zstd_compression(): 997253a570SHanna Reitz compression_type = 'zstd' 1007253a570SHanna Reitz else: 1017253a570SHanna Reitz compression_type = 'zlib' 1027253a570SHanna Reitz 1037253a570SHanna Reitz img_options = 'compat=1.1,lazy_refcounts=off' 1047253a570SHanna Reitz img_options += f',compression_type={compression_type}' 1050709c5a1SMax Reitz json_compare = { 'compat': '1.1', 'lazy-refcounts': False, 106572ad978SDenis Plotnikov 'refcount-bits': 16, 'corrupt': False, 1077253a570SHanna Reitz 'compression-type': compression_type, 'extended-l2': False } 1087253a570SHanna Reitz human_compare = [ 'compat: 1.1', f'compression type: {compression_type}', 109572ad978SDenis Plotnikov 'lazy refcounts: false', 'refcount bits: 16', 1107be20252SAlberto Garcia 'corrupt: false', 'extended l2: false' ] 1113677e6f6SMax Reitz 1123677e6f6SMax Reitzclass TestQCow3Lazy(TestQemuImgInfo): 1133677e6f6SMax Reitz '''Testing a qcow2 version 3 image with lazy refcounts enabled''' 11412a93617SVladimir Sementsov-Ogievskiy img_options = 'compat=1.1,lazy_refcounts=on,compression_type=zlib' 1150709c5a1SMax Reitz json_compare = { 'compat': '1.1', 'lazy-refcounts': True, 116572ad978SDenis Plotnikov 'refcount-bits': 16, 'corrupt': False, 1177be20252SAlberto Garcia 'compression-type': 'zlib', 'extended-l2': False } 118572ad978SDenis Plotnikov human_compare = [ 'compat: 1.1', 'compression type: zlib', 119572ad978SDenis Plotnikov 'lazy refcounts: true', 'refcount bits: 16', 1207be20252SAlberto Garcia 'corrupt: false', 'extended l2: false' ] 1213677e6f6SMax Reitz 1223677e6f6SMax Reitzclass TestQCow3NotLazyQMP(TestQMP): 1233677e6f6SMax Reitz '''Testing a qcow2 version 3 image with lazy refcounts disabled, opening 1243677e6f6SMax Reitz with lazy refcounts enabled''' 12512a93617SVladimir Sementsov-Ogievskiy img_options = 'compat=1.1,lazy_refcounts=off,compression_type=zlib' 1263677e6f6SMax Reitz qemu_options = 'lazy-refcounts=on' 1270709c5a1SMax Reitz compare = { 'compat': '1.1', 'lazy-refcounts': False, 128572ad978SDenis Plotnikov 'refcount-bits': 16, 'corrupt': False, 1297be20252SAlberto Garcia 'compression-type': 'zlib', 'extended-l2': False } 1300709c5a1SMax Reitz 1313677e6f6SMax Reitz 1323677e6f6SMax Reitzclass TestQCow3LazyQMP(TestQMP): 1333677e6f6SMax Reitz '''Testing a qcow2 version 3 image with lazy refcounts enabled, opening 1343677e6f6SMax Reitz with lazy refcounts disabled''' 1357253a570SHanna Reitz if supports_qcow2_zstd_compression(): 1367253a570SHanna Reitz compression_type = 'zstd' 1377253a570SHanna Reitz else: 1387253a570SHanna Reitz compression_type = 'zlib' 1397253a570SHanna Reitz 1407253a570SHanna Reitz img_options = 'compat=1.1,lazy_refcounts=on' 1417253a570SHanna Reitz img_options += f',compression_type={compression_type}' 1423677e6f6SMax Reitz qemu_options = 'lazy-refcounts=off' 1430709c5a1SMax Reitz compare = { 'compat': '1.1', 'lazy-refcounts': True, 144572ad978SDenis Plotnikov 'refcount-bits': 16, 'corrupt': False, 1457253a570SHanna Reitz 'compression-type': compression_type, 'extended-l2': False } 1463677e6f6SMax Reitz 1473677e6f6SMax ReitzTestImageInfoSpecific = None 1483677e6f6SMax ReitzTestQemuImgInfo = None 1493677e6f6SMax ReitzTestQMP = None 1503677e6f6SMax Reitz 1513677e6f6SMax Reitzif __name__ == '__main__': 152103cbc77SMax Reitz iotests.main(supported_fmts=['qcow2'], 153b30b8077SVladimir Sementsov-Ogievskiy supported_protocols=['file'], 154b30b8077SVladimir Sementsov-Ogievskiy unsupported_imgopts=['refcount_bits']) 155