#include "dbusconnectioneventloop.h" #include class TestDbusQEventLoop: public QObject { Q_OBJECT private: DBusConnection* systemBus; DBusConnection* sessionBus; DBUSConnectionEventLoop* dbusEventLoop; void resetValues() { wasInNotifyFnc = 0; responseString = 0; responseInt = 0; typeError = false; noResponse = false; timerTimeout = false; } void processQTEventLoop(DBusPendingCall* pending, int timeout) { // Reset response values to zeros and reset errors resetValues(); // Do we have something pending? if (pending == NULL) { qDebug("QTEventLoop: pending call is NULL!"); return; } MYDEBUGC("QTEventLoop: processing loop for %d ms", timeout); // If we have some pending operation, let's get notification about result dbus_pending_call_set_notify(pending, TestDbusQEventLoop::pendingNotify, this, NULL); // Setup timeout timer int activeTimer = startTimer(timeout); // Pump QT event loop, but only until pending operation is not finished while (!wasInNotifyFnc) { QCoreApplication::processEvents(QEventLoop::AllEvents); if (timerTimeout) { MYDEBUGC("QTEventLoop: timeout elapsed!!"); return; } } killTimer(activeTimer); } public: int pongServerRunningSession; int pongServerRunningSystem; int wasInNotifyFnc; const char* responseString; uint32_t responseInt; bool typeError; bool noResponse; bool timerTimeout; TestDbusQEventLoop() { resetValues(); } protected: void timerEvent(QTimerEvent *e) { // Set timeout flag and kill timer timerTimeout = true; killTimer(e->timerId()); } static void pendingNotify(DBusPendingCall *pending, void *user_data) { MYDEBUG(); // Get pointer to main class TestDbusQEventLoop* pThis = reinterpret_cast(user_data); // Get message from pending call DBusMessage* message = dbus_pending_call_steal_reply(pending); DBusMessageIter args; // Parse message if (!dbus_message_iter_init(message, &args)) MYDEBUGC("Reply message has no arguments!"); else { // Extract error message if is present const char* error = dbus_message_get_error_name(message); if (error != NULL) { // Check if it is NoReply message pThis->noResponse = (strcmp(error, "org.freedesktop.DBus.Error.NoReply") == 0); } // Get first argument int argType = dbus_message_iter_get_arg_type(&args); switch (argType) { case DBUS_TYPE_STRING: // Get string value dbus_message_iter_get_basic(&args, &pThis->responseString); // Display some debug info if (error != NULL) { MYDEBUGC("Got error [%s]: %s", error, pThis->responseString); } else { MYDEBUGC("Got Reply: %s", pThis->responseString); } break; case DBUS_TYPE_UINT32: // Handle integer dbus_message_iter_get_basic(&args, &pThis->responseInt); // Display some debug info MYDEBUGC("Got Reply: %d", pThis->responseInt); break; default: // Set unknown type flag pThis->typeError = true; // Display some debug info MYDEBUGC("Reply message argument has unsupported type (%d)!", argType); } } // Free message if needed if (message) dbus_message_unref(message); // Free pending call dbus_pending_call_unref(pending); // Set flag to end QEventLoop handler pThis->wasInNotifyFnc = 1; } private slots: void initTestCase() { // First allocate and obtain dbusEventLoop = new DBUSConnectionEventLoop(); systemBus = dbus_bus_get(DBUS_BUS_SYSTEM, NULL); sessionBus = dbus_bus_get(DBUS_BUS_SESSION, NULL);; // Last check, if server is running pongServerRunningSystem = dbus_bus_name_has_owner(systemBus, "com.nokia.dbusqeventloop.test", NULL); pongServerRunningSession = dbus_bus_name_has_owner(sessionBus, "com.nokia.dbusqeventloop.test", NULL); // Create event loop ... QVERIFY(dbusEventLoop != NULL); QVERIFY(dbusEventLoop->addConnection(systemBus) == true); QVERIFY(dbusEventLoop->addConnection(sessionBus) == true); // Then test ... otherwise something don't have to be allocated (i.e. event loop) QVERIFY(systemBus != NULL); QVERIFY(sessionBus != NULL); QVERIFY(pongServerRunningSystem != 0); QVERIFY(pongServerRunningSession != 0); } void cleanupTestCase() { // Create "quit" method call message DBusMessage* message = dbus_message_new_method_call("com.nokia.dbusqeventloop.test", "/", NULL, "quit"); DBusPendingCall* pending; QVERIFY(message != NULL); // Set correct values to suppress fake errors if connection fails in initTestCase() bool systemTimeout = false, sessionTimeout = false; int systemResponse = 12345, sessionResponse = 12345; // If pong server is running on system bus then send quit if (pongServerRunningSystem) { // Send the message dbus_connection_send_with_reply(systemBus, message, &pending, 1000); // Wait for response processQTEventLoop(pending, 4000); systemTimeout = timerTimeout; systemResponse = responseInt; } // If pong server is running on session bus then send quit if (pongServerRunningSession) { // Send the message dbus_connection_send_with_reply(sessionBus, message, &pending, 1000); // Wait for response processQTEventLoop(pending, 4000); sessionTimeout = timerTimeout; sessionResponse = responseInt; } // Free message, it is not necessary to test, QVERIFY upper will end function dbus_message_unref(message); // Cleanup allocated pointers QVERIFY(dbusEventLoop != NULL); if (dbusEventLoop) { delete dbusEventLoop; dbusEventLoop = NULL; } // Check if everything went well QVERIFY(systemTimeout == false); QVERIFY(systemResponse == 12345); QVERIFY(sessionTimeout == false); QVERIFY(sessionResponse == 12345); } void pingSystemBusTest() { // Create message DBusMessage* message = dbus_message_new_method_call("com.nokia.dbusqeventloop.test", "/", NULL, "ping"); QVERIFY(message != NULL); // Add argument to message const char* temp = "pekny kohutik co sa prechadza po svojom novom dvore a obzera si sliepocky"; dbus_message_append_args(message, DBUS_TYPE_STRING, &temp, DBUS_TYPE_INVALID); DBusPendingCall* pending; // Send the message dbus_connection_send_with_reply(systemBus, message, &pending, 3000); // Free message dbus_message_unref(message); // Process event loop processQTEventLoop(pending, 4000); // Check results QVERIFY(timerTimeout == false); QVERIFY(typeError == false); QVERIFY(strcmp(temp, responseString) == 0); } void timeoutSystemBusTest() { // Create message DBusMessage* message = dbus_message_new_method_call("com.nokia.dbusqeventloop.test", "/", NULL, "timeout"); QVERIFY(message != NULL); DBusPendingCall* pending; // Send the message dbus_connection_send_with_reply(systemBus, message, &pending, 1000); // Free message dbus_message_unref(message); // Process event loop processQTEventLoop(pending, 3000); // Check results QVERIFY(timerTimeout == false); QVERIFY(noResponse == true); QVERIFY(typeError == false); // Small pause to process reply sleep(1); } void pingSessionBusTest() { // Create message DBusMessage* message = dbus_message_new_method_call("com.nokia.dbusqeventloop.test", "/", NULL, "ping"); QVERIFY(message != NULL); // Add argument to message const char* temp = "pekny kohutik co sa prechadza po svojom novom dvore a obzera si sliepocky"; dbus_message_append_args(message, DBUS_TYPE_STRING, &temp, DBUS_TYPE_INVALID); DBusPendingCall* pending; // Send the message dbus_connection_send_with_reply(sessionBus, message, &pending, 3000); // Free message dbus_message_unref(message); // Process event loop processQTEventLoop(pending, 4000); // Check results QVERIFY(timerTimeout == false); QVERIFY(typeError == false); QVERIFY(strcmp(temp, responseString) == 0); } void timeoutSessionBusTest() { // Create message DBusMessage* message = dbus_message_new_method_call("com.nokia.dbusqeventloop.test", "/", NULL, "timeout"); QVERIFY(message != NULL); DBusPendingCall* pending; // Send the message dbus_connection_send_with_reply(sessionBus, message, &pending, 1000); // Free message dbus_message_unref(message); // Process event loop processQTEventLoop(pending, 3000); // Check results QVERIFY(timerTimeout == false); QVERIFY(noResponse == true); QVERIFY(typeError == false); // Small pause to process reply sleep(1); } }; QTEST_MAIN(TestDbusQEventLoop) #include "test-dbus-qeventloop.moc"