aboutsummaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
authorAnthony Liguori <aliguori@us.ibm.com>2012-11-19 09:27:00 -0600
committerAnthony Liguori <aliguori@us.ibm.com>2012-11-19 09:27:00 -0600
commitad1db3b341d3d55e6d722ad868bd48ed4425c9fb (patch)
treec7b1b73c9028e47a0fb83c7ff7fb45e997479f01 /tests
parent5cc82c2d20bdf762519822d3eade5dec4846cee8 (diff)
parente7c8b094c2cf4f7e1609e24efffe3632cba84346 (diff)
Merge remote-tracking branch 'kwolf/for-anthony' into staging
* kwolf/for-anthony: (26 commits) qemu-io: Use bdrv_drain_all instead of qemu_aio_flush megasas: Use bdrv_drain_all instead of qemu_aio_flush vmdk: Fix data corruption bug in WRITE and READ handling fdc: remove last usage of FD_STATE_SEEK fdc: fix typo in zero constant fdc: remove double affectation of FD_MSR_CMDBUSY flag fdc-tests: add tests for VERIFY command fdc: implement VERIFY command fdc-test: Check READ ID fdc: fix false FD_SR0_SEEK fdc: fix FD_SR0_SEEK for initial seek on DMA transfers fdc: fix FD_SR0_SEEK for non-DMA transfers and multi sectors transfers fdc: use status0 field instead of a local variable fdc-test: add tests for non-DMA READ command fdc-test: insert media before fuzzing registers fdc-test: split test_media_change() test, so insert part can be reused fdc: Remove status0 parameter from fdctrl_set_fifo() aio: rename AIOPool to AIOCBInfo aio: use g_slice_alloc() for AIOCB pooling aio: switch aiocb_size type int -> size_t ... Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
Diffstat (limited to 'tests')
-rw-r--r--tests/fdc-test.c192
-rwxr-xr-xtests/qemu-iotests/044117
-rw-r--r--tests/qemu-iotests/044.out6
-rw-r--r--tests/qemu-iotests/common13
-rw-r--r--tests/qemu-iotests/common.config10
-rw-r--r--tests/qemu-iotests/common.rc23
-rw-r--r--tests/qemu-iotests/group1
-rw-r--r--tests/qemu-iotests/iotests.py6
-rwxr-xr-xtests/qemu-iotests/qcow2.py9
9 files changed, 359 insertions, 18 deletions
diff --git a/tests/fdc-test.c b/tests/fdc-test.c
index fa7441110d..4b0301da46 100644
--- a/tests/fdc-test.c
+++ b/tests/fdc-test.c
@@ -48,13 +48,17 @@ enum {
enum {
CMD_SENSE_INT = 0x08,
+ CMD_READ_ID = 0x0a,
CMD_SEEK = 0x0f,
+ CMD_VERIFY = 0x16,
CMD_READ = 0xe6,
CMD_RELATIVE_SEEK_OUT = 0x8f,
CMD_RELATIVE_SEEK_IN = 0xcf,
};
enum {
+ BUSY = 0x10,
+ NONDMA = 0x20,
RQM = 0x80,
DIO = 0x40,
@@ -110,7 +114,7 @@ static void ack_irq(uint8_t *pcn)
g_assert(!get_irq(FLOPPY_IRQ));
}
-static uint8_t send_read_command(void)
+static uint8_t send_read_command(uint8_t cmd)
{
uint8_t drive = 0;
uint8_t head = 0;
@@ -126,7 +130,7 @@ static uint8_t send_read_command(void)
uint8_t ret = 0;
- floppy_send(CMD_READ);
+ floppy_send(cmd);
floppy_send(head << 2 | drive);
g_assert(!get_irq(FLOPPY_IRQ));
floppy_send(cyl);
@@ -152,7 +156,70 @@ static uint8_t send_read_command(void)
}
st0 = floppy_recv();
- if (st0 != 0x60) {
+ if (st0 != 0x40) {
+ ret = 1;
+ }
+
+ floppy_recv();
+ floppy_recv();
+ floppy_recv();
+ floppy_recv();
+ floppy_recv();
+ floppy_recv();
+
+ return ret;
+}
+
+static uint8_t send_read_no_dma_command(int nb_sect, uint8_t expected_st0)
+{
+ uint8_t drive = 0;
+ uint8_t head = 0;
+ uint8_t cyl = 0;
+ uint8_t sect_addr = 1;
+ uint8_t sect_size = 2;
+ uint8_t eot = nb_sect;
+ uint8_t gap = 0x1b;
+ uint8_t gpl = 0xff;
+
+ uint8_t msr = 0;
+ uint8_t st0;
+
+ uint8_t ret = 0;
+
+ floppy_send(CMD_READ);
+ floppy_send(head << 2 | drive);
+ g_assert(!get_irq(FLOPPY_IRQ));
+ floppy_send(cyl);
+ floppy_send(head);
+ floppy_send(sect_addr);
+ floppy_send(sect_size);
+ floppy_send(eot);
+ floppy_send(gap);
+ floppy_send(gpl);
+
+ uint16_t i = 0;
+ uint8_t n = 2;
+ for (; i < n; i++) {
+ msr = inb(FLOPPY_BASE + reg_msr);
+ if (msr == (BUSY | NONDMA | DIO | RQM)) {
+ break;
+ }
+ sleep(1);
+ }
+
+ if (i >= n) {
+ return 1;
+ }
+
+ /* Non-DMA mode */
+ for (i = 0; i < 512 * 2 * nb_sect; i++) {
+ msr = inb(FLOPPY_BASE + reg_msr);
+ assert_bit_set(msr, BUSY | RQM | DIO);
+ inb(FLOPPY_BASE + reg_fifo);
+ }
+
+ st0 = floppy_recv();
+ if (st0 != expected_st0) {
ret = 1;
}
@@ -213,11 +280,11 @@ static void test_read_without_media(void)
{
uint8_t ret;
- ret = send_read_command();
+ ret = send_read_command(CMD_READ);
g_assert(ret == 0);
}
-static void test_media_change(void)
+static void test_media_insert(void)
{
uint8_t dir;
@@ -245,6 +312,13 @@ static void test_media_change(void)
assert_bit_clear(dir, DSKCHG);
dir = inb(FLOPPY_BASE + reg_dir);
assert_bit_clear(dir, DSKCHG);
+}
+
+static void test_media_change(void)
+{
+ uint8_t dir;
+
+ test_media_insert();
/* Eject the floppy and check that DSKCHG is set. Reading it out doesn't
* reset the bit. */
@@ -320,6 +394,108 @@ static void test_relative_seek(void)
g_assert(pcn == 0);
}
+static void test_read_id(void)
+{
+ uint8_t drive = 0;
+ uint8_t head = 0;
+ uint8_t cyl;
+ uint8_t st0;
+
+ /* Seek to track 0 and check with READ ID */
+ send_seek(0);
+
+ floppy_send(CMD_READ_ID);
+ g_assert(!get_irq(FLOPPY_IRQ));
+ floppy_send(head << 2 | drive);
+
+ while (!get_irq(FLOPPY_IRQ)) {
+ /* qemu involves a timer with READ ID... */
+ clock_step(1000000000LL / 50);
+ }
+
+ st0 = floppy_recv();
+ floppy_recv();
+ floppy_recv();
+ cyl = floppy_recv();
+ head = floppy_recv();
+ floppy_recv();
+ floppy_recv();
+
+ g_assert_cmpint(cyl, ==, 0);
+ g_assert_cmpint(head, ==, 0);
+ g_assert_cmpint(st0, ==, head << 2);
+
+ /* Seek to track 8 on head 1 and check with READ ID */
+ head = 1;
+ cyl = 8;
+
+ floppy_send(CMD_SEEK);
+ floppy_send(head << 2 | drive);
+ g_assert(!get_irq(FLOPPY_IRQ));
+ floppy_send(cyl);
+ g_assert(get_irq(FLOPPY_IRQ));
+ ack_irq(NULL);
+
+ floppy_send(CMD_READ_ID);
+ g_assert(!get_irq(FLOPPY_IRQ));
+ floppy_send(head << 2 | drive);
+
+ while (!get_irq(FLOPPY_IRQ)) {
+ /* qemu involves a timer with READ ID... */
+ clock_step(1000000000LL / 50);
+ }
+
+ st0 = floppy_recv();
+ floppy_recv();
+ floppy_recv();
+ cyl = floppy_recv();
+ head = floppy_recv();
+ floppy_recv();
+ floppy_recv();
+
+ g_assert_cmpint(cyl, ==, 8);
+ g_assert_cmpint(head, ==, 1);
+ g_assert_cmpint(st0, ==, head << 2);
+}
+
+static void test_read_no_dma_1(void)
+{
+ uint8_t ret;
+
+ outb(FLOPPY_BASE + reg_dor, inb(FLOPPY_BASE + reg_dor) & ~0x08);
+ send_seek(0);
+ ret = send_read_no_dma_command(1, 0x04);
+ g_assert(ret == 0);
+}
+
+static void test_read_no_dma_18(void)
+{
+ uint8_t ret;
+
+ outb(FLOPPY_BASE + reg_dor, inb(FLOPPY_BASE + reg_dor) & ~0x08);
+ send_seek(0);
+ ret = send_read_no_dma_command(18, 0x04);
+ g_assert(ret == 0);
+}
+
+static void test_read_no_dma_19(void)
+{
+ uint8_t ret;
+
+ outb(FLOPPY_BASE + reg_dor, inb(FLOPPY_BASE + reg_dor) & ~0x08);
+ send_seek(0);
+ ret = send_read_no_dma_command(19, 0x20);
+ g_assert(ret == 0);
+}
+
+static void test_verify(void)
+{
+ uint8_t ret;
+
+ ret = send_read_command(CMD_VERIFY);
+ g_assert(ret == 0);
+}
+
/* success if no crash or abort */
static void fuzz_registers(void)
{
@@ -369,6 +545,12 @@ int main(int argc, char **argv)
qtest_add_func("/fdc/media_change", test_media_change);
qtest_add_func("/fdc/sense_interrupt", test_sense_interrupt);
qtest_add_func("/fdc/relative_seek", test_relative_seek);
+ qtest_add_func("/fdc/read_id", test_read_id);
+ qtest_add_func("/fdc/verify", test_verify);
+ qtest_add_func("/fdc/media_insert", test_media_insert);
+ qtest_add_func("/fdc/read_no_dma_1", test_read_no_dma_1);
+ qtest_add_func("/fdc/read_no_dma_18", test_read_no_dma_18);
+ qtest_add_func("/fdc/read_no_dma_19", test_read_no_dma_19);
qtest_add_func("/fdc/fuzz-registers", fuzz_registers);
ret = g_test_run();
diff --git a/tests/qemu-iotests/044 b/tests/qemu-iotests/044
new file mode 100755
index 0000000000..11ea0f4d35
--- /dev/null
+++ b/tests/qemu-iotests/044
@@ -0,0 +1,117 @@
+#!/usr/bin/env python
+#
+# Tests growing a large refcount table.
+#
+# Copyright (C) 2012 Red Hat, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+
+import time
+import os
+import qcow2
+from qcow2 import QcowHeader
+import iotests
+from iotests import qemu_img, qemu_img_verbose, qemu_io
+import struct
+import subprocess
+
+test_img = os.path.join(iotests.test_dir, 'test.img')
+
+class TestRefcountTableGrowth(iotests.QMPTestCase):
+ '''Abstract base class for image mirroring test cases'''
+
+ def preallocate(self, name):
+ fd = open(name, "r+b")
+ try:
+ off_reftable = 512
+ off_refblock = off_reftable + (512 * 512)
+ off_l1 = off_refblock + (512 * 512 * 64)
+ off_l2 = off_l1 + (512 * 512 * 4 * 8)
+ off_data = off_l2 + (512 * 512 * 4 * 512)
+
+ # Write a new header
+ h = QcowHeader(fd)
+ h.refcount_table_offset = off_reftable
+ h.refcount_table_clusters = 512
+ h.l1_table_offset = off_l1
+ h.l1_size = 512 * 512 * 4
+ h.update(fd)
+
+ # Write a refcount table
+ fd.seek(off_reftable)
+
+ for i in xrange(0, h.refcount_table_clusters):
+ sector = ''.join(struct.pack('>Q',
+ off_refblock + i * 64 * 512 + j * 512)
+ for j in xrange(0, 64))
+ fd.write(sector)
+
+ # Write the refcount blocks
+ assert(fd.tell() == off_refblock)
+ sector = ''.join(struct.pack('>H', 1) for j in xrange(0, 64 * 256))
+ for block in xrange(0, h.refcount_table_clusters):
+ fd.write(sector)
+
+ # Write the L1 table
+ assert(fd.tell() == off_l1)
+ assert(off_l2 + 512 * h.l1_size == off_data)
+ table = ''.join(struct.pack('>Q', (1 << 63) | off_l2 + 512 * j)
+ for j in xrange(0, h.l1_size))
+ fd.write(table)
+
+ # Write the L2 tables
+ assert(fd.tell() == off_l2)
+ img_file_size = h.refcount_table_clusters * 64 * 256 * 512
+ remaining = img_file_size - off_data
+
+ off = off_data
+ while remaining > 1024 * 512:
+ pytable = list((1 << 63) | off + 512 * j
+ for j in xrange(0, 1024))
+ table = struct.pack('>1024Q', *pytable)
+ fd.write(table)
+ remaining = remaining - 1024 * 512
+ off = off + 1024 * 512
+
+ table = ''.join(struct.pack('>Q', (1 << 63) | off + 512 * j)
+ for j in xrange(0, remaining / 512))
+ fd.write(table)
+
+
+ # Data
+ fd.truncate(img_file_size)
+
+
+ finally:
+ fd.close()
+
+
+ def setUp(self):
+ qemu_img('create', '-f', iotests.imgfmt, '-o', 'cluster_size=512', test_img, '16G')
+ self.preallocate(test_img)
+ pass
+
+
+ def tearDown(self):
+ os.remove(test_img)
+ pass
+
+ def test_grow_refcount_table(self):
+ qemu_io('-c', 'write 3800M 1M', test_img)
+ qemu_img_verbose('check' , test_img)
+ pass
+
+if __name__ == '__main__':
+ iotests.main(supported_fmts=['qcow2'])
diff --git a/tests/qemu-iotests/044.out b/tests/qemu-iotests/044.out
new file mode 100644
index 0000000000..7a4007137d
--- /dev/null
+++ b/tests/qemu-iotests/044.out
@@ -0,0 +1,6 @@
+No errors were found on the image.
+.
+----------------------------------------------------------------------
+Ran 1 tests
+
+OK
diff --git a/tests/qemu-iotests/common b/tests/qemu-iotests/common
index 1f6fdf5c56..b3aad89e2c 100644
--- a/tests/qemu-iotests/common
+++ b/tests/qemu-iotests/common
@@ -136,6 +136,7 @@ check options
-vmdk test vmdk
-rbd test rbd
-sheepdog test sheepdog
+ -nbd test nbd
-xdiff graphical mode diff
-nocache use O_DIRECT on backing file
-misalign misalign memory allocations
@@ -197,12 +198,14 @@ testlist options
IMGPROTO=rbd
xpand=false
;;
-
-sheepdog)
IMGPROTO=sheepdog
xpand=false
;;
-
+ -nbd)
+ IMGPROTO=nbd
+ xpand=false
+ ;;
-nocache)
QEMU_IO_OPTIONS="$QEMU_IO_OPTIONS --nocache"
xpand=false
@@ -350,7 +353,11 @@ fi
[ "$QEMU" = "" ] && _fatal "qemu not found"
[ "$QEMU_IMG" = "" ] && _fatal "qemu-img not found"
-[ "$QEMU_IO" = "" ] && _fatal "qemu-img not found"
+[ "$QEMU_IO" = "" ] && _fatal "qemu-io not found"
+
+if [ "$IMGPROTO" = "nbd" ] ; then
+ [ "$QEMU_NBD" = "" ] && _fatal "qemu-nbd not found"
+fi
if $valgrind; then
export REAL_QEMU_IO="$QEMU_IO_PROG"
diff --git a/tests/qemu-iotests/common.config b/tests/qemu-iotests/common.config
index df082e750c..08a3f100b8 100644
--- a/tests/qemu-iotests/common.config
+++ b/tests/qemu-iotests/common.config
@@ -90,21 +90,23 @@ export PS_ALL_FLAGS="-ef"
if [ -z "$QEMU_PROG" ]; then
export QEMU_PROG="`set_prog_path qemu`"
fi
-[ "$QEMU_PROG" = "" ] && _fatal "qemu not found"
if [ -z "$QEMU_IMG_PROG" ]; then
export QEMU_IMG_PROG="`set_prog_path qemu-img`"
fi
-[ "$QEMU_IMG_PROG" = "" ] && _fatal "qemu-img not found"
if [ -z "$QEMU_IO_PROG" ]; then
export QEMU_IO_PROG="`set_prog_path qemu-io`"
fi
-[ "$QEMU_IO_PROG" = "" ] && _fatal "qemu-io not found"
+
+if [ -z "$QEMU_NBD_PROG" ]; then
+ export QEMU_NBD_PROG="`set_prog_path qemu-nbd`"
+fi
export QEMU=$QEMU_PROG
-export QEMU_IMG=$QEMU_IMG_PROG
+export QEMU_IMG=$QEMU_IMG_PROG
export QEMU_IO="$QEMU_IO_PROG $QEMU_IO_OPTIONS"
+export QEMU_NBD=$QEMU_NBD_PROG
[ -f /etc/qemu-iotest.config ] && . /etc/qemu-iotest.config
diff --git a/tests/qemu-iotests/common.rc b/tests/qemu-iotests/common.rc
index 334534f22c..aef5f52b4f 100644
--- a/tests/qemu-iotests/common.rc
+++ b/tests/qemu-iotests/common.rc
@@ -49,6 +49,9 @@ umask 022
if [ "$IMGPROTO" = "file" ]; then
TEST_IMG=$TEST_DIR/t.$IMGFMT
+elif [ "$IMGPROTO" = "nbd" ]; then
+ TEST_IMG_FILE=$TEST_DIR/t.$IMGFMT
+ TEST_IMG="nbd:127.0.0.1:10810"
else
TEST_IMG=$IMGPROTO:$TEST_DIR/t.$IMGFMT
fi
@@ -86,6 +89,13 @@ _make_test_img()
local extra_img_options=""
local image_size=$*
local optstr=""
+ local img_name=""
+
+ if [ -n "$TEST_IMG_FILE" ]; then
+ img_name=$TEST_IMG_FILE
+ else
+ img_name=$TEST_IMG
+ fi
if [ -n "$IMGOPTS" ]; then
optstr=$(_optstr_add "$optstr" "$IMGOPTS")
@@ -104,7 +114,7 @@ _make_test_img()
fi
# XXX(hch): have global image options?
- $QEMU_IMG create -f $IMGFMT $extra_img_options $TEST_IMG $image_size | \
+ $QEMU_IMG create -f $IMGFMT $extra_img_options $img_name $image_size | \
sed -e "s#$IMGPROTO:$TEST_DIR#TEST_DIR#g" \
-e "s#$TEST_DIR#TEST_DIR#g" \
-e "s#$IMGFMT#IMGFMT#g" \
@@ -115,12 +125,23 @@ _make_test_img()
-e "s# compat6=\\(on\\|off\\)##g" \
-e "s# static=\\(on\\|off\\)##g" \
-e "s# lazy_refcounts=\\(on\\|off\\)##g"
+
+ # Start an NBD server on the image file, which is what we'll be talking to
+ if [ $IMGPROTO = "nbd" ]; then
+ eval "$QEMU_NBD -v -t -b 127.0.0.1 -p 10810 $TEST_IMG_FILE &"
+ QEMU_NBD_PID=$!
+ sleep 1 # FIXME: qemu-nbd needs to be listening before we continue
+ fi
}
_cleanup_test_img()
{
case "$IMGPROTO" in
+ nbd)
+ kill $QEMU_NBD_PID
+ rm -f $TEST_IMG_FILE
+ ;;
file)
rm -f $TEST_DIR/t.$IMGFMT
rm -f $TEST_DIR/t.$IMGFMT.orig
diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group
index ac86f54ae3..a4a9044f24 100644
--- a/tests/qemu-iotests/group
+++ b/tests/qemu-iotests/group
@@ -50,3 +50,4 @@
041 rw auto backing
042 rw auto quick
043 rw auto backing
+044 rw auto
diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py
index 735c6745d7..b2eaf20f0b 100644
--- a/tests/qemu-iotests/iotests.py
+++ b/tests/qemu-iotests/iotests.py
@@ -42,6 +42,10 @@ def qemu_img(*args):
devnull = open('/dev/null', 'r+')
return subprocess.call(qemu_img_args + list(args), stdin=devnull, stdout=devnull)
+def qemu_img_verbose(*args):
+ '''Run qemu-img without supressing its output and return the exit code'''
+ return subprocess.call(qemu_img_args + list(args))
+
def qemu_io(*args):
'''Run qemu-io and return the stdout data'''
args = qemu_io_args + list(args)
@@ -182,4 +186,4 @@ def main(supported_fmts=[]):
try:
unittest.main(testRunner=MyTestRunner)
finally:
- sys.stderr.write(re.sub(r'Ran (\d+) test[s] in [\d.]+s', r'Ran \1 tests', output.getvalue()))
+ sys.stderr.write(re.sub(r'Ran (\d+) tests? in [\d.]+s', r'Ran \1 tests', output.getvalue()))
diff --git a/tests/qemu-iotests/qcow2.py b/tests/qemu-iotests/qcow2.py
index 97f37707bc..fecf5b9a59 100755
--- a/tests/qemu-iotests/qcow2.py
+++ b/tests/qemu-iotests/qcow2.py
@@ -233,8 +233,9 @@ def usage():
for name, handler, num_args, desc in cmds:
print " %-20s - %s" % (name, desc)
-if len(sys.argv) < 3:
- usage()
- sys.exit(1)
+if __name__ == '__main__':
+ if len(sys.argv) < 3:
+ usage()
+ sys.exit(1)
-main(sys.argv[1], sys.argv[2], sys.argv[3:])
+ main(sys.argv[1], sys.argv[2], sys.argv[3:])