aboutsummaryrefslogtreecommitdiff
path: root/tests/qemu-iotests
diff options
context:
space:
mode:
Diffstat (limited to 'tests/qemu-iotests')
-rwxr-xr-xtests/qemu-iotests/05910
-rw-r--r--tests/qemu-iotests/059.out25
-rw-r--r--tests/qemu-iotests/067.out4
-rwxr-xr-xtests/qemu-iotests/08313
-rw-r--r--tests/qemu-iotests/083.out10
-rwxr-xr-xtests/qemu-iotests/11786
-rw-r--r--tests/qemu-iotests/117.out14
-rwxr-xr-xtests/qemu-iotests/118121
-rwxr-xr-xtests/qemu-iotests/14092
-rw-r--r--tests/qemu-iotests/140.out16
-rwxr-xr-xtests/qemu-iotests/141186
-rw-r--r--tests/qemu-iotests/141.out59
-rwxr-xr-xtests/qemu-iotests/14373
-rw-r--r--tests/qemu-iotests/143.out7
-rwxr-xr-xtests/qemu-iotests/144114
-rw-r--r--tests/qemu-iotests/144.out24
-rw-r--r--tests/qemu-iotests/common.filter13
-rw-r--r--tests/qemu-iotests/common.qemu15
-rw-r--r--tests/qemu-iotests/group5
19 files changed, 777 insertions, 110 deletions
diff --git a/tests/qemu-iotests/059 b/tests/qemu-iotests/059
index 0ded0c3da4..0332bbb348 100755
--- a/tests/qemu-iotests/059
+++ b/tests/qemu-iotests/059
@@ -133,6 +133,16 @@ $QEMU_IO -c "write -P 0xa 900G 512" "$TEST_IMG" | _filter_qemu_io
$QEMU_IO -c "read -v 900G 1024" "$TEST_IMG" | _filter_qemu_io
echo
+echo "=== Testing qemu-img map on extents ==="
+for fmt in monolithicSparse twoGbMaxExtentSparse; do
+ IMGOPTS="subformat=$fmt" _make_test_img 31G
+ $QEMU_IO -c "write 65024 1k" "$TEST_IMG" | _filter_qemu_io
+ $QEMU_IO -c "write 2147483136 1k" "$TEST_IMG" | _filter_qemu_io
+ $QEMU_IO -c "write 5G 1k" "$TEST_IMG" | _filter_qemu_io
+ $QEMU_IMG map "$TEST_IMG" | _filter_testdir
+done
+
+echo
echo "=== Testing afl image with a very large capacity ==="
_use_sample_img afl9.vmdk.bz2
_img_info
diff --git a/tests/qemu-iotests/059.out b/tests/qemu-iotests/059.out
index 9d506cb80c..678adb4379 100644
--- a/tests/qemu-iotests/059.out
+++ b/tests/qemu-iotests/059.out
@@ -2335,6 +2335,31 @@ e1000003f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
read 1024/1024 bytes at offset 966367641600
1 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+=== Testing qemu-img map on extents ===
+Formatting 'TEST_DIR/iotest-version3.IMGFMT', fmt=IMGFMT size=33285996544 subformat=monolithicSparse
+wrote 1024/1024 bytes at offset 65024
+1 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 1024/1024 bytes at offset 2147483136
+1 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 1024/1024 bytes at offset 5368709120
+1 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+Offset Length Mapped to File
+0 0x20000 0x3f0000 TEST_DIR/iotest-version3.vmdk
+0x7fff0000 0x20000 0x410000 TEST_DIR/iotest-version3.vmdk
+0x140000000 0x10000 0x430000 TEST_DIR/iotest-version3.vmdk
+Formatting 'TEST_DIR/iotest-version3.IMGFMT', fmt=IMGFMT size=33285996544 subformat=twoGbMaxExtentSparse
+wrote 1024/1024 bytes at offset 65024
+1 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 1024/1024 bytes at offset 2147483136
+1 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 1024/1024 bytes at offset 5368709120
+1 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+Offset Length Mapped to File
+0 0x20000 0x50000 TEST_DIR/iotest-version3-s001.vmdk
+0x7fff0000 0x10000 0x70000 TEST_DIR/iotest-version3-s001.vmdk
+0x80000000 0x10000 0x50000 TEST_DIR/iotest-version3-s002.vmdk
+0x140000000 0x10000 0x50000 TEST_DIR/iotest-version3-s003.vmdk
+
=== Testing afl image with a very large capacity ===
qemu-img: Can't get size of device 'image': File too large
*** done
diff --git a/tests/qemu-iotests/067.out b/tests/qemu-iotests/067.out
index 27ad56fe2f..ae3fccb15f 100644
--- a/tests/qemu-iotests/067.out
+++ b/tests/qemu-iotests/067.out
@@ -169,7 +169,6 @@ Testing: -drive file=TEST_DIR/t.qcow2,format=qcow2,if=none,id=disk
"file": "TEST_DIR/t.qcow2",
"encryption_key_missing": false
},
- "tray_open": false,
"type": "unknown"
}
]
@@ -289,7 +288,6 @@ Testing:
"file": "TEST_DIR/t.qcow2",
"encryption_key_missing": false
},
- "tray_open": false,
"type": "unknown"
}
]
@@ -410,7 +408,6 @@ Testing:
"file": "TEST_DIR/t.qcow2",
"encryption_key_missing": false
},
- "tray_open": false,
"type": "unknown"
}
]
@@ -501,7 +498,6 @@ Testing:
"file": "TEST_DIR/t.qcow2",
"encryption_key_missing": false
},
- "tray_open": false,
"type": "unknown"
}
]
diff --git a/tests/qemu-iotests/083 b/tests/qemu-iotests/083
index 566da99323..aa99278fd8 100755
--- a/tests/qemu-iotests/083
+++ b/tests/qemu-iotests/083
@@ -49,17 +49,6 @@ wait_for_tcp_port() {
done
}
-filter_nbd() {
- # nbd.c error messages contain function names and line numbers that are prone
- # to change. Message ordering depends on timing between send and receive
- # callbacks sometimes, making them unreliable.
- #
- # Filter out the TCP port number since this changes between runs.
- sed -e 's#^.*nbd/.*\.c:.*##g' \
- -e 's#nbd:127\.0\.0\.1:[^:]*:#nbd:127\.0\.0\.1:PORT:#g' \
- -e 's#\(exportname=foo\|PORT\): Failed to .*$#\1#'
-}
-
check_disconnect() {
event=$1
when=$2
@@ -84,7 +73,7 @@ EOF
$PYTHON nbd-fault-injector.py $extra_args "127.0.0.1:$port" "$TEST_DIR/nbd-fault-injector.conf" 2>&1 >/dev/null &
wait_for_tcp_port "127\\.0\\.0\\.1:$port"
- $QEMU_IO -c "read 0 512" "$nbd_url" 2>&1 | _filter_qemu_io | filter_nbd
+ $QEMU_IO -c "read 0 512" "$nbd_url" 2>&1 | _filter_qemu_io | _filter_nbd
echo
}
diff --git a/tests/qemu-iotests/083.out b/tests/qemu-iotests/083.out
index 78cc49ad91..ef3d1e32a5 100644
--- a/tests/qemu-iotests/083.out
+++ b/tests/qemu-iotests/083.out
@@ -51,7 +51,6 @@ no file open, try 'help open'
=== Check disconnect after neg2 ===
-
read failed: Input/output error
=== Check disconnect 8 neg2 ===
@@ -66,42 +65,34 @@ no file open, try 'help open'
=== Check disconnect before request ===
-
read failed: Input/output error
=== Check disconnect after request ===
-
read failed: Input/output error
=== Check disconnect before reply ===
-
read failed: Input/output error
=== Check disconnect after reply ===
-
read failed: Input/output error
=== Check disconnect 4 reply ===
-
read failed: Input/output error
=== Check disconnect 8 reply ===
-
read failed: Input/output error
=== Check disconnect before data ===
-
read failed: Input/output error
=== Check disconnect after data ===
-
read 512/512 bytes at offset 0
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
@@ -132,7 +123,6 @@ no file open, try 'help open'
=== Check disconnect after neg-classic ===
-
read failed: Input/output error
*** done
diff --git a/tests/qemu-iotests/117 b/tests/qemu-iotests/117
new file mode 100755
index 0000000000..969750d137
--- /dev/null
+++ b/tests/qemu-iotests/117
@@ -0,0 +1,86 @@
+#!/bin/bash
+#
+# Test case for shared BDS between backend trees
+#
+# Copyright (C) 2016 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/>.
+#
+
+# creator
+owner=mreitz@redhat.com
+
+seq="$(basename $0)"
+echo "QA output created by $seq"
+
+here="$PWD"
+tmp=/tmp/$$
+status=1 # failure is the default!
+
+_cleanup()
+{
+ _cleanup_test_img
+}
+trap "_cleanup; exit \$status" 0 1 2 3 15
+
+# get standard environment, filters and checks
+. ./common.rc
+. ./common.filter
+. ./common.qemu
+
+_supported_fmt qcow2
+_supported_proto file
+_supported_os Linux
+
+_make_test_img 64k
+
+_launch_qemu
+
+_send_qemu_cmd $QEMU_HANDLE \
+ "{ 'execute': 'qmp_capabilities' }" \
+ 'return'
+
+_send_qemu_cmd $QEMU_HANDLE \
+ "{ 'execute': 'blockdev-add',
+ 'arguments': { 'options': { 'id': 'protocol',
+ 'driver': 'file',
+ 'filename': '$TEST_IMG' } } }" \
+ 'return'
+
+_send_qemu_cmd $QEMU_HANDLE \
+ "{ 'execute': 'blockdev-add',
+ 'arguments': { 'options': { 'id': 'format',
+ 'driver': '$IMGFMT',
+ 'file': 'protocol' } } }" \
+ 'return'
+
+_send_qemu_cmd $QEMU_HANDLE \
+ "{ 'execute': 'human-monitor-command',
+ 'arguments': { 'command-line': 'qemu-io format \"write -P 42 0 64k\"' } }" \
+ 'return'
+
+_send_qemu_cmd $QEMU_HANDLE \
+ "{ 'execute': 'quit' }" \
+ 'return'
+
+wait=1 _cleanup_qemu
+
+_check_test_img
+
+$QEMU_IO -c 'read -P 42 0 64k' "$TEST_IMG" | _filter_qemu_io
+
+# success, all done
+echo '*** done'
+rm -f $seq.full
+status=0
diff --git a/tests/qemu-iotests/117.out b/tests/qemu-iotests/117.out
new file mode 100644
index 0000000000..f52dc1a357
--- /dev/null
+++ b/tests/qemu-iotests/117.out
@@ -0,0 +1,14 @@
+QA output created by 117
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=65536
+{"return": {}}
+{"return": {}}
+{"return": {}}
+wrote 65536/65536 bytes at offset 0
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+{"return": ""}
+{"return": {}}
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN"}
+No errors were found on the image.
+read 65536/65536 bytes at offset 0
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+*** done
diff --git a/tests/qemu-iotests/118 b/tests/qemu-iotests/118
index 114d0e2dea..9e5951f645 100755
--- a/tests/qemu-iotests/118
+++ b/tests/qemu-iotests/118
@@ -42,6 +42,9 @@ class ChangeBaseClass(iotests.QMPTestCase):
self.has_opened = True
def wait_for_open(self):
+ if not self.has_real_tray:
+ return
+
timeout = time.clock() + 3
while not self.has_opened and time.clock() < timeout:
self.process_events()
@@ -49,6 +52,9 @@ class ChangeBaseClass(iotests.QMPTestCase):
self.fail('Timeout while waiting for the tray to open')
def wait_for_close(self):
+ if not self.has_real_tray:
+ return
+
timeout = time.clock() + 3
while not self.has_closed and time.clock() < timeout:
self.process_events()
@@ -65,7 +71,8 @@ class GeneralChangeTestsBaseClass(ChangeBaseClass):
self.wait_for_close()
result = self.vm.qmp('query-block')
- self.assert_qmp(result, 'return[0]/tray_open', False)
+ if self.has_real_tray:
+ self.assert_qmp(result, 'return[0]/tray_open', False)
self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img)
def test_blockdev_change_medium(self):
@@ -78,7 +85,8 @@ class GeneralChangeTestsBaseClass(ChangeBaseClass):
self.wait_for_close()
result = self.vm.qmp('query-block')
- self.assert_qmp(result, 'return[0]/tray_open', False)
+ if self.has_real_tray:
+ self.assert_qmp(result, 'return[0]/tray_open', False)
self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img)
def test_eject(self):
@@ -88,7 +96,8 @@ class GeneralChangeTestsBaseClass(ChangeBaseClass):
self.wait_for_open()
result = self.vm.qmp('query-block')
- self.assert_qmp(result, 'return[0]/tray_open', True)
+ if self.has_real_tray:
+ self.assert_qmp(result, 'return[0]/tray_open', True)
self.assert_qmp_absent(result, 'return[0]/inserted')
def test_tray_eject_change(self):
@@ -98,7 +107,8 @@ class GeneralChangeTestsBaseClass(ChangeBaseClass):
self.wait_for_open()
result = self.vm.qmp('query-block')
- self.assert_qmp(result, 'return[0]/tray_open', True)
+ if self.has_real_tray:
+ self.assert_qmp(result, 'return[0]/tray_open', True)
self.assert_qmp_absent(result, 'return[0]/inserted')
result = self.vm.qmp('blockdev-change-medium', device='drive0',
@@ -109,7 +119,8 @@ class GeneralChangeTestsBaseClass(ChangeBaseClass):
self.wait_for_close()
result = self.vm.qmp('query-block')
- self.assert_qmp(result, 'return[0]/tray_open', False)
+ if self.has_real_tray:
+ self.assert_qmp(result, 'return[0]/tray_open', False)
self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img)
def test_tray_open_close(self):
@@ -119,7 +130,8 @@ class GeneralChangeTestsBaseClass(ChangeBaseClass):
self.wait_for_open()
result = self.vm.qmp('query-block')
- self.assert_qmp(result, 'return[0]/tray_open', True)
+ if self.has_real_tray:
+ self.assert_qmp(result, 'return[0]/tray_open', True)
if self.was_empty == True:
self.assert_qmp_absent(result, 'return[0]/inserted')
else:
@@ -132,10 +144,8 @@ class GeneralChangeTestsBaseClass(ChangeBaseClass):
self.wait_for_close()
result = self.vm.qmp('query-block')
- if self.has_real_tray or not self.was_empty:
+ if self.has_real_tray:
self.assert_qmp(result, 'return[0]/tray_open', False)
- else:
- self.assert_qmp(result, 'return[0]/tray_open', True)
if self.was_empty == True:
self.assert_qmp_absent(result, 'return[0]/inserted')
else:
@@ -148,20 +158,18 @@ class GeneralChangeTestsBaseClass(ChangeBaseClass):
self.wait_for_open()
result = self.vm.qmp('query-block')
- self.assert_qmp(result, 'return[0]/tray_open', True)
+ if self.has_real_tray:
+ self.assert_qmp(result, 'return[0]/tray_open', True)
self.assert_qmp_absent(result, 'return[0]/inserted')
result = self.vm.qmp('blockdev-close-tray', device='drive0')
self.assert_qmp(result, 'return', {})
- if self.has_real_tray:
- self.wait_for_close()
+ self.wait_for_close()
result = self.vm.qmp('query-block')
if self.has_real_tray:
self.assert_qmp(result, 'return[0]/tray_open', False)
- else:
- self.assert_qmp(result, 'return[0]/tray_open', True)
self.assert_qmp_absent(result, 'return[0]/inserted')
def test_tray_open_change(self):
@@ -171,7 +179,8 @@ class GeneralChangeTestsBaseClass(ChangeBaseClass):
self.wait_for_open()
result = self.vm.qmp('query-block')
- self.assert_qmp(result, 'return[0]/tray_open', True)
+ if self.has_real_tray:
+ self.assert_qmp(result, 'return[0]/tray_open', True)
if self.was_empty == True:
self.assert_qmp_absent(result, 'return[0]/inserted')
else:
@@ -185,7 +194,8 @@ class GeneralChangeTestsBaseClass(ChangeBaseClass):
self.wait_for_close()
result = self.vm.qmp('query-block')
- self.assert_qmp(result, 'return[0]/tray_open', False)
+ if self.has_real_tray:
+ self.assert_qmp(result, 'return[0]/tray_open', False)
self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img)
def test_cycle(self):
@@ -202,7 +212,8 @@ class GeneralChangeTestsBaseClass(ChangeBaseClass):
self.wait_for_open()
result = self.vm.qmp('query-block')
- self.assert_qmp(result, 'return[0]/tray_open', True)
+ if self.has_real_tray:
+ self.assert_qmp(result, 'return[0]/tray_open', True)
if self.was_empty == True:
self.assert_qmp_absent(result, 'return[0]/inserted')
else:
@@ -212,7 +223,8 @@ class GeneralChangeTestsBaseClass(ChangeBaseClass):
self.assert_qmp(result, 'return', {})
result = self.vm.qmp('query-block')
- self.assert_qmp(result, 'return[0]/tray_open', True)
+ if self.has_real_tray:
+ self.assert_qmp(result, 'return[0]/tray_open', True)
self.assert_qmp_absent(result, 'return[0]/inserted')
result = self.vm.qmp('x-blockdev-insert-medium', device='drive0',
@@ -220,7 +232,8 @@ class GeneralChangeTestsBaseClass(ChangeBaseClass):
self.assert_qmp(result, 'return', {})
result = self.vm.qmp('query-block')
- self.assert_qmp(result, 'return[0]/tray_open', True)
+ if self.has_real_tray:
+ self.assert_qmp(result, 'return[0]/tray_open', True)
self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img)
result = self.vm.qmp('blockdev-close-tray', device='drive0')
@@ -229,7 +242,8 @@ class GeneralChangeTestsBaseClass(ChangeBaseClass):
self.wait_for_close()
result = self.vm.qmp('query-block')
- self.assert_qmp(result, 'return[0]/tray_open', False)
+ if self.has_real_tray:
+ self.assert_qmp(result, 'return[0]/tray_open', False)
self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img)
def test_close_on_closed(self):
@@ -239,16 +253,14 @@ class GeneralChangeTestsBaseClass(ChangeBaseClass):
self.assertEquals(self.vm.get_qmp_events(wait=False), [])
def test_remove_on_closed(self):
- if self.has_opened:
- # Empty floppy drive
+ if not self.has_real_tray:
return
result = self.vm.qmp('x-blockdev-remove-medium', device='drive0')
self.assert_qmp(result, 'error/class', 'GenericError')
def test_insert_on_closed(self):
- if self.has_opened:
- # Empty floppy drive
+ if not self.has_real_tray:
return
result = self.vm.qmp('blockdev-add',
@@ -366,7 +378,6 @@ class TestChangeReadOnly(ChangeBaseClass):
self.vm.launch()
result = self.vm.qmp('query-block')
- self.assert_qmp(result, 'return[0]/tray_open', False)
self.assert_qmp(result, 'return[0]/inserted/ro', True)
self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img)
@@ -376,11 +387,7 @@ class TestChangeReadOnly(ChangeBaseClass):
read_only_mode='retain')
self.assert_qmp(result, 'return', {})
- self.wait_for_open()
- self.wait_for_close()
-
result = self.vm.qmp('query-block')
- self.assert_qmp(result, 'return[0]/tray_open', False)
self.assert_qmp(result, 'return[0]/inserted/ro', True)
self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img)
@@ -390,7 +397,6 @@ class TestChangeReadOnly(ChangeBaseClass):
self.vm.launch()
result = self.vm.qmp('query-block')
- self.assert_qmp(result, 'return[0]/tray_open', False)
self.assert_qmp(result, 'return[0]/inserted/ro', True)
self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img)
@@ -400,11 +406,7 @@ class TestChangeReadOnly(ChangeBaseClass):
read_only_mode='retain')
self.assert_qmp(result, 'return', {})
- self.wait_for_open()
- self.wait_for_close()
-
result = self.vm.qmp('query-block')
- self.assert_qmp(result, 'return[0]/tray_open', False)
self.assert_qmp(result, 'return[0]/inserted/ro', True)
self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img)
@@ -414,7 +416,6 @@ class TestChangeReadOnly(ChangeBaseClass):
self.vm.launch()
result = self.vm.qmp('query-block')
- self.assert_qmp(result, 'return[0]/tray_open', False)
self.assert_qmp(result, 'return[0]/inserted/ro', False)
self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img)
@@ -427,7 +428,6 @@ class TestChangeReadOnly(ChangeBaseClass):
self.assertEquals(self.vm.get_qmp_events(wait=False), [])
result = self.vm.qmp('query-block')
- self.assert_qmp(result, 'return[0]/tray_open', False)
self.assert_qmp(result, 'return[0]/inserted/ro', False)
self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img)
@@ -437,7 +437,6 @@ class TestChangeReadOnly(ChangeBaseClass):
self.vm.launch()
result = self.vm.qmp('query-block')
- self.assert_qmp(result, 'return[0]/tray_open', False)
self.assert_qmp(result, 'return[0]/inserted/ro', True)
self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img)
@@ -448,11 +447,7 @@ class TestChangeReadOnly(ChangeBaseClass):
read_only_mode='read-write')
self.assert_qmp(result, 'return', {})
- self.wait_for_open()
- self.wait_for_close()
-
result = self.vm.qmp('query-block')
- self.assert_qmp(result, 'return[0]/tray_open', False)
self.assert_qmp(result, 'return[0]/inserted/ro', False)
self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img)
@@ -462,7 +457,6 @@ class TestChangeReadOnly(ChangeBaseClass):
self.vm.launch()
result = self.vm.qmp('query-block')
- self.assert_qmp(result, 'return[0]/tray_open', False)
self.assert_qmp(result, 'return[0]/inserted/ro', False)
self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img)
@@ -473,11 +467,7 @@ class TestChangeReadOnly(ChangeBaseClass):
read_only_mode='read-only')
self.assert_qmp(result, 'return', {})
- self.wait_for_open()
- self.wait_for_close()
-
result = self.vm.qmp('query-block')
- self.assert_qmp(result, 'return[0]/tray_open', False)
self.assert_qmp(result, 'return[0]/inserted/ro', True)
self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img)
@@ -486,7 +476,6 @@ class TestChangeReadOnly(ChangeBaseClass):
self.vm.launch()
result = self.vm.qmp('query-block')
- self.assert_qmp(result, 'return[0]/tray_open', False)
self.assert_qmp(result, 'return[0]/inserted/ro', False)
self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img)
@@ -497,11 +486,7 @@ class TestChangeReadOnly(ChangeBaseClass):
read_only_mode='read-only')
self.assert_qmp(result, 'return', {})
- self.wait_for_open()
- self.wait_for_close()
-
result = self.vm.qmp('query-block')
- self.assert_qmp(result, 'return[0]/tray_open', False)
self.assert_qmp(result, 'return[0]/inserted/ro', True)
self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img)
@@ -511,7 +496,6 @@ class TestChangeReadOnly(ChangeBaseClass):
self.vm.launch()
result = self.vm.qmp('query-block')
- self.assert_qmp(result, 'return[0]/tray_open', False)
self.assert_qmp(result, 'return[0]/inserted/ro', False)
self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img)
@@ -522,10 +506,7 @@ class TestChangeReadOnly(ChangeBaseClass):
read_only_mode='read-write')
self.assert_qmp(result, 'error/class', 'GenericError')
- self.assertEquals(self.vm.get_qmp_events(wait=False), [])
-
result = self.vm.qmp('query-block')
- self.assert_qmp(result, 'return[0]/tray_open', False)
self.assert_qmp(result, 'return[0]/inserted/ro', False)
self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img)
@@ -535,7 +516,6 @@ class TestChangeReadOnly(ChangeBaseClass):
self.vm.launch()
result = self.vm.qmp('query-block')
- self.assert_qmp(result, 'return[0]/tray_open', False)
self.assert_qmp(result, 'return[0]/inserted/ro', True)
self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img)
@@ -545,11 +525,7 @@ class TestChangeReadOnly(ChangeBaseClass):
read_only_mode='retain')
self.assert_qmp(result, 'return', {})
- self.wait_for_open()
- self.wait_for_close()
-
result = self.vm.qmp('query-block')
- self.assert_qmp(result, 'return[0]/tray_open', False)
self.assert_qmp(result, 'return[0]/inserted/ro', True)
self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img)
@@ -559,7 +535,6 @@ class TestChangeReadOnly(ChangeBaseClass):
self.vm.launch()
result = self.vm.qmp('query-block')
- self.assert_qmp(result, 'return[0]/tray_open', False)
self.assert_qmp(result, 'return[0]/inserted/ro', False)
self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img)
@@ -569,10 +544,7 @@ class TestChangeReadOnly(ChangeBaseClass):
read_only_mode='retain')
self.assert_qmp(result, 'error/class', 'GenericError')
- self.assertEquals(self.vm.get_qmp_events(wait=False), [])
-
result = self.vm.qmp('query-block')
- self.assert_qmp(result, 'return[0]/tray_open', False)
self.assert_qmp(result, 'return[0]/inserted/ro', False)
self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img)
@@ -582,7 +554,6 @@ class TestChangeReadOnly(ChangeBaseClass):
self.vm.launch()
result = self.vm.qmp('query-block')
- self.assert_qmp(result, 'return[0]/tray_open', False)
self.assert_qmp(result, 'return[0]/inserted/ro', False)
self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img)
@@ -594,13 +565,7 @@ class TestChangeReadOnly(ChangeBaseClass):
'driver': 'file'}})
self.assert_qmp(result, 'return', {})
- result = self.vm.qmp('blockdev-open-tray', device='drive0', force=True)
- self.assert_qmp(result, 'return', {})
-
- self.wait_for_open()
-
result = self.vm.qmp('query-block')
- self.assert_qmp(result, 'return[0]/tray_open', True)
self.assert_qmp(result, 'return[0]/inserted/ro', False)
self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img)
@@ -608,7 +573,6 @@ class TestChangeReadOnly(ChangeBaseClass):
self.assert_qmp(result, 'return', {})
result = self.vm.qmp('query-block')
- self.assert_qmp(result, 'return[0]/tray_open', True)
self.assert_qmp_absent(result, 'return[0]/inserted')
result = self.vm.qmp('x-blockdev-insert-medium', device='drive0',
@@ -616,17 +580,10 @@ class TestChangeReadOnly(ChangeBaseClass):
self.assert_qmp(result, 'return', {})
result = self.vm.qmp('query-block')
- self.assert_qmp(result, 'return[0]/tray_open', True)
self.assert_qmp(result, 'return[0]/inserted/ro', True)
self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img)
- result = self.vm.qmp('blockdev-close-tray', device='drive0')
- self.assert_qmp(result, 'return', {})
-
- self.wait_for_close()
-
result = self.vm.qmp('query-block')
- self.assert_qmp(result, 'return[0]/tray_open', False)
self.assert_qmp(result, 'return[0]/inserted/ro', True)
self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img)
@@ -648,7 +605,6 @@ class TestBlockJobsAfterCycle(ChangeBaseClass):
self.assert_qmp(result, 'return', {})
result = self.vm.qmp('query-block')
- self.assert_qmp(result, 'return[0]/tray_open', False)
self.assert_qmp(result, 'return[0]/inserted/image/format', 'null-co')
# For device-less BBs, calling blockdev-open-tray or blockdev-close-tray
@@ -671,7 +627,6 @@ class TestBlockJobsAfterCycle(ChangeBaseClass):
self.assert_qmp(result, 'return', {})
result = self.vm.qmp('query-block')
- self.assert_qmp(result, 'return[0]/tray_open', False)
self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img)
def tearDown(self):
@@ -717,4 +672,6 @@ if __name__ == '__main__':
# We need floppy and IDE CD-ROM
iotests.notrun('not suitable for this machine type: %s' %
iotests.qemu_default_machine)
- iotests.main()
+ # Need to support image creation
+ iotests.main(supported_fmts=['vpc', 'parallels', 'qcow', 'vdi', 'qcow2',
+ 'vmdk', 'raw', 'vhdx', 'qed'])
diff --git a/tests/qemu-iotests/140 b/tests/qemu-iotests/140
new file mode 100755
index 0000000000..f78c3175a3
--- /dev/null
+++ b/tests/qemu-iotests/140
@@ -0,0 +1,92 @@
+#!/bin/bash
+#
+# Test case for ejecting a BB with an NBD server attached to it
+#
+# Copyright (C) 2016 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/>.
+#
+
+# creator
+owner=mreitz@redhat.com
+
+seq="$(basename $0)"
+echo "QA output created by $seq"
+
+here="$PWD"
+tmp=/tmp/$$
+status=1 # failure is the default!
+
+_cleanup()
+{
+ _cleanup_test_img
+ rm -f "$TEST_DIR/nbd"
+}
+trap "_cleanup; exit \$status" 0 1 2 3 15
+
+# get standard environment, filters and checks
+. ./common.rc
+. ./common.filter
+. ./common.qemu
+
+_supported_fmt generic
+_supported_proto file
+_supported_os Linux
+
+_make_test_img 64k
+
+$QEMU_IO -c 'write -P 42 0 64k' "$TEST_IMG" | _filter_qemu_io
+
+keep_stderr=y \
+_launch_qemu -drive if=ide,media=cdrom,id=drv,file="$TEST_IMG",format=$IMGFMT \
+ 2> >(_filter_nbd)
+
+_send_qemu_cmd $QEMU_HANDLE \
+ "{ 'execute': 'qmp_capabilities' }" \
+ 'return'
+
+_send_qemu_cmd $QEMU_HANDLE \
+ "{ 'execute': 'nbd-server-start',
+ 'arguments': { 'addr': { 'type': 'unix',
+ 'data': { 'path': '$TEST_DIR/nbd' }}}}" \
+ 'return'
+
+_send_qemu_cmd $QEMU_HANDLE \
+ "{ 'execute': 'nbd-server-add',
+ 'arguments': { 'device': 'drv' }}" \
+ 'return'
+
+$QEMU_IO_PROG -f raw -c 'read -P 42 0 64k' \
+ "nbd+unix:///drv?socket=$TEST_DIR/nbd" 2>&1 \
+ | _filter_qemu_io | _filter_nbd
+
+_send_qemu_cmd $QEMU_HANDLE \
+ "{ 'execute': 'eject',
+ 'arguments': { 'device': 'drv' }}" \
+ 'return'
+
+$QEMU_IO_PROG -f raw -c close \
+ "nbd+unix:///drv?socket=$TEST_DIR/nbd" 2>&1 \
+ | _filter_qemu_io | _filter_nbd
+
+_send_qemu_cmd $QEMU_HANDLE \
+ "{ 'execute': 'quit' }" \
+ 'return'
+
+wait=1 _cleanup_qemu
+
+# success, all done
+echo '*** done'
+rm -f $seq.full
+status=0
diff --git a/tests/qemu-iotests/140.out b/tests/qemu-iotests/140.out
new file mode 100644
index 0000000000..fdedeb3973
--- /dev/null
+++ b/tests/qemu-iotests/140.out
@@ -0,0 +1,16 @@
+QA output created by 140
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=65536
+wrote 65536/65536 bytes at offset 0
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+{"return": {}}
+{"return": {}}
+{"return": {}}
+read 65536/65536 bytes at offset 0
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "DEVICE_TRAY_MOVED", "data": {"device": "drv", "tray-open": true}}
+{"return": {}}
+can't open device nbd+unix:///drv?socket=TEST_DIR/nbd: Failed to read export length
+no file open, try 'help open'
+{"return": {}}
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN"}
+*** done
diff --git a/tests/qemu-iotests/141 b/tests/qemu-iotests/141
new file mode 100755
index 0000000000..f7c28b4463
--- /dev/null
+++ b/tests/qemu-iotests/141
@@ -0,0 +1,186 @@
+#!/bin/bash
+#
+# Test case for ejecting BDSs with block jobs still running on them
+#
+# Copyright (C) 2016 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/>.
+#
+
+# creator
+owner=mreitz@redhat.com
+
+seq="$(basename $0)"
+echo "QA output created by $seq"
+
+here="$PWD"
+tmp=/tmp/$$
+status=1 # failure is the default!
+
+_cleanup()
+{
+ _cleanup_test_img
+ rm -f "$TEST_DIR/{b,m,o}.$IMGFMT"
+}
+trap "_cleanup; exit \$status" 0 1 2 3 15
+
+# get standard environment, filters and checks
+. ./common.rc
+. ./common.filter
+. ./common.qemu
+
+# Needs backing file and backing format support
+_supported_fmt qcow2 qed
+_supported_proto file
+_supported_os Linux
+
+
+test_blockjob()
+{
+ _send_qemu_cmd $QEMU_HANDLE \
+ "{'execute': 'blockdev-add',
+ 'arguments': {
+ 'options': {
+ 'id': 'drv0',
+ 'driver': '$IMGFMT',
+ 'file': {
+ 'driver': 'file',
+ 'filename': '$TEST_IMG'
+ }}}}" \
+ 'return'
+
+ _send_qemu_cmd $QEMU_HANDLE \
+ "$1" \
+ "$2" \
+ | _filter_img_create
+
+ # We want this to return an error because the block job is still running
+ _send_qemu_cmd $QEMU_HANDLE \
+ "{'execute': 'x-blockdev-remove-medium',
+ 'arguments': {'device': 'drv0'}}" \
+ 'error'
+
+ _send_qemu_cmd $QEMU_HANDLE \
+ "{'execute': 'block-job-cancel',
+ 'arguments': {'device': 'drv0'}}" \
+ "$3"
+
+ _send_qemu_cmd $QEMU_HANDLE \
+ "{'execute': 'x-blockdev-del',
+ 'arguments': {'id': 'drv0'}}" \
+ 'return'
+}
+
+
+TEST_IMG="$TEST_DIR/b.$IMGFMT" _make_test_img 1M
+TEST_IMG="$TEST_DIR/m.$IMGFMT" _make_test_img -b "$TEST_DIR/b.$IMGFMT" 1M
+_make_test_img -b "$TEST_DIR/m.$IMGFMT" 1M
+
+_launch_qemu -nodefaults
+
+_send_qemu_cmd $QEMU_HANDLE \
+ "{'execute': 'qmp_capabilities'}" \
+ 'return'
+
+echo
+echo '=== Testing drive-backup ==='
+echo
+
+# drive-backup will not send BLOCK_JOB_READY by itself, and cancelling the job
+# will consequently result in BLOCK_JOB_CANCELLED being emitted.
+
+test_blockjob \
+ "{'execute': 'drive-backup',
+ 'arguments': {'device': 'drv0',
+ 'target': '$TEST_DIR/o.$IMGFMT',
+ 'format': '$IMGFMT',
+ 'sync': 'none'}}" \
+ 'return' \
+ 'BLOCK_JOB_CANCELLED'
+
+echo
+echo '=== Testing drive-mirror ==='
+echo
+
+# drive-mirror will send BLOCK_JOB_READY basically immediately, and cancelling
+# the job will consequently result in BLOCK_JOB_COMPLETED being emitted.
+
+test_blockjob \
+ "{'execute': 'drive-mirror',
+ 'arguments': {'device': 'drv0',
+ 'target': '$TEST_DIR/o.$IMGFMT',
+ 'format': '$IMGFMT',
+ 'sync': 'none'}}" \
+ 'BLOCK_JOB_READY' \
+ 'BLOCK_JOB_COMPLETED'
+
+echo
+echo '=== Testing active block-commit ==='
+echo
+
+# An active block-commit will send BLOCK_JOB_READY basically immediately, and
+# cancelling the job will consequently result in BLOCK_JOB_COMPLETED being
+# emitted.
+
+test_blockjob \
+ "{'execute': 'block-commit',
+ 'arguments': {'device': 'drv0'}}" \
+ 'BLOCK_JOB_READY' \
+ 'BLOCK_JOB_COMPLETED'
+
+echo
+echo '=== Testing non-active block-commit ==='
+echo
+
+# Give block-commit something to work on, otherwise it would be done
+# immediately, send a BLOCK_JOB_COMPLETED and ejecting the BDS would work just
+# fine without the block job still running.
+
+$QEMU_IO -c 'write 0 1M' "$TEST_DIR/m.$IMGFMT" | _filter_qemu_io
+
+test_blockjob \
+ "{'execute': 'block-commit',
+ 'arguments': {'device': 'drv0',
+ 'top': '$TEST_DIR/m.$IMGFMT',
+ 'speed': 1}}" \
+ 'return' \
+ 'BLOCK_JOB_CANCELLED'
+
+echo
+echo '=== Testing block-stream ==='
+echo
+
+# Give block-stream something to work on, otherwise it would be done
+# immediately, send a BLOCK_JOB_COMPLETED and ejecting the BDS would work just
+# fine without the block job still running.
+
+$QEMU_IO -c 'write 0 1M' "$TEST_DIR/b.$IMGFMT" | _filter_qemu_io
+
+# With some data to stream (and @speed set to 1), block-stream will not complete
+# until we send the block-job-cancel command. Therefore, no event other than
+# BLOCK_JOB_CANCELLED will be emitted.
+
+test_blockjob \
+ "{'execute': 'block-stream',
+ 'arguments': {'device': 'drv0',
+ 'speed': 1}}" \
+ 'return' \
+ 'BLOCK_JOB_CANCELLED'
+
+_cleanup_qemu
+
+# success, all done
+echo "*** done"
+rm -f $seq.full
+status=0
diff --git a/tests/qemu-iotests/141.out b/tests/qemu-iotests/141.out
new file mode 100644
index 0000000000..adceac1817
--- /dev/null
+++ b/tests/qemu-iotests/141.out
@@ -0,0 +1,59 @@
+QA output created by 141
+Formatting 'TEST_DIR/b.IMGFMT', fmt=IMGFMT size=1048576
+Formatting 'TEST_DIR/m.IMGFMT', fmt=IMGFMT size=1048576 backing_file=TEST_DIR/b.IMGFMT
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576 backing_file=TEST_DIR/m.IMGFMT
+{"return": {}}
+
+=== Testing drive-backup ===
+
+{"return": {}}
+Formatting 'TEST_DIR/o.IMGFMT', fmt=IMGFMT size=1048576 backing_file=TEST_DIR/t.IMGFMT backing_fmt=IMGFMT
+{"return": {}}
+{"error": {"class": "GenericError", "desc": "Node 'drv0' is busy: block device is in use by block job: backup"}}
+{"return": {}}
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_CANCELLED", "data": {"device": "drv0", "len": 1048576, "offset": 0, "speed": 0, "type": "backup"}}
+{"return": {}}
+
+=== Testing drive-mirror ===
+
+{"return": {}}
+Formatting 'TEST_DIR/o.IMGFMT', fmt=IMGFMT size=1048576 backing_file=TEST_DIR/t.IMGFMT backing_fmt=IMGFMT
+{"return": {}}
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_READY", "data": {"device": "drv0", "len": 0, "offset": 0, "speed": 0, "type": "mirror"}}
+{"error": {"class": "GenericError", "desc": "Node 'drv0' is busy: block device is in use by block job: mirror"}}
+{"return": {}}
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "drv0", "len": 0, "offset": 0, "speed": 0, "type": "mirror"}}
+{"return": {}}
+
+=== Testing active block-commit ===
+
+{"return": {}}
+{"return": {}}
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_READY", "data": {"device": "drv0", "len": 0, "offset": 0, "speed": 0, "type": "commit"}}
+{"error": {"class": "GenericError", "desc": "Node 'drv0' is busy: block device is in use by block job: commit"}}
+{"return": {}}
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "drv0", "len": 0, "offset": 0, "speed": 0, "type": "commit"}}
+{"return": {}}
+
+=== Testing non-active block-commit ===
+
+wrote 1048576/1048576 bytes at offset 0
+1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+{"return": {}}
+{"return": {}}
+{"error": {"class": "GenericError", "desc": "Node 'drv0' is busy: block device is in use by block job: commit"}}
+{"return": {}}
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_CANCELLED", "data": {"device": "drv0", "len": 1048576, "offset": 524288, "speed": 1, "type": "commit"}}
+{"return": {}}
+
+=== Testing block-stream ===
+
+wrote 1048576/1048576 bytes at offset 0
+1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+{"return": {}}
+{"return": {}}
+{"error": {"class": "GenericError", "desc": "Node 'drv0' is busy: block device is in use by block job: stream"}}
+{"return": {}}
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_CANCELLED", "data": {"device": "drv0", "len": 1048576, "offset": 524288, "speed": 1, "type": "stream"}}
+{"return": {}}
+*** done
diff --git a/tests/qemu-iotests/143 b/tests/qemu-iotests/143
new file mode 100755
index 0000000000..6207368f04
--- /dev/null
+++ b/tests/qemu-iotests/143
@@ -0,0 +1,73 @@
+#!/bin/bash
+#
+# Test case for connecting to a non-existing NBD export name
+#
+# Copyright (C) 2016 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/>.
+#
+
+# creator
+owner=mreitz@redhat.com
+
+seq="$(basename $0)"
+echo "QA output created by $seq"
+
+here="$PWD"
+tmp=/tmp/$$
+status=1 # failure is the default!
+
+_cleanup()
+{
+ rm -f "$TEST_DIR/nbd"
+}
+trap "_cleanup; exit \$status" 0 1 2 3 15
+
+# get standard environment, filters and checks
+. ./common.rc
+. ./common.filter
+. ./common.qemu
+
+_supported_fmt generic
+_supported_proto generic
+_supported_os Linux
+
+keep_stderr=y \
+_launch_qemu 2> >(_filter_nbd)
+
+_send_qemu_cmd $QEMU_HANDLE \
+ "{ 'execute': 'qmp_capabilities' }" \
+ 'return'
+
+_send_qemu_cmd $QEMU_HANDLE \
+ "{ 'execute': 'nbd-server-start',
+ 'arguments': { 'addr': { 'type': 'unix',
+ 'data': { 'path': '$TEST_DIR/nbd' }}}}" \
+ 'return'
+
+# This should just result in a client error, not in the server crashing
+$QEMU_IO_PROG -f raw -c quit \
+ "nbd+unix:///no_such_export?socket=$TEST_DIR/nbd" 2>&1 \
+ | _filter_qemu_io | _filter_nbd
+
+_send_qemu_cmd $QEMU_HANDLE \
+ "{ 'execute': 'quit' }" \
+ 'return'
+
+wait=1 _cleanup_qemu
+
+# success, all done
+echo '*** done'
+rm -f $seq.full
+status=0
diff --git a/tests/qemu-iotests/143.out b/tests/qemu-iotests/143.out
new file mode 100644
index 0000000000..dad20240a4
--- /dev/null
+++ b/tests/qemu-iotests/143.out
@@ -0,0 +1,7 @@
+QA output created by 143
+{"return": {}}
+{"return": {}}
+can't open device nbd+unix:///no_such_export?socket=TEST_DIR/nbd: Failed to read export length
+{"return": {}}
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN"}
+*** done
diff --git a/tests/qemu-iotests/144 b/tests/qemu-iotests/144
new file mode 100755
index 0000000000..00de3c33cf
--- /dev/null
+++ b/tests/qemu-iotests/144
@@ -0,0 +1,114 @@
+#!/bin/bash
+# Check live snapshot, followed by active commit, and another snapshot.
+#
+# This test is to catch the error case of BZ #1300209:
+# https://bugzilla.redhat.com/show_bug.cgi?id=1300209
+#
+# Copyright (C) 2016 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/>.
+#
+
+# creator
+owner=jcody@redhat.com
+
+seq=`basename $0`
+echo "QA output created by $seq"
+
+here=`pwd`
+status=1 # failure is the default!
+
+TMP_SNAP1=${TEST_DIR}/tmp.qcow2
+TMP_SNAP2=${TEST_DIR}/tmp2.qcow2
+
+_cleanup()
+{
+ _cleanup_qemu
+ rm -f "${TEST_IMG}" "${TMP_SNAP1}" "${TMP_SNAP2}"
+}
+
+trap "_cleanup; exit \$status" 0 1 2 3 15
+
+# get standard environment, filters and checks
+. ./common.rc
+. ./common.filter
+. ./common.qemu
+
+_supported_fmt qcow2
+_supported_proto file
+_supported_os Linux
+
+size=512M
+
+_make_test_img $size
+
+echo
+echo === Launching QEMU ===
+echo
+
+qemu_comm_method="qmp"
+_launch_qemu -drive file="${TEST_IMG}",if=virtio
+h=$QEMU_HANDLE
+
+
+echo
+echo === Performing Live Snapshot 1 ===
+echo
+
+_send_qemu_cmd $h "{ 'execute': 'qmp_capabilities' }" "return"
+
+
+# First live snapshot, new overlay as active layer
+_send_qemu_cmd $h "{ 'execute': 'blockdev-snapshot-sync',
+ 'arguments': {
+ 'device': 'virtio0',
+ 'snapshot-file':'${TMP_SNAP1}',
+ 'format': 'qcow2'
+ }
+ }" "return"
+
+echo
+echo === Performing block-commit on active layer ===
+echo
+
+# Block commit on active layer, push the new overlay into base
+_send_qemu_cmd $h "{ 'execute': 'block-commit',
+ 'arguments': {
+ 'device': 'virtio0'
+ }
+ }" "READY"
+
+_send_qemu_cmd $h "{ 'execute': 'block-job-complete',
+ 'arguments': {
+ 'device': 'virtio0'
+ }
+ }" "COMPLETED"
+
+echo
+echo === Performing Live Snapshot 2 ===
+echo
+
+# New live snapshot, new overlays as active layer
+_send_qemu_cmd $h "{ 'execute': 'blockdev-snapshot-sync',
+ 'arguments': {
+ 'device': 'virtio0',
+ 'snapshot-file':'${TMP_SNAP2}',
+ 'format': 'qcow2'
+ }
+ }" "return"
+
+# success, all done
+echo "*** done"
+rm -f $seq.full
+status=0
diff --git a/tests/qemu-iotests/144.out b/tests/qemu-iotests/144.out
new file mode 100644
index 0000000000..410d74180a
--- /dev/null
+++ b/tests/qemu-iotests/144.out
@@ -0,0 +1,24 @@
+QA output created by 144
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=536870912
+
+=== Launching QEMU ===
+
+
+=== Performing Live Snapshot 1 ===
+
+{"return": {}}
+Formatting 'TEST_DIR/tmp.qcow2', fmt=qcow2 size=536870912 backing_file=TEST_DIR/t.qcow2 backing_fmt=qcow2 encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16
+{"return": {}}
+
+=== Performing block-commit on active layer ===
+
+{"return": {}}
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_READY", "data": {"device": "virtio0", "len": 0, "offset": 0, "speed": 0, "type": "commit"}}
+{"return": {}}
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "virtio0", "len": 0, "offset": 0, "speed": 0, "type": "commit"}}
+
+=== Performing Live Snapshot 2 ===
+
+Formatting 'TEST_DIR/tmp2.qcow2', fmt=qcow2 size=536870912 backing_file=TEST_DIR/t.qcow2 backing_fmt=qcow2 encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16
+{"return": {}}
+*** done
diff --git a/tests/qemu-iotests/common.filter b/tests/qemu-iotests/common.filter
index cfdb6338aa..84b7434bcf 100644
--- a/tests/qemu-iotests/common.filter
+++ b/tests/qemu-iotests/common.filter
@@ -230,5 +230,18 @@ _filter_qemu_img_map()
-e 's/Mapped to *//' | _filter_testdir | _filter_imgfmt
}
+_filter_nbd()
+{
+ # nbd.c error messages contain function names and line numbers that are
+ # prone to change. Message ordering depends on timing between send and
+ # receive callbacks sometimes, making them unreliable.
+ #
+ # Filter out the TCP port number since this changes between runs.
+ sed -e '/nbd\/.*\.c:/d' \
+ -e 's#nbd:\(//\)\?127\.0\.0\.1:[0-9]*#nbd:\1127.0.0.1:PORT#g' \
+ -e "s#?socket=$TEST_DIR#?socket=TEST_DIR#g" \
+ -e 's#\(exportname=foo\|PORT\): Failed to .*$#\1#'
+}
+
# make sure this script returns success
true
diff --git a/tests/qemu-iotests/common.qemu b/tests/qemu-iotests/common.qemu
index 8bf3969418..2548a8700b 100644
--- a/tests/qemu-iotests/common.qemu
+++ b/tests/qemu-iotests/common.qemu
@@ -129,6 +129,8 @@ function _send_qemu_cmd()
# $qemu_comm_method: set this variable to 'monitor' (case insensitive)
# to use the QEMU HMP monitor for communication.
# Otherwise, the default of QMP is used.
+# $keep_stderr: Set this variable to 'y' to keep QEMU's stderr output on stderr.
+# If this variable is empty, stderr will be redirected to stdout.
# Returns:
# $QEMU_HANDLE: set to a handle value to communicate with this QEMU instance.
#
@@ -151,11 +153,20 @@ function _launch_qemu()
mkfifo "${fifo_out}"
mkfifo "${fifo_in}"
- QEMU_NEED_PID='y'\
- ${QEMU} -nographic -serial none ${comm} -machine accel=qtest "${@}" \
+ if [ -z "$keep_stderr" ]; then
+ QEMU_NEED_PID='y'\
+ ${QEMU} -nographic -serial none ${comm} -machine accel=qtest "${@}" \
>"${fifo_out}" \
2>&1 \
<"${fifo_in}" &
+ elif [ "$keep_stderr" = "y" ]; then
+ QEMU_NEED_PID='y'\
+ ${QEMU} -nographic -serial none ${comm} -machine accel=qtest "${@}" \
+ >"${fifo_out}" \
+ <"${fifo_in}" &
+ else
+ exit 1
+ fi
if [[ "${BASH_VERSINFO[0]}" -ge "5" ||
("${BASH_VERSINFO[0]}" -ge "4" && "${BASH_VERSINFO[1]}" -ge "1") ]]
diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group
index d6e9219e56..65df029d7d 100644
--- a/tests/qemu-iotests/group
+++ b/tests/qemu-iotests/group
@@ -122,6 +122,7 @@
114 rw auto quick
115 rw auto
116 rw auto quick
+117 rw auto
118 rw auto
119 rw auto quick
120 rw auto quick
@@ -141,4 +142,8 @@
137 rw auto
138 rw auto quick
139 rw auto quick
+140 rw auto quick
+141 rw auto quick
142 auto
+143 auto quick
+144 rw auto quick