cirrus: fix off-by-one in cirrus_bitblt_rop_bkwd_transp_*_16
[qemu.git] / tests / qemu-iotests / 118
1 #!/usr/bin/env python
2 #
3 # Test case for the QMP 'change' command and all other associated
4 # commands
5 #
6 # Copyright (C) 2015 Red Hat, Inc.
7 #
8 # This program is free software; you can redistribute it and/or modify
9 # it under the terms of the GNU General Public License as published by
10 # the Free Software Foundation; either version 2 of the License, or
11 # (at your option) any later version.
12 #
13 # This program is distributed in the hope that it will be useful,
14 # but WITHOUT ANY WARRANTY; without even the implied warranty of
15 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 # GNU General Public License for more details.
17 #
18 # You should have received a copy of the GNU General Public License
19 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
20 #
21
22 import os
23 import stat
24 import time
25 import iotests
26 from iotests import qemu_img
27
28 old_img = os.path.join(iotests.test_dir, 'test0.img')
29 new_img = os.path.join(iotests.test_dir, 'test1.img')
30
31 class ChangeBaseClass(iotests.QMPTestCase):
32     has_opened = False
33     has_closed = False
34
35     def process_events(self):
36         for event in self.vm.get_qmp_events(wait=False):
37             if (event['event'] == 'DEVICE_TRAY_MOVED' and
38                 event['data']['device'] == 'drive0'):
39                 if event['data']['tray-open'] == False:
40                     self.has_closed = True
41                 else:
42                     self.has_opened = True
43
44     def wait_for_open(self):
45         if not self.has_real_tray:
46             return
47
48         timeout = time.clock() + 3
49         while not self.has_opened and time.clock() < timeout:
50             self.process_events()
51         if not self.has_opened:
52             self.fail('Timeout while waiting for the tray to open')
53
54     def wait_for_close(self):
55         if not self.has_real_tray:
56             return
57
58         timeout = time.clock() + 3
59         while not self.has_closed and time.clock() < timeout:
60             self.process_events()
61         if not self.has_opened:
62             self.fail('Timeout while waiting for the tray to close')
63
64 class GeneralChangeTestsBaseClass(ChangeBaseClass):
65
66     device_name = None
67
68     def test_change(self):
69         result = self.vm.qmp('change', device='drive0', target=new_img,
70                                        arg=iotests.imgfmt)
71         self.assert_qmp(result, 'return', {})
72
73         self.wait_for_open()
74         self.wait_for_close()
75
76         result = self.vm.qmp('query-block')
77         if self.has_real_tray:
78             self.assert_qmp(result, 'return[0]/tray_open', False)
79         self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img)
80
81     def test_blockdev_change_medium(self):
82         if self.device_name is not None:
83             result = self.vm.qmp('blockdev-change-medium',
84                                  id=self.device_name, filename=new_img,
85                                  format=iotests.imgfmt)
86         else:
87             result = self.vm.qmp('blockdev-change-medium',
88                                  device='drive0', filename=new_img,
89                                  format=iotests.imgfmt)
90
91         self.assert_qmp(result, 'return', {})
92
93         self.wait_for_open()
94         self.wait_for_close()
95
96         result = self.vm.qmp('query-block')
97         if self.has_real_tray:
98             self.assert_qmp(result, 'return[0]/tray_open', False)
99         self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img)
100
101     def test_eject(self):
102         if self.device_name is not None:
103             result = self.vm.qmp('eject', id=self.device_name, force=True)
104         else:
105             result = self.vm.qmp('eject', device='drive0', force=True)
106         self.assert_qmp(result, 'return', {})
107
108         self.wait_for_open()
109
110         result = self.vm.qmp('query-block')
111         if self.has_real_tray:
112             self.assert_qmp(result, 'return[0]/tray_open', True)
113         self.assert_qmp_absent(result, 'return[0]/inserted')
114
115     def test_tray_eject_change(self):
116         if self.device_name is not None:
117             result = self.vm.qmp('eject', id=self.device_name, force=True)
118         else:
119             result = self.vm.qmp('eject', device='drive0', force=True)
120         self.assert_qmp(result, 'return', {})
121
122         self.wait_for_open()
123
124         result = self.vm.qmp('query-block')
125         if self.has_real_tray:
126             self.assert_qmp(result, 'return[0]/tray_open', True)
127         self.assert_qmp_absent(result, 'return[0]/inserted')
128
129         if self.device_name is not None:
130             result = self.vm.qmp('blockdev-change-medium', id=self.device_name,
131                                  filename=new_img, format=iotests.imgfmt)
132         else:
133             result = self.vm.qmp('blockdev-change-medium', device='drive0',
134                                  filename=new_img, format=iotests.imgfmt)
135         self.assert_qmp(result, 'return', {})
136
137         self.wait_for_close()
138
139         result = self.vm.qmp('query-block')
140         if self.has_real_tray:
141             self.assert_qmp(result, 'return[0]/tray_open', False)
142         self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img)
143
144     def test_tray_open_close(self):
145         if self.device_name is not None:
146             result = self.vm.qmp('blockdev-open-tray',
147                                  id=self.device_name, force=True)
148         else:
149             result = self.vm.qmp('blockdev-open-tray',
150                                  device='drive0', force=True)
151         self.assert_qmp(result, 'return', {})
152
153         self.wait_for_open()
154
155         result = self.vm.qmp('query-block')
156         if self.has_real_tray:
157             self.assert_qmp(result, 'return[0]/tray_open', True)
158         if self.was_empty == True:
159             self.assert_qmp_absent(result, 'return[0]/inserted')
160         else:
161             self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img)
162
163         if self.device_name is not None:
164             result = self.vm.qmp('blockdev-close-tray', id=self.device_name)
165         else:
166             result = self.vm.qmp('blockdev-close-tray', device='drive0')
167         self.assert_qmp(result, 'return', {})
168
169         if self.has_real_tray or not self.was_empty:
170             self.wait_for_close()
171
172         result = self.vm.qmp('query-block')
173         if self.has_real_tray:
174             self.assert_qmp(result, 'return[0]/tray_open', False)
175         if self.was_empty == True:
176             self.assert_qmp_absent(result, 'return[0]/inserted')
177         else:
178             self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img)
179
180     def test_tray_eject_close(self):
181         result = self.vm.qmp('eject', device='drive0', force=True)
182         self.assert_qmp(result, 'return', {})
183
184         self.wait_for_open()
185
186         result = self.vm.qmp('query-block')
187         if self.has_real_tray:
188             self.assert_qmp(result, 'return[0]/tray_open', True)
189         self.assert_qmp_absent(result, 'return[0]/inserted')
190
191         if self.device_name is not None:
192             result = self.vm.qmp('blockdev-close-tray', id=self.device_name)
193         else:
194             result = self.vm.qmp('blockdev-close-tray', device='drive0')
195         self.assert_qmp(result, 'return', {})
196
197         self.wait_for_close()
198
199         result = self.vm.qmp('query-block')
200         if self.has_real_tray:
201             self.assert_qmp(result, 'return[0]/tray_open', False)
202         self.assert_qmp_absent(result, 'return[0]/inserted')
203
204     def test_tray_open_change(self):
205         result = self.vm.qmp('blockdev-open-tray', device='drive0', force=True)
206         self.assert_qmp(result, 'return', {})
207
208         self.wait_for_open()
209
210         result = self.vm.qmp('query-block')
211         if self.has_real_tray:
212             self.assert_qmp(result, 'return[0]/tray_open', True)
213         if self.was_empty == True:
214             self.assert_qmp_absent(result, 'return[0]/inserted')
215         else:
216             self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img)
217
218         result = self.vm.qmp('blockdev-change-medium', device='drive0',
219                                                        filename=new_img,
220                                                        format=iotests.imgfmt)
221         self.assert_qmp(result, 'return', {})
222
223         self.wait_for_close()
224
225         result = self.vm.qmp('query-block')
226         if self.has_real_tray:
227             self.assert_qmp(result, 'return[0]/tray_open', False)
228         self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img)
229
230     def test_cycle(self):
231         result = self.vm.qmp('blockdev-add',
232                              node_name='new',
233                              driver=iotests.imgfmt,
234                              file={'filename': new_img,
235                                     'driver': 'file'})
236         self.assert_qmp(result, 'return', {})
237
238         if self.device_name is not None:
239             result = self.vm.qmp('blockdev-open-tray',
240                                  id=self.device_name, force=True)
241         else:
242             result = self.vm.qmp('blockdev-open-tray',
243                                  device='drive0', force=True)
244         self.assert_qmp(result, 'return', {})
245
246         self.wait_for_open()
247
248         result = self.vm.qmp('query-block')
249         if self.has_real_tray:
250             self.assert_qmp(result, 'return[0]/tray_open', True)
251         if self.was_empty == True:
252             self.assert_qmp_absent(result, 'return[0]/inserted')
253         else:
254             self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img)
255
256         if self.device_name is not None:
257             result = self.vm.qmp('x-blockdev-remove-medium',
258                                  id=self.device_name)
259         else:
260             result = self.vm.qmp('x-blockdev-remove-medium', device='drive0')
261         self.assert_qmp(result, 'return', {})
262
263         result = self.vm.qmp('query-block')
264         if self.has_real_tray:
265             self.assert_qmp(result, 'return[0]/tray_open', True)
266         self.assert_qmp_absent(result, 'return[0]/inserted')
267
268         if self.device_name is not None:
269             result = self.vm.qmp('x-blockdev-insert-medium',
270                                  id=self.device_name, node_name='new')
271         else:
272             result = self.vm.qmp('x-blockdev-insert-medium',
273                                  device='drive0', node_name='new')
274         self.assert_qmp(result, 'return', {})
275
276         result = self.vm.qmp('query-block')
277         if self.has_real_tray:
278             self.assert_qmp(result, 'return[0]/tray_open', True)
279         self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img)
280
281         if self.device_name is not None:
282             result = self.vm.qmp('blockdev-close-tray', id=self.device_name)
283         else:
284             result = self.vm.qmp('blockdev-close-tray', device='drive0')
285         self.assert_qmp(result, 'return', {})
286
287         self.wait_for_close()
288
289         result = self.vm.qmp('query-block')
290         if self.has_real_tray:
291             self.assert_qmp(result, 'return[0]/tray_open', False)
292         self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img)
293
294     def test_close_on_closed(self):
295         result = self.vm.qmp('blockdev-close-tray', device='drive0')
296         # Should be a no-op
297         self.assert_qmp(result, 'return', {})
298         self.assertEquals(self.vm.get_qmp_events(wait=False), [])
299
300     def test_remove_on_closed(self):
301         if not self.has_real_tray:
302             return
303
304         result = self.vm.qmp('x-blockdev-remove-medium', device='drive0')
305         self.assert_qmp(result, 'error/class', 'GenericError')
306
307     def test_insert_on_closed(self):
308         if not self.has_real_tray:
309             return
310
311         result = self.vm.qmp('blockdev-add',
312                              node_name='new',
313                              driver=iotests.imgfmt,
314                              file={'filename': new_img,
315                                    'driver': 'file'})
316         self.assert_qmp(result, 'return', {})
317
318         result = self.vm.qmp('x-blockdev-insert-medium', device='drive0',
319                                                        node_name='new')
320         self.assert_qmp(result, 'error/class', 'GenericError')
321
322 class TestInitiallyFilled(GeneralChangeTestsBaseClass):
323     was_empty = False
324
325     def setUp(self, media, interface):
326         qemu_img('create', '-f', iotests.imgfmt, old_img, '1440k')
327         qemu_img('create', '-f', iotests.imgfmt, new_img, '1440k')
328         self.vm = iotests.VM()
329         if interface == 'ide':
330             self.device_name = 'qdev0'
331             self.vm.add_drive(old_img, 'media=%s' % media, 'none')
332             self.vm.add_device('ide-cd,drive=drive0,id=%s' % self.device_name)
333         else:
334             self.vm.add_drive(old_img, 'media=%s' % media, interface)
335         self.vm.launch()
336
337     def tearDown(self):
338         self.vm.shutdown()
339         os.remove(old_img)
340         os.remove(new_img)
341
342     def test_insert_on_filled(self):
343         result = self.vm.qmp('blockdev-add',
344                              node_name='new',
345                              driver=iotests.imgfmt,
346                              file={'filename': new_img,
347                                    'driver': 'file'})
348         self.assert_qmp(result, 'return', {})
349
350         result = self.vm.qmp('blockdev-open-tray', device='drive0')
351         self.assert_qmp(result, 'return', {})
352
353         self.wait_for_open()
354
355         result = self.vm.qmp('x-blockdev-insert-medium', device='drive0',
356                                                        node_name='new')
357         self.assert_qmp(result, 'error/class', 'GenericError')
358
359 class TestInitiallyEmpty(GeneralChangeTestsBaseClass):
360     was_empty = True
361
362     def setUp(self, media, interface):
363         qemu_img('create', '-f', iotests.imgfmt, new_img, '1440k')
364         self.vm = iotests.VM().add_drive(None, 'media=%s' % media, interface)
365         self.vm.launch()
366
367     def tearDown(self):
368         self.vm.shutdown()
369         os.remove(new_img)
370
371     def test_remove_on_empty(self):
372         result = self.vm.qmp('blockdev-open-tray', device='drive0')
373         self.assert_qmp(result, 'return', {})
374
375         self.wait_for_open()
376
377         result = self.vm.qmp('x-blockdev-remove-medium', device='drive0')
378         # Should be a no-op
379         self.assert_qmp(result, 'return', {})
380
381 class TestCDInitiallyFilled(TestInitiallyFilled):
382     TestInitiallyFilled = TestInitiallyFilled
383     has_real_tray = True
384
385     def setUp(self):
386         self.TestInitiallyFilled.setUp(self, 'cdrom', 'ide')
387
388 class TestCDInitiallyEmpty(TestInitiallyEmpty):
389     TestInitiallyEmpty = TestInitiallyEmpty
390     has_real_tray = True
391
392     def setUp(self):
393         self.TestInitiallyEmpty.setUp(self, 'cdrom', 'ide')
394
395 class TestFloppyInitiallyFilled(TestInitiallyFilled):
396     TestInitiallyFilled = TestInitiallyFilled
397     has_real_tray = False
398
399     def setUp(self):
400         self.TestInitiallyFilled.setUp(self, 'disk', 'floppy')
401
402 class TestFloppyInitiallyEmpty(TestInitiallyEmpty):
403     TestInitiallyEmpty = TestInitiallyEmpty
404     has_real_tray = False
405
406     def setUp(self):
407         self.TestInitiallyEmpty.setUp(self, 'disk', 'floppy')
408         # FDDs not having a real tray and there not being a medium inside the
409         # tray at startup means the tray will be considered open
410         self.has_opened = True
411
412 class TestChangeReadOnly(ChangeBaseClass):
413     def setUp(self):
414         qemu_img('create', '-f', iotests.imgfmt, old_img, '1440k')
415         qemu_img('create', '-f', iotests.imgfmt, new_img, '1440k')
416         self.vm = iotests.VM()
417
418     def tearDown(self):
419         self.vm.shutdown()
420         os.chmod(old_img, 0666)
421         os.chmod(new_img, 0666)
422         os.remove(old_img)
423         os.remove(new_img)
424
425     def test_ro_ro_retain(self):
426         os.chmod(old_img, 0444)
427         os.chmod(new_img, 0444)
428         self.vm.add_drive(old_img, 'media=disk,read-only=on', 'floppy')
429         self.vm.launch()
430
431         result = self.vm.qmp('query-block')
432         self.assert_qmp(result, 'return[0]/inserted/ro', True)
433         self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img)
434
435         result = self.vm.qmp('blockdev-change-medium', device='drive0',
436                                                        filename=new_img,
437                                                        format=iotests.imgfmt,
438                                                        read_only_mode='retain')
439         self.assert_qmp(result, 'return', {})
440
441         result = self.vm.qmp('query-block')
442         self.assert_qmp(result, 'return[0]/inserted/ro', True)
443         self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img)
444
445     def test_ro_rw_retain(self):
446         os.chmod(old_img, 0444)
447         self.vm.add_drive(old_img, 'media=disk,read-only=on', 'floppy')
448         self.vm.launch()
449
450         result = self.vm.qmp('query-block')
451         self.assert_qmp(result, 'return[0]/inserted/ro', True)
452         self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img)
453
454         result = self.vm.qmp('blockdev-change-medium', device='drive0',
455                                                        filename=new_img,
456                                                        format=iotests.imgfmt,
457                                                        read_only_mode='retain')
458         self.assert_qmp(result, 'return', {})
459
460         result = self.vm.qmp('query-block')
461         self.assert_qmp(result, 'return[0]/inserted/ro', True)
462         self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img)
463
464     def test_rw_ro_retain(self):
465         os.chmod(new_img, 0444)
466         self.vm.add_drive(old_img, 'media=disk', 'floppy')
467         self.vm.launch()
468
469         result = self.vm.qmp('query-block')
470         self.assert_qmp(result, 'return[0]/inserted/ro', False)
471         self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img)
472
473         result = self.vm.qmp('blockdev-change-medium', device='drive0',
474                                                        filename=new_img,
475                                                        format=iotests.imgfmt,
476                                                        read_only_mode='retain')
477         self.assert_qmp(result, 'error/class', 'GenericError')
478
479         self.assertEquals(self.vm.get_qmp_events(wait=False), [])
480
481         result = self.vm.qmp('query-block')
482         self.assert_qmp(result, 'return[0]/inserted/ro', False)
483         self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img)
484
485     def test_ro_rw(self):
486         os.chmod(old_img, 0444)
487         self.vm.add_drive(old_img, 'media=disk,read-only=on', 'floppy')
488         self.vm.launch()
489
490         result = self.vm.qmp('query-block')
491         self.assert_qmp(result, 'return[0]/inserted/ro', True)
492         self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img)
493
494         result = self.vm.qmp('blockdev-change-medium',
495                              device='drive0',
496                              filename=new_img,
497                              format=iotests.imgfmt,
498                              read_only_mode='read-write')
499         self.assert_qmp(result, 'return', {})
500
501         result = self.vm.qmp('query-block')
502         self.assert_qmp(result, 'return[0]/inserted/ro', False)
503         self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img)
504
505     def test_rw_ro(self):
506         os.chmod(new_img, 0444)
507         self.vm.add_drive(old_img, 'media=disk', 'floppy')
508         self.vm.launch()
509
510         result = self.vm.qmp('query-block')
511         self.assert_qmp(result, 'return[0]/inserted/ro', False)
512         self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img)
513
514         result = self.vm.qmp('blockdev-change-medium',
515                              device='drive0',
516                              filename=new_img,
517                              format=iotests.imgfmt,
518                              read_only_mode='read-only')
519         self.assert_qmp(result, 'return', {})
520
521         result = self.vm.qmp('query-block')
522         self.assert_qmp(result, 'return[0]/inserted/ro', True)
523         self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img)
524
525     def test_make_rw_ro(self):
526         self.vm.add_drive(old_img, 'media=disk', 'floppy')
527         self.vm.launch()
528
529         result = self.vm.qmp('query-block')
530         self.assert_qmp(result, 'return[0]/inserted/ro', False)
531         self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img)
532
533         result = self.vm.qmp('blockdev-change-medium',
534                              device='drive0',
535                              filename=new_img,
536                              format=iotests.imgfmt,
537                              read_only_mode='read-only')
538         self.assert_qmp(result, 'return', {})
539
540         result = self.vm.qmp('query-block')
541         self.assert_qmp(result, 'return[0]/inserted/ro', True)
542         self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img)
543
544     def test_make_ro_rw(self):
545         os.chmod(new_img, 0444)
546         self.vm.add_drive(old_img, 'media=disk', 'floppy')
547         self.vm.launch()
548
549         result = self.vm.qmp('query-block')
550         self.assert_qmp(result, 'return[0]/inserted/ro', False)
551         self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img)
552
553         result = self.vm.qmp('blockdev-change-medium',
554                              device='drive0',
555                              filename=new_img,
556                              format=iotests.imgfmt,
557                              read_only_mode='read-write')
558         self.assert_qmp(result, 'error/class', 'GenericError')
559
560         result = self.vm.qmp('query-block')
561         self.assert_qmp(result, 'return[0]/inserted/ro', False)
562         self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img)
563
564     def test_make_rw_ro_by_retain(self):
565         os.chmod(old_img, 0444)
566         self.vm.add_drive(old_img, 'media=disk,read-only=on', 'floppy')
567         self.vm.launch()
568
569         result = self.vm.qmp('query-block')
570         self.assert_qmp(result, 'return[0]/inserted/ro', True)
571         self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img)
572
573         result = self.vm.qmp('blockdev-change-medium', device='drive0',
574                                                        filename=new_img,
575                                                        format=iotests.imgfmt,
576                                                        read_only_mode='retain')
577         self.assert_qmp(result, 'return', {})
578
579         result = self.vm.qmp('query-block')
580         self.assert_qmp(result, 'return[0]/inserted/ro', True)
581         self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img)
582
583     def test_make_ro_rw_by_retain(self):
584         os.chmod(new_img, 0444)
585         self.vm.add_drive(old_img, 'media=disk', 'floppy')
586         self.vm.launch()
587
588         result = self.vm.qmp('query-block')
589         self.assert_qmp(result, 'return[0]/inserted/ro', False)
590         self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img)
591
592         result = self.vm.qmp('blockdev-change-medium', device='drive0',
593                                                        filename=new_img,
594                                                        format=iotests.imgfmt,
595                                                        read_only_mode='retain')
596         self.assert_qmp(result, 'error/class', 'GenericError')
597
598         result = self.vm.qmp('query-block')
599         self.assert_qmp(result, 'return[0]/inserted/ro', False)
600         self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img)
601
602     def test_rw_ro_cycle(self):
603         os.chmod(new_img, 0444)
604         self.vm.add_drive(old_img, 'media=disk', 'floppy')
605         self.vm.launch()
606
607         result = self.vm.qmp('query-block')
608         self.assert_qmp(result, 'return[0]/inserted/ro', False)
609         self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img)
610
611         result = self.vm.qmp('blockdev-add',
612                              node_name='new',
613                              driver=iotests.imgfmt,
614                              read_only=True,
615                              file={'filename': new_img,
616                                     'driver': 'file'})
617         self.assert_qmp(result, 'return', {})
618
619         result = self.vm.qmp('query-block')
620         self.assert_qmp(result, 'return[0]/inserted/ro', False)
621         self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img)
622
623         result = self.vm.qmp('x-blockdev-remove-medium', device='drive0')
624         self.assert_qmp(result, 'return', {})
625
626         result = self.vm.qmp('query-block')
627         self.assert_qmp_absent(result, 'return[0]/inserted')
628
629         result = self.vm.qmp('x-blockdev-insert-medium', device='drive0',
630                                                        node_name='new')
631         self.assert_qmp(result, 'return', {})
632
633         result = self.vm.qmp('query-block')
634         self.assert_qmp(result, 'return[0]/inserted/ro', True)
635         self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img)
636
637         result = self.vm.qmp('query-block')
638         self.assert_qmp(result, 'return[0]/inserted/ro', True)
639         self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img)
640
641 GeneralChangeTestsBaseClass = None
642 TestInitiallyFilled = None
643 TestInitiallyEmpty = None
644
645
646 class TestBlockJobsAfterCycle(ChangeBaseClass):
647     def setUp(self):
648         qemu_img('create', '-f', iotests.imgfmt, old_img, '1M')
649
650         self.vm = iotests.VM()
651         self.vm.add_drive_raw("id=drive0,driver=null-co,if=none")
652         self.vm.launch()
653
654         result = self.vm.qmp('query-block')
655         self.assert_qmp(result, 'return[0]/inserted/image/format', 'null-co')
656
657         # For device-less BBs, calling blockdev-open-tray or blockdev-close-tray
658         # is not necessary
659         result = self.vm.qmp('x-blockdev-remove-medium', device='drive0')
660         self.assert_qmp(result, 'return', {})
661
662         result = self.vm.qmp('query-block')
663         self.assert_qmp_absent(result, 'return[0]/inserted')
664
665         result = self.vm.qmp('blockdev-add',
666                              node_name='node0',
667                              driver=iotests.imgfmt,
668                              file={'filename': old_img,
669                                    'driver': 'file'})
670         self.assert_qmp(result, 'return', {})
671
672         result = self.vm.qmp('x-blockdev-insert-medium', device='drive0',
673                                                        node_name='node0')
674         self.assert_qmp(result, 'return', {})
675
676         result = self.vm.qmp('query-block')
677         self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img)
678
679     def tearDown(self):
680         self.vm.shutdown()
681         os.remove(old_img)
682         try:
683             os.remove(new_img)
684         except OSError:
685             pass
686
687     def test_snapshot_and_commit(self):
688         # We need backing file support
689         if iotests.imgfmt != 'qcow2' and iotests.imgfmt != 'qed':
690             return
691
692         result = self.vm.qmp('blockdev-snapshot-sync', device='drive0',
693                                                        snapshot_file=new_img,
694                                                        format=iotests.imgfmt)
695         self.assert_qmp(result, 'return', {})
696
697         result = self.vm.qmp('query-block')
698         self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img)
699         self.assert_qmp(result,
700                         'return[0]/inserted/image/backing-image/filename',
701                         old_img)
702
703         result = self.vm.qmp('block-commit', device='drive0')
704         self.assert_qmp(result, 'return', {})
705
706         self.vm.event_wait(name='BLOCK_JOB_READY')
707
708         result = self.vm.qmp('query-block-jobs')
709         self.assert_qmp(result, 'return[0]/device', 'drive0')
710
711         result = self.vm.qmp('block-job-complete', device='drive0')
712         self.assert_qmp(result, 'return', {})
713
714         self.vm.event_wait(name='BLOCK_JOB_COMPLETED')
715
716
717 if __name__ == '__main__':
718     if iotests.qemu_default_machine != 'pc':
719         # We need floppy and IDE CD-ROM
720         iotests.notrun('not suitable for this machine type: %s' %
721                        iotests.qemu_default_machine)
722     # Need to support image creation
723     iotests.main(supported_fmts=['vpc', 'parallels', 'qcow', 'vdi', 'qcow2',
724                                  'vmdk', 'raw', 'vhdx', 'qed'])