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 27*9ebb2b76SJohn Snowfrom iotests import qemu_img, qemu_img_info, qemu_img_pipe 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): 52*9ebb2b76SJohn 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): 573677e6f6SMax Reitz data = qemu_img_pipe('info', '--output=human', test_img).split('\n') 583677e6f6SMax Reitz data = data[(data.index('Format specific information:') + 1) 593677e6f6SMax Reitz :data.index('')] 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''' 9812a93617SVladimir Sementsov-Ogievskiy img_options = 'compat=1.1,lazy_refcounts=off,compression_type=zstd' 990709c5a1SMax Reitz json_compare = { 'compat': '1.1', 'lazy-refcounts': False, 100572ad978SDenis Plotnikov 'refcount-bits': 16, 'corrupt': False, 10112a93617SVladimir Sementsov-Ogievskiy 'compression-type': 'zstd', 'extended-l2': False } 10212a93617SVladimir Sementsov-Ogievskiy human_compare = [ 'compat: 1.1', 'compression type: zstd', 103572ad978SDenis Plotnikov 'lazy refcounts: false', 'refcount bits: 16', 1047be20252SAlberto Garcia 'corrupt: false', 'extended l2: false' ] 1053677e6f6SMax Reitz 1063677e6f6SMax Reitzclass TestQCow3Lazy(TestQemuImgInfo): 1073677e6f6SMax Reitz '''Testing a qcow2 version 3 image with lazy refcounts enabled''' 10812a93617SVladimir Sementsov-Ogievskiy img_options = 'compat=1.1,lazy_refcounts=on,compression_type=zlib' 1090709c5a1SMax Reitz json_compare = { 'compat': '1.1', 'lazy-refcounts': True, 110572ad978SDenis Plotnikov 'refcount-bits': 16, 'corrupt': False, 1117be20252SAlberto Garcia 'compression-type': 'zlib', 'extended-l2': False } 112572ad978SDenis Plotnikov human_compare = [ 'compat: 1.1', 'compression type: zlib', 113572ad978SDenis Plotnikov 'lazy refcounts: true', 'refcount bits: 16', 1147be20252SAlberto Garcia 'corrupt: false', 'extended l2: false' ] 1153677e6f6SMax Reitz 1163677e6f6SMax Reitzclass TestQCow3NotLazyQMP(TestQMP): 1173677e6f6SMax Reitz '''Testing a qcow2 version 3 image with lazy refcounts disabled, opening 1183677e6f6SMax Reitz with lazy refcounts enabled''' 11912a93617SVladimir Sementsov-Ogievskiy img_options = 'compat=1.1,lazy_refcounts=off,compression_type=zlib' 1203677e6f6SMax Reitz qemu_options = 'lazy-refcounts=on' 1210709c5a1SMax Reitz compare = { 'compat': '1.1', 'lazy-refcounts': False, 122572ad978SDenis Plotnikov 'refcount-bits': 16, 'corrupt': False, 1237be20252SAlberto Garcia 'compression-type': 'zlib', 'extended-l2': False } 1240709c5a1SMax Reitz 1253677e6f6SMax Reitz 1263677e6f6SMax Reitzclass TestQCow3LazyQMP(TestQMP): 1273677e6f6SMax Reitz '''Testing a qcow2 version 3 image with lazy refcounts enabled, opening 1283677e6f6SMax Reitz with lazy refcounts disabled''' 12912a93617SVladimir Sementsov-Ogievskiy img_options = 'compat=1.1,lazy_refcounts=on,compression_type=zstd' 1303677e6f6SMax Reitz qemu_options = 'lazy-refcounts=off' 1310709c5a1SMax Reitz compare = { 'compat': '1.1', 'lazy-refcounts': True, 132572ad978SDenis Plotnikov 'refcount-bits': 16, 'corrupt': False, 13312a93617SVladimir Sementsov-Ogievskiy 'compression-type': 'zstd', 'extended-l2': False } 1343677e6f6SMax Reitz 1353677e6f6SMax ReitzTestImageInfoSpecific = None 1363677e6f6SMax ReitzTestQemuImgInfo = None 1373677e6f6SMax ReitzTestQMP = None 1383677e6f6SMax Reitz 1393677e6f6SMax Reitzif __name__ == '__main__': 140103cbc77SMax Reitz iotests.main(supported_fmts=['qcow2'], 141b30b8077SVladimir Sementsov-Ogievskiy supported_protocols=['file'], 142b30b8077SVladimir Sementsov-Ogievskiy unsupported_imgopts=['refcount_bits']) 143