message: Add call_async method
This makes it possible to perform an async method call that is agnostic
to the event loop running the sd_bus state machine.
Change-Id: I32bc0fdf89c44cc6bab1c4622b143d6e06098659
Signed-off-by: William A. Kennington III <wak@google.com>
diff --git a/test/message/call.cpp b/test/message/call.cpp
new file mode 100644
index 0000000..0ef015f
--- /dev/null
+++ b/test/message/call.cpp
@@ -0,0 +1,102 @@
+#include <sdbusplus/bus.hpp>
+#include <sdbusplus/message.hpp>
+
+#include <chrono>
+#include <string>
+
+#include <gtest/gtest.h>
+
+namespace sdbusplus
+{
+namespace message
+{
+
+using namespace std::literals::chrono_literals;
+
+std::string globalId;
+
+void setGlobalId(message&& m)
+{
+ m.read(globalId);
+}
+
+message newBusIdReq(bus::bus& b)
+{
+ return b.new_method_call("org.freedesktop.DBus", "/org/freedesktop/DBus",
+ "org.freedesktop.DBus", "GetId");
+}
+
+std::string syncBusId(bus::bus& b)
+{
+ std::string ret;
+ newBusIdReq(b).call().read(ret);
+ return ret;
+}
+
+TEST(CallAsync, Function)
+{
+ auto b = bus::new_default();
+ globalId = "";
+ while (b.process_discard())
+ ;
+ auto slot = newBusIdReq(b).call_async(setGlobalId);
+ b.wait(1s);
+ b.process_discard();
+ EXPECT_EQ(syncBusId(b), globalId);
+}
+
+TEST(CallAsync, FunctionPointer)
+{
+ auto b = bus::new_default();
+ globalId = "";
+ while (b.process_discard())
+ ;
+ auto slot = newBusIdReq(b).call_async(&setGlobalId);
+ b.wait(1s);
+ b.process_discard();
+ EXPECT_EQ(syncBusId(b), globalId);
+}
+
+TEST(CallAsync, Lambda)
+{
+ auto b = bus::new_default();
+ std::string id;
+ while (b.process_discard())
+ ;
+ auto slot = newBusIdReq(b).call_async([&](message&& m) { m.read(id); });
+ b.wait(1s);
+ b.process_discard();
+ EXPECT_EQ(syncBusId(b), id);
+}
+
+TEST(CallAsync, SlotDrop)
+{
+ auto b = bus::new_default();
+ globalId = "";
+ while (b.process_discard())
+ ;
+ {
+ auto slot = newBusIdReq(b).call_async(setGlobalId);
+ }
+ b.wait(1s);
+ b.process_discard();
+ EXPECT_EQ("", globalId);
+}
+
+TEST(CallAsync, ExceptionCaught)
+{
+ EXPECT_DEATH(
+ [] {
+ auto b = bus::new_bus();
+ while (b.process_discard())
+ ;
+ auto slot = newBusIdReq(b).call_async(
+ [&](message&&) { throw std::runtime_error("testerror"); });
+ b.wait(1s);
+ b.process_discard();
+ }(),
+ "testerror");
+}
+
+} // namespace message
+} // namespace sdbusplus