/* * Copyright (C) 2013, 2014 Red Hat, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library. If not, see * . */ #include #define LIBVIRT_VIRDBUSPRIV_H_ALLOW #include "virdbuspriv.h" #include "virlog.h" #include "testutils.h" VIR_LOG_INIT("tests.dbustest"); #define VERIFY(typname, valorig, valnew, fmt) \ do { \ VIR_DEBUG("Compare " typname " '" fmt "' to '" \ fmt "'", valorig, valnew); \ if (valorig != valnew) { \ fprintf(stderr, "Failed to round-trip " typname " '" \ fmt "' to '" fmt "'\n", valorig, valnew); \ goto cleanup; \ } \ } while (0) #define VERIFY_STR(typname, valorig, valnew, fmt) \ do { \ VIR_DEBUG("Compare " typname " '" fmt "' to '" \ fmt "'", valorig, valnew); \ if (STRNEQ(valorig, valnew)) { \ fprintf(stderr, "Failed to round-trip " typname " '" \ fmt "' to '" fmt "'\n", valorig, valnew); \ goto cleanup; \ } \ } while (0) static int testMessageSimple(const void *args G_GNUC_UNUSED) { DBusMessage *msg = NULL; int ret = -1; unsigned char in_byte = 200, out_byte = 0; bool in_bool = true, out_bool = false; short in_int16 = 0xfefe, out_int16 = 0; unsigned short in_uint16 = 32000, out_uint16 = 0; int in_int32 = 100000000, out_int32 = 0; unsigned int in_uint32 = 200000000, out_uint32 = 0; long long in_int64 = 1000000000000LL, out_int64 = 0; unsigned long long in_uint64 = 2000000000000LL, out_uint64 = 0; double in_double = 3.14159265359, out_double = 0; const char *in_string = "Hello World"; char *out_string = NULL; const char *in_objectpath = "/org/libvirt/test"; char *out_objectpath = NULL; const char *in_signature = "ybnqiuxtdsog"; char *out_signature = NULL; if (!(msg = dbus_message_new_method_call("org.libvirt.test", "/org/libvirt/test", "org.libvirt.test.astrochicken", "cluck"))) { VIR_DEBUG("Failed to allocate method call"); goto cleanup; } if (virDBusMessageEncode(msg, "ybnqiuxtdsog", in_byte, in_bool, in_int16, in_uint16, in_int32, in_uint32, in_int64, in_uint64, in_double, in_string, in_objectpath, in_signature) < 0) { VIR_DEBUG("Failed to encode arguments"); goto cleanup; } if (virDBusMessageDecode(msg, "ybnqiuxtdsog", &out_byte, &out_bool, &out_int16, &out_uint16, &out_int32, &out_uint32, &out_int64, &out_uint64, &out_double, &out_string, &out_objectpath, &out_signature) < 0) { VIR_DEBUG("Failed to decode arguments"); goto cleanup; } VERIFY("byte", in_byte, out_byte, "%d"); VERIFY("bool", in_bool, out_bool, "%d"); VERIFY("int16", in_int16, out_int16, "%d"); VERIFY("uint16", in_int16, out_int16, "%d"); VERIFY("int32", in_int32, out_int32, "%d"); VERIFY("uint32", in_int32, out_int32, "%d"); VERIFY("int64", in_int64, out_int64, "%lld"); VERIFY("uint64", in_int64, out_int64, "%lld"); VERIFY("double", in_double, out_double, "%lf"); VERIFY_STR("string", in_string, out_string, "%s"); VERIFY_STR("objectpath", in_objectpath, out_objectpath, "%s"); VERIFY_STR("signature", in_signature, out_signature, "%s"); ret = 0; cleanup: VIR_FREE(out_string); VIR_FREE(out_signature); VIR_FREE(out_objectpath); virDBusMessageUnref(msg); return ret; } static int testMessageVariant(const void *args G_GNUC_UNUSED) { DBusMessage *msg = NULL; int ret = -1; const char *in_str1 = "Hello"; int in_int32 = 100000000, out_int32 = 0; const char *in_str2 = "World"; char *out_str1 = NULL, *out_str2 = NULL; if (!(msg = dbus_message_new_method_call("org.libvirt.test", "/org/libvirt/test", "org.libvirt.test.astrochicken", "cluck"))) { VIR_DEBUG("Failed to allocate method call"); goto cleanup; } if (virDBusMessageEncode(msg, "svs", in_str1, "i", in_int32, in_str2) < 0) { VIR_DEBUG("Failed to encode arguments"); goto cleanup; } if (virDBusMessageDecode(msg, "svs", &out_str1, "i", &out_int32, &out_str2) < 0) { VIR_DEBUG("Failed to decode arguments"); goto cleanup; } VERIFY_STR("str1", in_str1, out_str1, "%s"); VERIFY("int32", in_int32, out_int32, "%d"); VERIFY_STR("str2", in_str2, out_str2, "%s"); ret = 0; cleanup: VIR_FREE(out_str1); VIR_FREE(out_str2); virDBusMessageUnref(msg); return ret; } static int testMessageArray(const void *args G_GNUC_UNUSED) { DBusMessage *msg = NULL; int ret = -1; const char *in_str1 = "Hello"; int in_int32a = 1000000000, out_int32a = 0; int in_int32b = 2000000000, out_int32b = 0; int in_int32c = -2000000000, out_int32c = 0; bool in_bool[] = { true, false, true }, out_bool[] = { false, true, false}; const char *in_str2 = "World"; char *out_str1 = NULL, *out_str2 = NULL; if (!(msg = dbus_message_new_method_call("org.libvirt.test", "/org/libvirt/test", "org.libvirt.test.astrochicken", "cluck"))) { VIR_DEBUG("Failed to allocate method call"); goto cleanup; } if (virDBusMessageEncode(msg, "saiabs", in_str1, 3, in_int32a, in_int32b, in_int32c, 3, in_bool[0], in_bool[1], in_bool[2], in_str2) < 0) { VIR_DEBUG("Failed to encode arguments"); goto cleanup; } if (virDBusMessageDecode(msg, "saiabs", &out_str1, 3, &out_int32a, &out_int32b, &out_int32c, 3, &out_bool[0], &out_bool[1], &out_bool[2], &out_str2) < 0) { VIR_DEBUG("Failed to decode arguments"); goto cleanup; } VERIFY_STR("str1", in_str1, out_str1, "%s"); VERIFY("int32a", in_int32a, out_int32a, "%d"); VERIFY("int32b", in_int32b, out_int32b, "%d"); VERIFY("int32c", in_int32c, out_int32c, "%d"); VERIFY("bool[0]", in_bool[0], out_bool[0], "%d"); VERIFY("bool[1]", in_bool[1], out_bool[1], "%d"); VERIFY("bool[2]", in_bool[2], out_bool[2], "%d"); VERIFY_STR("str2", in_str2, out_str2, "%s"); ret = 0; cleanup: VIR_FREE(out_str1); VIR_FREE(out_str2); virDBusMessageUnref(msg); return ret; } static int testMessageEmptyArrayRef(const void *args G_GNUC_UNUSED) { DBusMessage *msg = NULL; int ret = -1; const char *in_strv1[] = {}; size_t out_nstrv1; char **out_strv1 = NULL; if (!(msg = dbus_message_new_method_call("org.libvirt.test", "/org/libvirt/test", "org.libvirt.test.astrochicken", "cluck"))) { VIR_DEBUG("Failed to allocate method call"); goto cleanup; } if (virDBusMessageEncode(msg, "a&s", 0, in_strv1) < 0) { VIR_DEBUG("Failed to encode arguments"); goto cleanup; } if (virDBusMessageDecode(msg, "a&s", &out_nstrv1, &out_strv1) < 0) { VIR_DEBUG("Failed to decode arguments"); goto cleanup; } if (out_nstrv1 != 0) { fprintf(stderr, "Expected 0 string, but got %zu\n", out_nstrv1); goto cleanup; } ret = 0; cleanup: virDBusMessageUnref(msg); return ret; } static int testMessageSingleArrayRef(const void *args G_GNUC_UNUSED) { DBusMessage *msg = NULL; int ret = -1; const char *in_strv1[] = { "Fishfood", }; char **out_strv1 = NULL; size_t out_nstrv1 = 0; if (!(msg = dbus_message_new_method_call("org.libvirt.test", "/org/libvirt/test", "org.libvirt.test.astrochicken", "cluck"))) { VIR_DEBUG("Failed to allocate method call"); goto cleanup; } if (virDBusMessageEncode(msg, "a&s", 1, in_strv1) < 0) { VIR_DEBUG("Failed to encode arguments"); goto cleanup; } if (virDBusMessageDecode(msg, "a&s", &out_nstrv1, &out_strv1) < 0) { VIR_DEBUG("Failed to decode arguments"); goto cleanup; } if (out_nstrv1 != 1) { fprintf(stderr, "Expected 1 string, but got %zu\n", out_nstrv1); goto cleanup; } VERIFY_STR("strv1[0]", in_strv1[0], out_strv1[0], "%s"); ret = 0; cleanup: if (out_strv1) VIR_FREE(out_strv1[0]); VIR_FREE(out_strv1); virDBusMessageUnref(msg); return ret; } static int testMessageArrayRef(const void *args G_GNUC_UNUSED) { DBusMessage *msg = NULL; int ret = -1; const char *in_str1 = "Hello"; int in_int32[] = { 100000000, 2000000000, -2000000000 }; bool in_bool[] = { true, false, true }; const char *in_strv1[] = { "Fishfood", }; const char *in_strv2[] = { "Hello", "World", }; int *out_int32 = NULL; size_t out_nint32 = 0; bool *out_bool = NULL; size_t out_nbool = 0; char **out_strv1 = NULL; char **out_strv2 = NULL; size_t out_nstrv1 = 0; size_t out_nstrv2 = 0; const char *in_str2 = "World"; char *out_str1 = NULL, *out_str2 = NULL; size_t i; if (!(msg = dbus_message_new_method_call("org.libvirt.test", "/org/libvirt/test", "org.libvirt.test.astrochicken", "cluck"))) { VIR_DEBUG("Failed to allocate method call"); goto cleanup; } if (virDBusMessageEncode(msg, "sa&sa&ia&ba&ss", in_str1, 1, in_strv1, 3, in_int32, 3, in_bool, 2, in_strv2, in_str2) < 0) { VIR_DEBUG("Failed to encode arguments"); goto cleanup; } if (virDBusMessageDecode(msg, "sa&sa&ia&ba&ss", &out_str1, &out_nstrv1, &out_strv1, &out_nint32, &out_int32, &out_nbool, &out_bool, &out_nstrv2, &out_strv2, &out_str2) < 0) { VIR_DEBUG("Failed to decode arguments"); goto cleanup; } VERIFY_STR("str1", in_str1, out_str1, "%s"); if (out_nstrv1 != 1) { fprintf(stderr, "Expected 1 string, but got %zu\n", out_nstrv1); goto cleanup; } VERIFY_STR("strv1[0]", in_strv1[0], out_strv1[0], "%s"); if (out_nint32 != 3) { fprintf(stderr, "Expected 3 integers, but got %zu\n", out_nint32); goto cleanup; } VERIFY("int32a", in_int32[0], out_int32[0], "%d"); VERIFY("int32b", in_int32[1], out_int32[1], "%d"); VERIFY("int32c", in_int32[2], out_int32[2], "%d"); if (out_nbool != 3) { fprintf(stderr, "Expected 3 bools, but got %zu\n", out_nbool); goto cleanup; } VERIFY("bool[0]", in_bool[0], out_bool[0], "%d"); VERIFY("bool[1]", in_bool[1], out_bool[1], "%d"); VERIFY("bool[2]", in_bool[2], out_bool[2], "%d"); if (out_nstrv2 != 2) { fprintf(stderr, "Expected 2 strings, but got %zu\n", out_nstrv2); goto cleanup; } VERIFY_STR("strv2[0]", in_strv2[0], out_strv2[0], "%s"); VERIFY_STR("strv2[1]", in_strv2[1], out_strv2[1], "%s"); VERIFY_STR("str2", in_str2, out_str2, "%s"); ret = 0; cleanup: VIR_FREE(out_int32); VIR_FREE(out_bool); VIR_FREE(out_str1); VIR_FREE(out_str2); for (i = 0; i < out_nstrv1; i++) VIR_FREE(out_strv1[i]); VIR_FREE(out_strv1); for (i = 0; i < out_nstrv2; i++) VIR_FREE(out_strv2[i]); VIR_FREE(out_strv2); virDBusMessageUnref(msg); return ret; } static int testMessageStruct(const void *args G_GNUC_UNUSED) { DBusMessage *msg = NULL; int ret = -1; unsigned char in_byte = 200, out_byte = 0; bool in_bool = true, out_bool = false; short in_int16 = 12000, out_int16 = 0; unsigned short in_uint16 = 32000, out_uint16 = 0; int in_int32 = 100000000, out_int32 = 0; unsigned int in_uint32 = 200000000, out_uint32 = 0; long long in_int64 = -1000000000000LL, out_int64 = 0; unsigned long long in_uint64 = 2000000000000LL, out_uint64 = 0; double in_double = 3.14159265359, out_double = 0; const char *in_string = "Hello World"; char *out_string = NULL; const char *in_objectpath = "/org/libvirt/test"; char *out_objectpath = NULL; const char *in_signature = "ybnqiuxtdsog"; char *out_signature = NULL; if (!(msg = dbus_message_new_method_call("org.libvirt.test", "/org/libvirt/test", "org.libvirt.test.astrochicken", "cluck"))) { VIR_DEBUG("Failed to allocate method call"); goto cleanup; } if (virDBusMessageEncode(msg, "ybn(qiuxtds)og", in_byte, in_bool, in_int16, in_uint16, in_int32, in_uint32, in_int64, in_uint64, in_double, in_string, in_objectpath, in_signature) < 0) { VIR_DEBUG("Failed to encode arguments"); goto cleanup; } if (virDBusMessageDecode(msg, "ybn(qiuxtds)og", &out_byte, &out_bool, &out_int16, &out_uint16, &out_int32, &out_uint32, &out_int64, &out_uint64, &out_double, &out_string, &out_objectpath, &out_signature) < 0) { VIR_DEBUG("Failed to decode arguments"); goto cleanup; } VERIFY("byte", in_byte, out_byte, "%d"); VERIFY("bool", in_bool, out_bool, "%d"); VERIFY("int16", in_int16, out_int16, "%d"); VERIFY("uint16", in_int16, out_int16, "%d"); VERIFY("int32", in_int32, out_int32, "%d"); VERIFY("uint32", in_int32, out_int32, "%d"); VERIFY("int64", in_int64, out_int64, "%lld"); VERIFY("uint64", in_int64, out_int64, "%lld"); VERIFY("double", in_double, out_double, "%lf"); VERIFY_STR("string", in_string, out_string, "%s"); VERIFY_STR("objectpath", in_objectpath, out_objectpath, "%s"); VERIFY_STR("signature", in_signature, out_signature, "%s"); ret = 0; cleanup: VIR_FREE(out_string); VIR_FREE(out_signature); VIR_FREE(out_objectpath); virDBusMessageUnref(msg); return ret; } static int testMessageDict(const void *args G_GNUC_UNUSED) { DBusMessage *msg = NULL; int ret = -1; const char *in_str1 = "Hello"; int in_int32a = 100000000, out_int32a = 0; const char *in_key1 = "turnover"; int in_int32b = 200000000, out_int32b = 0; const char *in_key2 = "revenue"; int in_int32c = 300000000, out_int32c = 0; const char *in_key3 = "debt"; const char *in_str2 = "World"; char *out_str1 = NULL, *out_str2 = NULL; char *out_key1 = NULL, *out_key2 = NULL, *out_key3 = NULL; if (!(msg = dbus_message_new_method_call("org.libvirt.test", "/org/libvirt/test", "org.libvirt.test.astrochicken", "cluck"))) { VIR_DEBUG("Failed to allocate method call"); goto cleanup; } if (virDBusMessageEncode(msg, "(sa{si}s)", in_str1, 3, in_key1, in_int32a, in_key2, in_int32b, in_key3, in_int32c, in_str2) < 0) { VIR_DEBUG("Failed to encode arguments"); goto cleanup; } if (virDBusMessageDecode(msg, "(sa{si}s)", &out_str1, 3, &out_key1, &out_int32a, &out_key2, &out_int32b, &out_key3, &out_int32c, &out_str2) < 0) { VIR_DEBUG("Failed to decode arguments"); goto cleanup; } VERIFY_STR("str1", in_str1, out_str1, "%s"); VERIFY("int32a", in_int32a, out_int32a, "%d"); VERIFY("int32b", in_int32b, out_int32b, "%d"); VERIFY("int32c", in_int32c, out_int32c, "%d"); VERIFY_STR("key1", in_key1, out_key1, "%s"); VERIFY_STR("key1", in_key2, out_key2, "%s"); VERIFY_STR("key1", in_key3, out_key3, "%s"); VERIFY_STR("str2", in_str2, out_str2, "%s"); ret = 0; cleanup: VIR_FREE(out_str1); VIR_FREE(out_str2); VIR_FREE(out_key1); VIR_FREE(out_key2); VIR_FREE(out_key3); virDBusMessageUnref(msg); return ret; } static int testMessageDictRef(const void *args G_GNUC_UNUSED) { DBusMessage *msg = NULL; int ret = -1; const char *in_str1 = "Hello"; const char *in_strv1[] = { "Fruit1", "Apple", "Fruit2", "Orange", "Fruit3", "Kiwi", }; const char *in_str2 = "World"; char *out_str1 = NULL; size_t out_nint32 = 0; char **out_strv1 = NULL; char *out_str2 = NULL; if (!(msg = dbus_message_new_method_call("org.libvirt.test", "/org/libvirt/test", "org.libvirt.test.astrochicken", "cluck"))) { VIR_DEBUG("Failed to allocate method call"); goto cleanup; } if (virDBusMessageEncode(msg, "(sa&{ss}s)", in_str1, 3, in_strv1, in_str2) < 0) { VIR_DEBUG("Failed to encode arguments"); goto cleanup; } if (virDBusMessageDecode(msg, "(sa&{ss}s)", &out_str1, &out_nint32, &out_strv1, &out_str2) < 0) { VIR_DEBUG("Failed to decode arguments: '%s'", virGetLastErrorMessage()); goto cleanup; } VERIFY_STR("str1", in_str1, out_str1, "%s"); VERIFY_STR("strv1[0]", in_strv1[0], out_strv1[0], "%s"); VERIFY_STR("strv1[1]", in_strv1[1], out_strv1[1], "%s"); VERIFY_STR("strv1[2]", in_strv1[2], out_strv1[2], "%s"); VERIFY_STR("strv1[3]", in_strv1[3], out_strv1[3], "%s"); VERIFY_STR("strv1[4]", in_strv1[4], out_strv1[4], "%s"); VERIFY_STR("strv1[5]", in_strv1[5], out_strv1[5], "%s"); VERIFY_STR("str2", in_str2, out_str2, "%s"); ret = 0; cleanup: VIR_FREE(out_str1); VIR_FREE(out_str2); if (out_strv1) { VIR_FREE(out_strv1[0]); VIR_FREE(out_strv1[1]); VIR_FREE(out_strv1[2]); VIR_FREE(out_strv1[3]); VIR_FREE(out_strv1[4]); VIR_FREE(out_strv1[5]); } VIR_FREE(out_strv1); virDBusMessageUnref(msg); return ret; } static int testMessageEmptyDictRef(const void *args G_GNUC_UNUSED) { DBusMessage *msg = NULL; int ret = -1; const char *in_strv1[] = {}; size_t out_nint32 = 0; char **out_strv1 = NULL; if (!(msg = dbus_message_new_method_call("org.libvirt.test", "/org/libvirt/test", "org.libvirt.test.astrochicken", "cluck"))) { VIR_DEBUG("Failed to allocate method call"); goto cleanup; } if (virDBusMessageEncode(msg, "a&{ss}", 0, in_strv1) < 0) { VIR_DEBUG("Failed to encode arguments"); goto cleanup; } if (virDBusMessageDecode(msg, "a&{ss}", &out_nint32, &out_strv1) < 0) { VIR_DEBUG("Failed to decode arguments: '%s'", virGetLastErrorMessage()); goto cleanup; } if (out_nint32 != 0) { fprintf(stderr, "Unexpected dict entries\n"); goto cleanup; } ret = 0; cleanup: virDBusMessageUnref(msg); return ret; } static int mymain(void) { int ret = 0; if (virTestRun("Test message simple ", testMessageSimple, NULL) < 0) ret = -1; if (virTestRun("Test message variant ", testMessageVariant, NULL) < 0) ret = -1; if (virTestRun("Test message array ", testMessageArray, NULL) < 0) ret = -1; if (virTestRun("Test message array empty ref ", testMessageEmptyArrayRef, NULL) < 0) ret = -1; if (virTestRun("Test message array single ref ", testMessageSingleArrayRef, NULL) < 0) ret = -1; if (virTestRun("Test message array ref ", testMessageArrayRef, NULL) < 0) ret = -1; if (virTestRun("Test message struct ", testMessageStruct, NULL) < 0) ret = -1; if (virTestRun("Test message dict ", testMessageDict, NULL) < 0) ret = -1; if (virTestRun("Test message dict empty ref ", testMessageEmptyDictRef, NULL) < 0) ret = -1; if (virTestRun("Test message dict ref ", testMessageDictRef, NULL) < 0) ret = -1; return ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE; } VIR_TEST_MAIN(mymain)