diff options
Diffstat (limited to 'tests')
-rw-r--r-- | tests/Makefile | 6 | ||||
-rw-r--r-- | tests/acpi-test.c | 5 | ||||
-rw-r--r-- | tests/check-qom-interface.c | 105 | ||||
-rw-r--r-- | tests/i440fx-test.c | 167 |
4 files changed, 264 insertions, 19 deletions
diff --git a/tests/Makefile b/tests/Makefile index 8d258781b7..0b85a34147 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -52,6 +52,8 @@ check-unit-y += tests/test-int128$(EXESUF) gcov-files-test-int128-y = check-unit-y += tests/test-bitops$(EXESUF) check-unit-y += tests/test-qdev-global-props$(EXESUF) +check-unit-y += tests/check-qom-interface$(EXESUF) +gcov-files-check-qom-interface-y = qom/object.c check-block-$(CONFIG_POSIX) += tests/qemu-iotests-quick.sh @@ -138,6 +140,7 @@ test-qapi-obj-y = tests/test-qapi-visit.o tests/test-qapi-types.o $(test-obj-y): QEMU_INCLUDES += -Itests QEMU_CFLAGS += -I$(SRC_PATH)/tests +qom-core-obj = qom/object.o qom/qom-qobject.o qom/container.o tests/test-x86-cpuid.o: QEMU_INCLUDES += -I$(SRC_PATH)/target-i386 @@ -147,6 +150,7 @@ tests/check-qdict$(EXESUF): tests/check-qdict.o libqemuutil.a tests/check-qlist$(EXESUF): tests/check-qlist.o libqemuutil.a tests/check-qfloat$(EXESUF): tests/check-qfloat.o libqemuutil.a tests/check-qjson$(EXESUF): tests/check-qjson.o libqemuutil.a libqemustub.a +tests/check-qom-interface$(EXESUF): tests/check-qom-interface.o $(qom-core-obj) libqemuutil.a tests/test-coroutine$(EXESUF): tests/test-coroutine.o $(block-obj-y) libqemuutil.a libqemustub.a tests/test-aio$(EXESUF): tests/test-aio.o $(block-obj-y) libqemuutil.a libqemustub.a tests/test-throttle$(EXESUF): tests/test-throttle.o $(block-obj-y) libqemuutil.a libqemustub.a @@ -160,7 +164,7 @@ tests/test-int128$(EXESUF): tests/test-int128.o tests/test-qdev-global-props$(EXESUF): tests/test-qdev-global-props.o \ hw/core/qdev.o hw/core/qdev-properties.o \ hw/core/irq.o \ - qom/object.o qom/container.o qom/qom-qobject.o \ + $(qom-core-obj) \ $(test-qapi-obj-y) \ libqemuutil.a libqemustub.a diff --git a/tests/acpi-test.c b/tests/acpi-test.c index ca83b1d6b6..df1af83158 100644 --- a/tests/acpi-test.c +++ b/tests/acpi-test.c @@ -382,6 +382,7 @@ int main(int argc, char *argv[]) { const char *arch = qtest_get_arch(); FILE *f = fopen(disk, "w"); + int ret; fwrite(boot_sector, 1, sizeof boot_sector, f); fclose(f); @@ -390,5 +391,7 @@ int main(int argc, char *argv[]) if (strcmp(arch, "i386") == 0 || strcmp(arch, "x86_64") == 0) { qtest_add_func("acpi/tcg", test_acpi_tcg); } - return g_test_run(); + ret = g_test_run(); + unlink(disk); + return ret; } diff --git a/tests/check-qom-interface.c b/tests/check-qom-interface.c new file mode 100644 index 0000000000..f06380ef14 --- /dev/null +++ b/tests/check-qom-interface.c @@ -0,0 +1,105 @@ +/* + * QOM interface test. + * + * Copyright (C) 2013 Red Hat Inc. + * + * Authors: + * Igor Mammedov <imammedo@redhat.com> + * + * This work is licensed under the terms of the GNU LGPL, version 2.1 or later. + * See the COPYING.LIB file in the top-level directory. + */ +#include <glib.h> + +#include "qom/object.h" +#include "qemu/module.h" + + +#define TYPE_TEST_IF "test-interface" +#define TEST_IF_CLASS(klass) \ + OBJECT_CLASS_CHECK(TestIfClass, (klass), TYPE_TEST_IF) +#define TEST_IF_GET_CLASS(obj) \ + OBJECT_GET_CLASS(TestIfClass, (obj), TYPE_TEST_IF) +#define TEST_IF(obj) \ + INTERFACE_CHECK(TestIf, (obj), TYPE_TEST_IF) + +typedef struct TestIf { + Object parent_obj; +} TestIf; + +typedef struct TestIfClass { + InterfaceClass parent_class; + + uint32_t test; +} TestIfClass; + +static const TypeInfo test_if_info = { + .name = TYPE_TEST_IF, + .parent = TYPE_INTERFACE, + .class_size = sizeof(TestIfClass), +}; + +#define PATTERN 0xFAFBFCFD + +static void test_class_init(ObjectClass *oc, void *data) +{ + TestIfClass *tc = TEST_IF_CLASS(oc); + + g_assert(tc); + tc->test = PATTERN; +} + +#define TYPE_DIRECT_IMPL "direct-impl" + +static const TypeInfo direct_impl_info = { + .name = TYPE_DIRECT_IMPL, + .parent = TYPE_OBJECT, + .class_init = test_class_init, + .interfaces = (InterfaceInfo[]) { + { TYPE_TEST_IF }, + { } + } +}; + +#define TYPE_INTERMEDIATE_IMPL "intermediate-impl" + +static const TypeInfo intermediate_impl_info = { + .name = TYPE_INTERMEDIATE_IMPL, + .parent = TYPE_DIRECT_IMPL, +}; + +static void test_interface_impl(const char *type) +{ + Object *obj = object_new(type); + TestIf *iobj = TEST_IF(obj); + TestIfClass *ioc = TEST_IF_GET_CLASS(iobj); + + g_assert(iobj); + g_assert(ioc->test == PATTERN); +} + +static void interface_direct_test(void) +{ + test_interface_impl(TYPE_DIRECT_IMPL); +} + +static void interface_intermediate_test(void) +{ + test_interface_impl(TYPE_INTERMEDIATE_IMPL); +} + +int main(int argc, char **argv) +{ + g_test_init(&argc, &argv, NULL); + + module_call_init(MODULE_INIT_QOM); + type_register_static(&test_if_info); + type_register_static(&direct_impl_info); + type_register_static(&intermediate_impl_info); + + g_test_add_func("/qom/interface/direct_impl", interface_direct_test); + g_test_add_func("/qom/interface/intermediate_impl", + interface_intermediate_test); + + return g_test_run(); +} diff --git a/tests/i440fx-test.c b/tests/i440fx-test.c index 65c786ca1e..fa3e3d6b87 100644 --- a/tests/i440fx-test.c +++ b/tests/i440fx-test.c @@ -2,9 +2,11 @@ * qtest I440FX test case * * Copyright IBM, Corp. 2012-2013 + * Copyright Red Hat, Inc. 2013 * * Authors: * Anthony Liguori <aliguori@us.ibm.com> + * Laszlo Ersek <lersek@redhat.com> * * This work is licensed under the terms of the GNU GPL, version 2 or later. * See the COPYING file in the top-level directory. @@ -18,6 +20,11 @@ #include <glib.h> #include <string.h> +#include <stdio.h> +#include <unistd.h> +#include <errno.h> +#include <sys/mman.h> +#include <stdlib.h> #define BROKEN 1 @@ -26,16 +33,32 @@ typedef struct TestData { int num_cpus; - QPCIBus *bus; } TestData; +typedef struct FirmwareTestFixture { + /* decides whether we're testing -bios or -pflash */ + bool is_bios; +} FirmwareTestFixture; + +static QPCIBus *test_start_get_bus(const TestData *s) +{ + char *cmdline; + + cmdline = g_strdup_printf("-smp %d", s->num_cpus); + qtest_start(cmdline); + g_free(cmdline); + return qpci_init_pc(); +} + static void test_i440fx_defaults(gconstpointer opaque) { const TestData *s = opaque; + QPCIBus *bus; QPCIDevice *dev; uint32_t value; - dev = qpci_device_find(s->bus, QPCI_DEVFN(0, 0)); + bus = test_start_get_bus(s); + dev = qpci_device_find(bus, QPCI_DEVFN(0, 0)); g_assert(dev != NULL); /* 3.2.2 */ @@ -119,6 +142,8 @@ static void test_i440fx_defaults(gconstpointer opaque) g_assert_cmpint(qpci_config_readb(dev, 0x91), ==, 0x00); /* ERRSTS */ /* 3.2.26 */ g_assert_cmpint(qpci_config_readb(dev, 0x93), ==, 0x00); /* TRC */ + + qtest_end(); } #define PAM_RE 1 @@ -177,6 +202,7 @@ static void write_area(uint32_t start, uint32_t end, uint8_t value) static void test_i440fx_pam(gconstpointer opaque) { const TestData *s = opaque; + QPCIBus *bus; QPCIDevice *dev; int i; static struct { @@ -199,7 +225,8 @@ static void test_i440fx_pam(gconstpointer opaque) { 0xEC000, 0xEFFFF }, /* BIOS Extension */ }; - dev = qpci_device_find(s->bus, QPCI_DEVFN(0, 0)); + bus = test_start_get_bus(s); + dev = qpci_device_find(bus, QPCI_DEVFN(0, 0)); g_assert(dev != NULL); for (i = 0; i < ARRAY_SIZE(pam_area); i++) { @@ -252,34 +279,140 @@ static void test_i440fx_pam(gconstpointer opaque) /* Verify the area is not our new mask */ g_assert(!verify_area(pam_area[i].start, pam_area[i].end, 0x82)); } + qtest_end(); +} + +#define BLOB_SIZE ((size_t)65536) +#define ISA_BIOS_MAXSZ ((size_t)(128 * 1024)) + +/* Create a blob file, and return its absolute pathname as a dynamically + * allocated string. + * The file is closed before the function returns. + * In case of error, NULL is returned. The function prints the error message. + */ +static char *create_blob_file(void) +{ + int ret, fd; + char *pathname; + GError *error = NULL; + + ret = -1; + fd = g_file_open_tmp("blob_XXXXXX", &pathname, &error); + if (fd == -1) { + fprintf(stderr, "unable to create blob file: %s\n", error->message); + g_error_free(error); + } else { + if (ftruncate(fd, BLOB_SIZE) == -1) { + fprintf(stderr, "ftruncate(\"%s\", %zu): %s\n", pathname, + BLOB_SIZE, strerror(errno)); + } else { + void *buf; + + buf = mmap(NULL, BLOB_SIZE, PROT_WRITE, MAP_SHARED, fd, 0); + if (buf == MAP_FAILED) { + fprintf(stderr, "mmap(\"%s\", %zu): %s\n", pathname, BLOB_SIZE, + strerror(errno)); + } else { + size_t i; + + for (i = 0; i < BLOB_SIZE; ++i) { + ((uint8_t *)buf)[i] = i; + } + munmap(buf, BLOB_SIZE); + ret = 0; + } + } + close(fd); + if (ret == -1) { + unlink(pathname); + g_free(pathname); + } + } + + return ret == -1 ? NULL : pathname; +} + +static void test_i440fx_firmware(FirmwareTestFixture *fixture, + gconstpointer user_data) +{ + char *fw_pathname, *cmdline; + uint8_t *buf; + size_t i, isa_bios_size; + + fw_pathname = create_blob_file(); + g_assert(fw_pathname != NULL); + + /* Better hope the user didn't put metacharacters in TMPDIR and co. */ + cmdline = g_strdup_printf("-S %s %s", + fixture->is_bios ? "-bios" : "-pflash", + fw_pathname); + g_test_message("qemu cmdline: %s", cmdline); + qtest_start(cmdline); + g_free(cmdline); + + /* Qemu has loaded the firmware (because qtest_start() only returns after + * the QMP handshake completes). We must unlink the firmware blob right + * here, because any assertion firing below would leak it in the + * filesystem. This is also the reason why we recreate the blob every time + * this function is invoked. + */ + unlink(fw_pathname); + g_free(fw_pathname); + + /* check below 4G */ + buf = g_malloc0(BLOB_SIZE); + memread(0x100000000ULL - BLOB_SIZE, buf, BLOB_SIZE); + for (i = 0; i < BLOB_SIZE; ++i) { + g_assert_cmphex(buf[i], ==, (uint8_t)i); + } + + /* check in ISA space too */ + memset(buf, 0, BLOB_SIZE); + isa_bios_size = ISA_BIOS_MAXSZ < BLOB_SIZE ? ISA_BIOS_MAXSZ : BLOB_SIZE; + memread(0x100000 - isa_bios_size, buf, isa_bios_size); + for (i = 0; i < isa_bios_size; ++i) { + g_assert_cmphex(buf[i], ==, + (uint8_t)((BLOB_SIZE - isa_bios_size) + i)); + } + + g_free(buf); + qtest_end(); +} + +static void add_firmware_test(const char *testpath, + void (*setup_fixture)(FirmwareTestFixture *f, + gconstpointer test_data)) +{ + g_test_add(testpath, FirmwareTestFixture, NULL, setup_fixture, + test_i440fx_firmware, NULL); +} + +static void request_bios(FirmwareTestFixture *fixture, + gconstpointer user_data) +{ + fixture->is_bios = true; +} + +static void request_pflash(FirmwareTestFixture *fixture, + gconstpointer user_data) +{ + fixture->is_bios = false; } int main(int argc, char **argv) { - QTestState *s; TestData data; - char *cmdline; int ret; g_test_init(&argc, &argv, NULL); data.num_cpus = 1; - cmdline = g_strdup_printf("-smp %d", data.num_cpus); - s = qtest_start(cmdline); - g_free(cmdline); - - data.bus = qpci_init_pc(); - g_test_add_data_func("/i440fx/defaults", &data, test_i440fx_defaults); g_test_add_data_func("/i440fx/pam", &data, test_i440fx_pam); - + add_firmware_test("/i440fx/firmware/bios", request_bios); + add_firmware_test("/i440fx/firmware/pflash", request_pflash); ret = g_test_run(); - - if (s) { - qtest_quit(s); - } - return ret; } |