#include <iostream> #include <sdbusplus/message/append.hpp> #include <cassert> // Global to share the dbus type string between client and server. static std::string verifyTypeString; static constexpr auto SERVICE = "sdbusplus.test"; static constexpr auto INTERFACE = SERVICE; static constexpr auto TEST_METHOD = "test"; static constexpr auto QUIT_METHOD = "quit"; // Open up the sdbus and claim SERVICE name. void serverInit(sd_bus** b) { assert(0 <= sd_bus_open(b)); assert(0 <= sd_bus_request_name(*b, SERVICE, 0)); } // Thread to run the dbus server. void* server(void* b) { auto bus = reinterpret_cast<sd_bus*>(b); while(1) { // Wait for messages. sd_bus_message *m = nullptr; if (0 == sd_bus_process(bus, &m)) { sd_bus_wait(bus, 0); continue; } if(!m) { continue; } if (sd_bus_message_is_method_call(m, INTERFACE, TEST_METHOD)) { // Verify the message type matches what the test expects. // TODO: It would be nice to verify content here as well. assert(verifyTypeString == sd_bus_message_get_signature(m, true)); // Reply to client. sd_bus_reply_method_return(m, nullptr); } else if (sd_bus_message_is_method_call(m, INTERFACE, QUIT_METHOD)) { // Reply and exit. sd_bus_reply_method_return(m, nullptr); break; } } } void newMethodCall__test(sd_bus* b, sd_bus_message** m) { // Allocate a method-call message for INTERFACE,TEST_METHOD. assert(0 <= sd_bus_message_new_method_call(b, m, SERVICE, "/", INTERFACE, TEST_METHOD)); sd_bus_message_set_expect_reply(*m, true); } void runTests() { using namespace std::literals; sd_bus_message* m = nullptr; sd_bus* b = nullptr; // Connect to dbus. assert(0 <= sd_bus_open(&b)); // Test r-value int. { newMethodCall__test(b, &m); sdbusplus::message::append(m, 1); verifyTypeString = "i"; sd_bus_call(b, m, 0, nullptr, nullptr); } // Test l-value int. { newMethodCall__test(b, &m); int a = 1; sdbusplus::message::append(m, a, a); verifyTypeString = "ii"; sd_bus_call(b, m, 0, nullptr, nullptr); } // Test multiple ints. { newMethodCall__test(b, &m); sdbusplus::message::append(m, 1, 2, 3, 4, 5); verifyTypeString = "iiiii"; sd_bus_call(b, m, 0, nullptr, nullptr); } // Test r-value string. { newMethodCall__test(b, &m); sdbusplus::message::append(m, "asdf"s); verifyTypeString = "s"; sd_bus_call(b, m, 0, nullptr, nullptr); } // Test multiple strings, various forms. { newMethodCall__test(b, &m); auto str = "jkl;"s; auto str2 = "JKL:"s; sdbusplus::message::append(m, 1, "asdf", "ASDF"s, str, std::move(str2), 5); verifyTypeString = "issssi"; sd_bus_call(b, m, 0, nullptr, nullptr); } // Shutdown server. sd_bus_call_method(b, SERVICE, "/", INTERFACE, QUIT_METHOD, nullptr, nullptr, nullptr); } int main() { // Initialize and start server thread. pthread_t t; { sd_bus* b; serverInit(&b); pthread_create(&t, NULL, server, b); } runTests(); // Wait for server thread to exit. pthread_join(t, NULL); return 0; }