summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPatrick Ohly <patrick.ohly@intel.com>2012-03-22 17:46:10 +0100
committerPatrick Ohly <patrick.ohly@intel.com>2012-05-10 22:08:45 +0200
commit6ac33ec077e93d85624de1b76a6a9e6daa2e3721 (patch)
tree1601efb8383f23595acf3a4d992bbf5955d2f4f3
parenteb6b80698eb41be94cc89b2dc92468f2517df984 (diff)
dbus-client-server: added test code for client or server dying
The test covers waiting for a reply that never comes because the peer dies. GIO D-Bus returns a "connection lost" error in this case. Still need to test what happens when a process isn't currently waiting for a response to its own call, but rather a method invocation from its peer - it seems that it'll simply get stuck waiting forever when the peer dies.
-rw-r--r--test/dbus-client-server.cpp79
1 files changed, 75 insertions, 4 deletions
diff --git a/test/dbus-client-server.cpp b/test/dbus-client-server.cpp
index 3c941567..6bef63dd 100644
--- a/test/dbus-client-server.cpp
+++ b/test/dbus-client-server.cpp
@@ -31,6 +31,7 @@ public:
m_server.add(this, &Test::hello, "Hello");
m_server.add(this, &Test::getstrings, "GetStrings");
m_server.add(this, &Test::getmixed, "GetMixed");
+ m_server.add(this, &Test::kill, "Kill");
}
void activate()
@@ -65,6 +66,12 @@ public:
third = "world";
}
+ void kill()
+ {
+ std::cout << "killing myself as requested" << std::endl;
+ abort();
+ }
+
void disconnected()
{
std::cout << "connection disconnected";
@@ -110,12 +117,37 @@ class TestProxy : public GDBusCXX::DBusRemoteObject
public:
TestProxy(const GDBusCXX::DBusConnectionPtr &conn) :
GDBusCXX::DBusRemoteObject(conn.get(), "/test", "org.example.Test", "direct.peer"),
- m_hello(*this, "Hello") {
+ m_hello(*this, "Hello"),
+ m_kill(*this, "Kill")
+ {
}
GDBusCXX::DBusClientCall1<std::string> m_hello;
+ GDBusCXX::DBusClientCall0 m_kill;
};
+static void onChildConnectKill(const GDBusCXX::DBusConnectionPtr &conn,
+ boost::scoped_ptr<Test> &testptr)
+{
+ std::cout << "child is ready, kill it" << std::endl;
+ testptr.reset(new Test(conn.get()));
+ testptr->activate();
+
+ // process messages already before returning from this onConnect callback
+ dbus_bus_connection_undelay(conn);
+
+ TestProxy proxy(conn);
+ try {
+ proxy.m_kill();
+ } catch (const std::runtime_error &ex) {
+ std::cout << "caught exception, as expected: " << ex.what() << std::endl;
+ std::cout << "aborting..." << std::endl;
+ abort();
+ }
+ std::cout << "did not get the expected exception" << std::endl;
+ abort();
+}
+
static void helloCB(GMainLoop *loop, const std::string &res, const std::string &error)
{
if (!error.empty()) {
@@ -129,6 +161,8 @@ static void helloCB(GMainLoop *loop, const std::string &res, const std::string &
static void callServer(const GDBusCXX::DBusConnectionPtr &conn)
{
TestProxy proxy(conn);
+ Test test(conn.get());
+ test.activate();
// process messages already before returning from this onConnect callback
dbus_bus_connection_undelay(conn);
@@ -156,6 +190,33 @@ static void callServer(const GDBusCXX::DBusConnectionPtr &conn)
guard.reset(new GDBusCXX::DBusObject(conn, "foo", "bar", true));
}
+static void killServer(const GDBusCXX::DBusConnectionPtr &conn)
+{
+ TestProxy proxy(conn);
+
+ // process messages already before returning from this onConnect callback
+ dbus_bus_connection_undelay(conn);
+
+ try {
+ proxy.m_kill();
+ } catch (const std::runtime_error &ex) {
+ std::cout << "caught exception, as expected: " << ex.what() << std::endl;
+ std::cout << "aborting..." << std::endl;
+ abort();
+ }
+ std::cout << "did not get the expected exception" << std::endl;
+ abort();
+}
+
+static void calledByServer(const GDBusCXX::DBusConnectionPtr &conn)
+{
+ // run until Test::kill() is invoked by server
+ Test test(conn.get());
+ test.activate();
+ dbus_bus_connection_undelay(conn);
+ g_main_loop_run(loop.get());
+}
+
void signalHandler (int sig)
{
if (loop) {
@@ -177,6 +238,7 @@ int main(int argc, char **argv)
gboolean opt_fork_exec;
gboolean opt_fork_exec_failure;
gchar *opt_address;
+ gchar *opt_kill;
GOptionContext *opt_context;
// gboolean opt_allow_anonymous;
SyncEvo::GErrorCXX gerror;
@@ -184,7 +246,8 @@ int main(int argc, char **argv)
GOptionEntry opt_entries[] = {
{ "server", 's', 0, G_OPTION_ARG_NONE, &opt_server, "Start a server instead of a client", NULL },
{ "forkexec", 'e', 0, G_OPTION_ARG_NONE, &opt_fork_exec, "Use fork+exec to start the client (implies --server)", NULL },
- { "forkfailure", 'f', 0, G_OPTION_ARG_NONE, &opt_fork_exec_failure, "Fork /bin/false to simulate a failure in the child (implies --forkexec)", NULL },
+ { "forkfailure", 'f', 0, G_OPTION_ARG_NONE, &opt_fork_exec_failure, "Fork /bin/false to simulate a failure in the child (implies )", NULL },
+ { "forkkill", 'a', 0, G_OPTION_ARG_STRING, &opt_kill, "'child/parent' call peer which kills itself before replying (implies --forkexec)", NULL },
{ "address", 'a', 0, G_OPTION_ARG_STRING, &opt_address, "D-Bus address to use", NULL },
// { "allow-anonymous", 'n', 0, G_OPTION_ARG_NONE, &opt_allow_anonymous, "Allow anonymous authentication", NULL },
{ NULL}
@@ -193,6 +256,7 @@ int main(int argc, char **argv)
g_type_init();
opt_address = NULL;
+ opt_kill = NULL;
opt_server = FALSE;
opt_fork_exec = FALSE;
opt_fork_exec_failure = FALSE;
@@ -218,7 +282,12 @@ int main(int argc, char **argv)
boost::scoped_ptr<Test> testptr;
boost::shared_ptr<SyncEvo::ForkExecParent> forkexec =
SyncEvo::ForkExecParent::create(opt_fork_exec_failure ? "/bin/false" : argv[0]);
- forkexec->m_onConnect.connect(boost::bind(onChildConnect, _1, boost::ref(testptr)));
+ if (opt_kill) {
+ forkexec->addEnvVar("DBUS_CLIENT_SERVER_KILL", opt_kill);
+ }
+ forkexec->m_onConnect.connect(g_strcmp0(opt_kill, "child") ?
+ boost::bind(onChildConnect, _1, boost::ref(testptr)) :
+ boost::bind(onChildConnectKill, _1, boost::ref(testptr)));
forkexec->m_onQuit.connect(onQuit);
forkexec->m_onFailure.connect(boost::bind(onFailure, _2));
forkexec->start();
@@ -240,7 +309,9 @@ int main(int argc, char **argv)
boost::shared_ptr<SyncEvo::ForkExecChild> forkexec =
SyncEvo::ForkExecChild::create();
- forkexec->m_onConnect.connect(callServer);
+ forkexec->m_onConnect.connect(!g_strcmp0(getenv("DBUS_CLIENT_SERVER_KILL"), "child") ? calledByServer :
+ !g_strcmp0(getenv("DBUS_CLIENT_SERVER_KILL"), "server") ? killServer :
+ callServer);
forkexec->m_onFailure.connect(boost::bind(onFailure, _2));
forkexec->connect();
g_main_loop_run(loop.get());