1 /* vi: set et sw=4 ts=4 cino=t0,(0: */
2 /* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
4 * This file is part of message-port.
6 * Copyright (C) 2013 Intel Corporation.
8 * Contact: Amarnath Valluri <amarnath.valluri@linux.intel.com>
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Lesser General Public
12 * License as published by the Free Software Foundation; either
13 * version 2.1 of the License, or (at your option) any later version.
15 * This library is distributed in the hope that it will be useful, but
16 * WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Lesser General Public License for more details.
20 * You should have received a copy of the GNU Lesser General Public
21 * License along with this library; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
27 #include <message-port.h>
28 #include <bundle.h> // bundle
29 #include <string> // std::string
30 #include <map> // std::map
31 #include <iostream> // cout, cerr
32 #include <unistd.h> // pipe ()
35 #include <glib-unix.h> // g_unix_signal_add()
39 struct AsyncTestData {
44 #ifdef USE_SESSION_BUS
45 static pid_t __daemon_pid = 0;
46 #endif // USE_SESSION_BUS
48 #define TEST_PARENT_PORT "test-parent-port"
49 #define TEST_PARENT_TRUSTED_PORT "test-parent-trusted-port"
50 #define TEST_CHILD_PORT "test-child-port"
51 #define TEST_CHILD_TRUSTED_PORT "test-child-trusted-port"
53 #define TEST_CASE(case) \
55 if (case() != true) { \
56 cerr << #case << ": FAIL\n"; \
59 else cout << #case << ": SUCCESS\n"; \
63 #define test_assert(expr, msg) \
65 if ((expr) == false) {\
66 cerr << __FUNCTION__ << "-" << __LINE__ << ": assert(" << #expr << ") : " << msg << "\n"; \
72 std::string toString (int a)
76 snprintf (str, 255, "%d", a);
78 return std::string(str);
81 std::string toString (messageport_error_e err)
83 return toString ((int)err);
91 static void onMessage (int portId, const char *remoteAppId, const char *remotePort, bool isTrusted, bundle *message);
94 typedef void (*MessageHandler)(LocalPort *port, bundle *message, RemotePort *remotePort, void *userdata);
96 LocalPort (const std::string &name, bool is_trusted, LocalPort::MessageHandler message_handler, void *userdata)
97 : m_name (name), m_trusted(is_trusted), m_msgCb(message_handler), m_cbData(userdata) {
99 cachedPorts[m_portId] = this;
104 cachedPorts.erase(m_portId);
109 res = m_trusted ? messageport_register_trusted_local_port (m_name.c_str(), onMessage)
110 : messageport_register_local_port (m_name.c_str(), onMessage);
113 cerr << "Failed to register port '"<< m_name << "'";
114 m_err = (messageport_error_e) res;
123 bool SendMessage (const std::string &app_id, const std::string &port_name, bool is_trusted, bundle *data)
125 m_err = is_trusted ? messageport_send_bidirectional_trusted_message (m_portId, app_id.c_str(), port_name.c_str(), data)
126 : messageport_send_bidirectional_message (m_portId, app_id.c_str(), port_name.c_str(), data);
128 cerr << "Fail to send bidirectional message to '" << app_id << "/" << port_name << ":" << m_err ;
135 const std::string& name () const {
139 bool isTrusted () const {
147 messageport_error_e lastError () {
148 return (messageport_error_e) m_err;
156 LocalPort::MessageHandler m_msgCb;
159 static std::map<int,LocalPort*> cachedPorts ;
161 std::map<int,LocalPort*> LocalPort::cachedPorts ;
165 RemotePort (const string &appId, const string &portName, bool isTrusted)
166 :m_appId(appId), m_portName(portName), m_isTrusted (isTrusted), m_isValid (false)
168 m_err = isTrusted ? messageport_check_trusted_remote_port (appId.c_str(), portName.c_str(), &m_isValid)
169 : messageport_check_remote_port (appId.c_str(), portName.c_str(), &m_isValid);
170 if (m_err != MESSAGEPORT_ERROR_NONE) {
171 cerr << std::string ("Fail to find remote port '") + appId + "', '" + portName + "': error : " + toString (m_err) + "\n";
177 bool sendMessage (bundle *b) {
179 m_err = m_isTrusted ? messageport_send_trusted_message (m_appId.c_str(), m_portName.c_str(), b)
180 : messageport_send_message (m_appId.c_str(), m_portName.c_str(), b);
182 return m_err == MESSAGEPORT_ERROR_NONE;
185 bool sendBidirectionalMessage (bundle *b, const LocalPort &port) {
186 m_err = m_isTrusted ? messageport_send_bidirectional_trusted_message (port.id(), m_appId.c_str(), m_portName.c_str(), b)
187 : messageport_send_bidirectional_message (port.id(), m_appId.c_str(), m_portName.c_str(), b);
188 return m_err == MESSAGEPORT_ERROR_NONE;
191 bool isValid () const {
195 messageport_error_e lastError () const {
199 const string & appId () const {
203 const string & portName () const {
207 bool isTrusted () const {
214 messageport_error_e m_err;
218 void LocalPort::onMessage (int portId, const char *remoteAppId, const char *portName, bool isTrusted, bundle *message)
220 LocalPort * port = LocalPort::cachedPorts[portId];
222 RemotePort *remotePort = NULL;
223 if (remoteAppId && portName)
224 remotePort = new RemotePort (string(remoteAppId), string(portName), isTrusted);
225 port->m_msgCb (port, message, remotePort, port->m_cbData);
229 else cerr <<"No cached Port found\n" ;
233 _onParentGotMessage (LocalPort *port, bundle *data, RemotePort *remotePort, void *userdata)
235 /* Write acknoledgement */
237 int len = ok.length() + 1;
238 if ( write (__pipe[1], ok.c_str(), len) < len) {
239 cerr << "WRITE failed" ;
243 bundle *reply = bundle_create ();
244 bundle_add (reply, "Results", "GOT_IT");
245 remotePort->sendMessage (reply);
252 _onChildGotMessage (LocalPort *port, bundle *data, RemotePort *remotePort, void *userdata)
254 AsyncTestData *test_data = (AsyncTestData *)userdata;
256 int len = ack.length () + 1;
257 /* Write acknoledgement */
258 if (write (__pipe[1], ack.c_str(), len) < len) {
259 cerr << "WRITE to pipe failed";
263 test_data->result = TRUE;
264 g_main_loop_quit (test_data->m_loop);
270 test_register_local_port ()
272 static LocalPort *port = new LocalPort(TEST_PARENT_PORT, false, _onParentGotMessage, NULL);
274 test_assert (port->Register() == true, "Failed to register port : " + toString(port->lastError ()));
280 test_register_trusted_local_port ()
282 static LocalPort *trused_port = new LocalPort(TEST_PARENT_TRUSTED_PORT, true, _onParentGotMessage, NULL);
284 test_assert (trused_port->Register() == true, "Failed to regiser trusted port :" + toString (trused_port->lastError ()));
290 test_get_local_port_name()
292 LocalPort port("dummy_port", false, _onParentGotMessage, NULL);
293 test_assert (port.Register() == true, "Failed to regiser trusted port :" + toString (port.lastError ()));
294 test_assert (port.name() == "dummy_port", "Wrong port name : " + port.name());
296 LocalPort trusted_port("dummy_trusted_port", true, _onParentGotMessage, NULL);
297 test_assert (trusted_port.Register() == true, "Failed to regiser trusted port :" + toString (trusted_port.lastError ()));
298 test_assert (trusted_port.name() == "dummy_trusted_port", "Wrong port name : " + trusted_port.name());
304 test_check_trusted_local_port ()
306 LocalPort port("dummy_port", false, _onParentGotMessage, NULL);
307 test_assert (port.Register() == true, "Failed to regiser trusted port :" + toString (port.lastError ()));
308 test_assert (port.isTrusted() == false, "Wrong port type : " + port.isTrusted());
310 LocalPort trusted_port("dummy_trusted_port", true, _onParentGotMessage, NULL);
311 test_assert (trusted_port.Register() == true, "Failed to regiser trusted port :" + toString (trusted_port.lastError ()));
312 test_assert (trusted_port.isTrusted() == true, "Wrong port type : " + trusted_port.isTrusted());
318 test_check_remote_port ()
320 RemotePort p(toString(getppid()), TEST_PARENT_PORT, false);
322 test_assert (p.isValid() == true, "Could not get remote port : " + toString(p.lastError()));
328 test_check_remote_trusted_port ()
330 RemotePort p(toString(getppid()), TEST_PARENT_TRUSTED_PORT, true);
332 test_assert (p.isValid() == true, "Could not get remote trusted port : " + toString(p.lastError()));
341 bundle *b = bundle_create ();
342 bundle_add (b, "Name", "Amarnath");
343 bundle_add (b, "Email", "amarnath.valluri@intel.com");
345 RemotePort port (toString (getppid()), TEST_PARENT_PORT, false);
347 res = port.sendMessage (b);
349 test_assert (res == true, std::string("Fail to send message to port '") +
350 TEST_PARENT_PORT + "' at app_id : '" + toString(getppid()) +
351 "', error : " + toString (port.lastError()));
355 test_assert ((read (__pipe[0], &result, sizeof(result)) > 0), "Parent did not received the message");
356 test_assert ((g_strcmp0 (result, "OK") == 0), "Parent did not received the message");
362 test_send_trusted_message ()
365 bundle *b = bundle_create ();
366 bundle_add (b, "Name", "Amarnath");
367 bundle_add (b, "Email", "amarnath.valluri@intel.com");
369 RemotePort port (toString (getppid()), TEST_PARENT_TRUSTED_PORT, true);
371 res = port.sendMessage (b);
373 test_assert (res == true, std::string("Fail to send trusted message to port '") +
374 TEST_PARENT_TRUSTED_PORT + "' at app_id : '" + toString(getppid()) +
375 "', error : " + toString (port.lastError()));
378 test_assert ((read (__pipe[0], &result, sizeof(result)) > 0), "Parent did not received the message");
379 test_assert ((g_strcmp0 (result, "OK") == 0), "Parent did not received the message");
385 _update_test_result (gpointer userdata)
387 AsyncTestData *test_data = (AsyncTestData *)userdata;
388 test_data->result = false;
389 g_main_loop_quit (test_data->m_loop);
395 test_send_bidirectional_message ()
399 AsyncTestData *test_data = new AsyncTestData();
400 test_data->m_loop = g_main_loop_new (NULL, FALSE);
402 LocalPort localPort(TEST_CHILD_PORT, false, _onChildGotMessage, test_data);
404 test_assert (localPort.Register() == true, "Failed to register local port: Error: " + toString(localPort.lastError()));
406 RemotePort remotePort (toString (getppid()), TEST_PARENT_PORT, false);
408 test_assert (remotePort.isValid() == true, "Invalid remote port, Erorr: " + toString(remotePort.lastError()));
410 b = bundle_create ();
411 bundle_add (b, "Name", "Amarnath");
412 bundle_add (b, "Email", "amarnath.valluri@intel.com");
413 res = remotePort.sendBidirectionalMessage (b, localPort);
416 test_assert (res == true, "Fail to send bidirectional message , Error : " + toString(remotePort.lastError()));
419 test_assert ((read (__pipe[0], &result, sizeof(result)) > 0), "Parent did not received the message");
420 test_assert ((g_strcmp0 (result, "OK") == 0), "Parent did not received the message");
422 g_timeout_add_seconds (5, _update_test_result, test_data);
424 g_main_loop_run (test_data->m_loop);
425 bool child_got_message = test_data->result;
427 g_main_loop_unref (test_data->m_loop);
430 test_assert (child_got_message == true, "Timeout, Child did not recieved reply");
436 test_send_bidirectional_trusted_message()
440 AsyncTestData *test_data = new AsyncTestData();
441 test_data->m_loop = g_main_loop_new (NULL, FALSE);
443 LocalPort localPort(TEST_CHILD_TRUSTED_PORT, true, _onChildGotMessage, test_data);
444 test_assert (localPort.Register() == true, "Failed to register trusted local port: Error: " + toString(localPort.lastError()));
446 RemotePort remotePort (toString (getppid()), TEST_PARENT_TRUSTED_PORT, true);
447 test_assert (remotePort.isValid() == true, "Invalid remote port, Erorr: " + toString(remotePort.lastError()));
449 b = bundle_create ();
450 bundle_add (b, "Name", "Amarnath");
451 bundle_add (b, "Email", "amarnath.valluri@intel.com");
452 res = remotePort.sendBidirectionalMessage (b, localPort);
455 test_assert (res == true, "Fail to send bidirectional message , Error : " + toString(remotePort.lastError()));
458 test_assert ((read (__pipe[0], &result, sizeof(result)) > 0), "Parent did not received the message");
459 test_assert ((g_strcmp0 (result, "OK") == 0), "Parent did not received the message");
461 g_timeout_add_seconds (5, _update_test_result, test_data);
463 g_main_loop_run (test_data->m_loop);
464 bool child_got_message = test_data->result;
466 g_main_loop_unref (test_data->m_loop);
469 test_assert (child_got_message == true, "Timeout, Child did not recieved reply");
475 _on_term (gpointer userdata)
477 g_main_loop_quit ((GMainLoop *)userdata);
485 #ifdef USE_SESSION_BUS
486 GIOChannel *channel = NULL;
487 gchar *bus_address = NULL;
492 const gchar *dbus_monitor = NULL;
493 GError *error = NULL;
495 argv[0] = const_cast<gchar*>("dbus-daemon");
496 argv[1] = const_cast<gchar*>("--config-file="TEST_DBUS_DAEMON_CONF_FILE);
497 argv[2] = const_cast<gchar*>("--print-address=<<fd>>");
500 if (pipe(pipe_fd)== -1) {
501 GSpawnFlags flags = G_SPAWN_SEARCH_PATH;
502 cerr << "Failed to open temp file :" << error->message;
503 argv[2] = g_strdup_printf ("--print-address=1");
504 g_spawn_async_with_pipes (NULL, argv, NULL, flags, NULL, NULL, &__daemon_pid, NULL, NULL, &tmp_fd, &error);
506 GSpawnFlags flags = (GSpawnFlags)(G_SPAWN_SEARCH_PATH | G_SPAWN_LEAVE_DESCRIPTORS_OPEN);
508 argv[2] = g_strdup_printf ("--print-address=%d", pipe_fd[1]);
509 g_spawn_async (NULL, argv, NULL, flags, NULL, NULL, &__daemon_pid, &error);
512 test_assert (error == NULL, std::string("Failed to span daemon : ") + error->message);
513 test_assert (__daemon_pid != 0, "Failed to get daemon pid");
514 sleep (5); /* 5 seconds */
516 channel = g_io_channel_unix_new (tmp_fd);
517 g_io_channel_read_line (channel, &bus_address, NULL, &len, &error);
518 test_assert (error == NULL, "Failed to daemon address : " << error->message);
519 g_io_channel_unref (channel);
521 if (pipe_fd[0]) close (pipe_fd[0]);
522 if (pipe_fd[1]) close (pipe_fd[1]);
524 if (bus_address) bus_address[len] = '\0';
525 test_assert (bus_address != NULL && bus_address[0] != 0, "Failed to get dbus-daemon address");
527 cout << "Dbus daemon start at : " << bus_address << "\n";
529 setenv("DBUS_SESSION_BUS_ADDRESS", bus_address, TRUE);
531 g_free (bus_address);
532 #endif /* USE_SESSION_BUS */
540 #ifdef USE_SESSION_BUS
541 if (__daemon_pid) kill (__daemon_pid, SIGTERM);
542 #endif /* USE_SESSION_BUS */
545 int main (int argc, const char *argv[])
549 if (test_setup () != true) {
550 cerr << "Test setup failur!!!\n";
554 if (pipe(__pipe) < 0) {
555 cerr << "Failed to create pipe. Cannot run tests!!!" ;
559 if ( child_pid < 0) {
560 cerr << "Failed to fork process, Cannot run tests!!!";
563 else if (child_pid != 0)
566 GMainLoop *m_loop = g_main_loop_new (NULL, FALSE);
568 TEST_CASE (test_register_local_port);
569 TEST_CASE (test_register_trusted_local_port);
570 TEST_CASE(test_get_local_port_name);
571 TEST_CASE(test_check_trusted_local_port);
573 g_unix_signal_add (SIGTERM, _on_term, m_loop);
575 g_main_loop_run (m_loop);
576 g_main_loop_unref (m_loop);
581 TEST_CASE(test_check_remote_port);
582 TEST_CASE(test_check_remote_trusted_port);
583 TEST_CASE(test_send_message);
584 TEST_CASE(test_send_bidirectional_message);
585 TEST_CASE(test_send_trusted_message);
586 TEST_CASE(test_send_bidirectional_trusted_message);
588 kill (getppid(), SIGTERM);