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 static pid_t __daemon_pid = 0;
46 #define TEST_PARENT_PORT "test-parent-port"
47 #define TEST_PARENT_TRUSTED_PORT "test-parent-trusted-port"
48 #define TEST_CHILD_PORT "test-child-port"
49 #define TEST_CHILD_TRUSTED_PORT "test-child-trusted-port"
51 #define TEST_CASE(case) \
53 if (case() != true) { \
54 cerr << #case << ": FAIL\n"; \
57 else cout << #case << ": SUCCESS\n"; \
61 #define test_assert(expr, msg) \
63 if ((expr) == false) {\
64 cerr << __FUNCTION__ << "-" << __LINE__ << ": assert(" << #expr << ") : " << msg << "\n"; \
70 std::string toString (int a)
74 snprintf (str, 255, "%d", a);
76 return std::string(str);
79 std::string toString (messageport_error_e err)
81 return toString ((int)err);
89 static void onMessage (int portId, const char *remoteAppId, const char *remotePort, bool isTrusted, bundle *message);
92 typedef void (*MessageHandler)(LocalPort *port, bundle *message, RemotePort *remotePort, void *userdata);
94 LocalPort (const std::string &name, bool is_trusted, LocalPort::MessageHandler message_handler, void *userdata)
95 : m_name (name), m_trusted(is_trusted), m_msgCb(message_handler), m_cbData(userdata) {
97 cachedPorts[m_portId] = this;
102 cachedPorts.erase(m_portId);
107 res = m_trusted ? messageport_register_trusted_local_port (m_name.c_str(), onMessage)
108 : messageport_register_local_port (m_name.c_str(), onMessage);
111 cerr << "Failed to register port '"<< m_name << "'";
112 m_err = (messageport_error_e) res;
121 bool SendMessage (const std::string &app_id, const std::string &port_name, bool is_trusted, bundle *data)
123 m_err = is_trusted ? messageport_send_bidirectional_trusted_message (m_portId, app_id.c_str(), port_name.c_str(), data)
124 : messageport_send_bidirectional_message (m_portId, app_id.c_str(), port_name.c_str(), data);
126 cerr << "Fail to send bidirectional message to '" << app_id << "/" << port_name << ":" << m_err ;
133 const std::string& name () const {
137 bool isTrusted () const {
145 messageport_error_e lastError () {
146 return (messageport_error_e) m_err;
154 LocalPort::MessageHandler m_msgCb;
157 static std::map<int,LocalPort*> cachedPorts ;
159 std::map<int,LocalPort*> LocalPort::cachedPorts ;
163 RemotePort (const string &appId, const string &portName, bool isTrusted)
164 :m_appId(appId), m_portName(portName), m_isTrusted (isTrusted), m_isValid (false)
166 m_err = isTrusted ? messageport_check_trusted_remote_port (appId.c_str(), portName.c_str(), &m_isValid)
167 : messageport_check_remote_port (appId.c_str(), portName.c_str(), &m_isValid);
168 if (m_err != MESSAGEPORT_ERROR_NONE) {
169 cerr << std::string ("Fail to find remote port '") + appId + "', '" + portName + "': error : " + toString (m_err) + "\n";
175 bool sendMessage (bundle *b) {
177 m_err = m_isTrusted ? messageport_send_trusted_message (m_appId.c_str(), m_portName.c_str(), b)
178 : messageport_send_message (m_appId.c_str(), m_portName.c_str(), b);
180 return m_err == MESSAGEPORT_ERROR_NONE;
183 bool sendBidirectionalMessage (bundle *b, const LocalPort &port) {
184 m_err = m_isTrusted ? messageport_send_bidirectional_trusted_message (port.id(), m_appId.c_str(), m_portName.c_str(), b)
185 : messageport_send_bidirectional_message (port.id(), m_appId.c_str(), m_portName.c_str(), b);
186 return m_err == MESSAGEPORT_ERROR_NONE;
189 bool isValid () const {
193 messageport_error_e lastError () const {
197 const string & appId () const {
201 const string & portName () const {
205 bool isTrusted () const {
212 messageport_error_e m_err;
216 void LocalPort::onMessage (int portId, const char *remoteAppId, const char *portName, bool isTrusted, bundle *message)
218 LocalPort * port = LocalPort::cachedPorts[portId];
220 RemotePort *remotePort = NULL;
221 if (remoteAppId && portName)
222 remotePort = new RemotePort (string(remoteAppId), string(portName), isTrusted);
223 port->m_msgCb (port, message, remotePort, port->m_cbData);
227 else cerr <<"No cached Port found\n" ;
231 _onParentGotMessage (LocalPort *port, bundle *data, RemotePort *remotePort, void *userdata)
233 /* Write acknoledgement */
235 int len = ok.length() + 1;
236 if ( write (__pipe[1], ok.c_str(), len) < len) {
237 cerr << "WRITE failed" ;
241 bundle *reply = bundle_create ();
242 bundle_add (reply, "Results", "GOT_IT");
243 remotePort->sendMessage (reply);
250 _onChildGotMessage (LocalPort *port, bundle *data, RemotePort *remotePort, void *userdata)
252 AsyncTestData *test_data = (AsyncTestData *)userdata;
254 int len = ack.length () + 1;
255 /* Write acknoledgement */
256 if (write (__pipe[1], ack.c_str(), len) < len) {
257 cerr << "WRITE to pipe failed";
261 test_data->result = TRUE;
262 g_main_loop_quit (test_data->m_loop);
268 test_register_local_port ()
270 static LocalPort *port = new LocalPort(TEST_PARENT_PORT, false, _onParentGotMessage, NULL);
272 test_assert (port->Register() == true, "Failed to register port : " + toString(port->lastError ()));
278 test_register_trusted_local_port ()
280 static LocalPort *trused_port = new LocalPort(TEST_PARENT_TRUSTED_PORT, true, _onParentGotMessage, NULL);
282 test_assert (trused_port->Register() == true, "Failed to regiser trusted port :" + toString (trused_port->lastError ()));
288 test_get_local_port_name()
290 LocalPort port("dummy_port", false, _onParentGotMessage, NULL);
291 test_assert (port.Register() == true, "Failed to regiser trusted port :" + toString (port.lastError ()));
292 test_assert (port.name() == "dummy_port", "Wrong port name : " + port.name());
294 LocalPort trusted_port("dummy_trusted_port", true, _onParentGotMessage, NULL);
295 test_assert (trusted_port.Register() == true, "Failed to regiser trusted port :" + toString (trusted_port.lastError ()));
296 test_assert (trusted_port.name() == "dummy_trusted_port", "Wrong port name : " + trusted_port.name());
302 test_check_trusted_local_port ()
304 LocalPort port("dummy_port", false, _onParentGotMessage, NULL);
305 test_assert (port.Register() == true, "Failed to regiser trusted port :" + toString (port.lastError ()));
306 test_assert (port.isTrusted() == false, "Wrong port type : " + port.isTrusted());
308 LocalPort trusted_port("dummy_trusted_port", true, _onParentGotMessage, NULL);
309 test_assert (trusted_port.Register() == true, "Failed to regiser trusted port :" + toString (trusted_port.lastError ()));
310 test_assert (trusted_port.isTrusted() == true, "Wrong port type : " + trusted_port.isTrusted());
316 test_check_remote_port ()
318 RemotePort p(toString(getppid()), TEST_PARENT_PORT, false);
320 test_assert (p.isValid() == true, "Could not get remote port : " + toString(p.lastError()));
326 test_check_remote_trusted_port ()
328 RemotePort p(toString(getppid()), TEST_PARENT_TRUSTED_PORT, true);
330 test_assert (p.isValid() == true, "Could not get remote trusted port : " + toString(p.lastError()));
339 bundle *b = bundle_create ();
340 bundle_add (b, "Name", "Amarnath");
341 bundle_add (b, "Email", "amarnath.valluri@intel.com");
343 RemotePort port (toString (getppid()), TEST_PARENT_PORT, false);
345 res = port.sendMessage (b);
347 test_assert (res == true, std::string("Fail to send message to port '") +
348 TEST_PARENT_PORT + "' at app_id : '" + toString(getppid()) +
349 "', error : " + toString (port.lastError()));
353 test_assert ((read (__pipe[0], &result, sizeof(result)) > 0), "Parent did not received the message");
354 test_assert ((g_strcmp0 (result, "OK") == 0), "Parent did not received the message");
360 test_send_trusted_message ()
363 bundle *b = bundle_create ();
364 bundle_add (b, "Name", "Amarnath");
365 bundle_add (b, "Email", "amarnath.valluri@intel.com");
367 RemotePort port (toString (getppid()), TEST_PARENT_TRUSTED_PORT, true);
369 res = port.sendMessage (b);
371 test_assert (res == true, std::string("Fail to send trusted message to port '") +
372 TEST_PARENT_TRUSTED_PORT + "' at app_id : '" + toString(getppid()) +
373 "', error : " + toString (port.lastError()));
376 test_assert ((read (__pipe[0], &result, sizeof(result)) > 0), "Parent did not received the message");
377 test_assert ((g_strcmp0 (result, "OK") == 0), "Parent did not received the message");
383 _update_test_result (gpointer userdata)
385 AsyncTestData *test_data = (AsyncTestData *)userdata;
386 test_data->result = false;
387 g_main_loop_quit (test_data->m_loop);
391 test_send_bidirectional_message ()
395 AsyncTestData *test_data = new AsyncTestData();
396 test_data->m_loop = g_main_loop_new (NULL, FALSE);
398 LocalPort localPort(TEST_CHILD_PORT, false, _onChildGotMessage, test_data);
400 test_assert (localPort.Register() == true, "Failed to register local port: Error: " + toString(localPort.lastError()));
402 RemotePort remotePort (toString (getppid()), TEST_PARENT_PORT, false);
404 test_assert (remotePort.isValid() == true, "Invalid remote port, Erorr: " + toString(remotePort.lastError()));
406 b = bundle_create ();
407 bundle_add (b, "Name", "Amarnath");
408 bundle_add (b, "Email", "amarnath.valluri@intel.com");
409 res = remotePort.sendBidirectionalMessage (b, localPort);
412 test_assert (res == true, "Fail to send bidirectional message , Error : " + toString(remotePort.lastError()));
415 test_assert ((read (__pipe[0], &result, sizeof(result)) > 0), "Parent did not received the message");
416 test_assert ((g_strcmp0 (result, "OK") == 0), "Parent did not received the message");
418 g_timeout_add_seconds (5, _update_test_result, test_data);
420 g_main_loop_run (test_data->m_loop);
421 bool child_got_message = test_data->result;
423 g_main_loop_unref (test_data->m_loop);
426 test_assert (child_got_message == true, "Timeout, Child did not recieved reply");
432 test_send_bidirectional_trusted_message()
436 AsyncTestData *test_data = new AsyncTestData();
437 test_data->m_loop = g_main_loop_new (NULL, FALSE);
439 LocalPort localPort(TEST_CHILD_TRUSTED_PORT, true, _onChildGotMessage, test_data);
440 test_assert (localPort.Register() == true, "Failed to register trusted local port: Error: " + toString(localPort.lastError()));
442 RemotePort remotePort (toString (getppid()), TEST_PARENT_TRUSTED_PORT, true);
443 test_assert (remotePort.isValid() == true, "Invalid remote port, Erorr: " + toString(remotePort.lastError()));
445 b = bundle_create ();
446 bundle_add (b, "Name", "Amarnath");
447 bundle_add (b, "Email", "amarnath.valluri@intel.com");
448 res = remotePort.sendBidirectionalMessage (b, localPort);
451 test_assert (res == true, "Fail to send bidirectional message , Error : " + toString(remotePort.lastError()));
454 test_assert ((read (__pipe[0], &result, sizeof(result)) > 0), "Parent did not received the message");
455 test_assert ((g_strcmp0 (result, "OK") == 0), "Parent did not received the message");
457 g_timeout_add_seconds (5, _update_test_result, test_data);
459 g_main_loop_run (test_data->m_loop);
460 bool child_got_message = test_data->result;
462 g_main_loop_unref (test_data->m_loop);
465 test_assert (child_got_message == true, "Timeout, Child did not recieved reply");
471 _on_term (gpointer userdata)
473 g_main_loop_quit ((GMainLoop *)userdata);
481 #ifdef USE_SESSION_BUS
482 GIOChannel *channel = NULL;
483 gchar *bus_address = NULL;
488 const gchar *dbus_monitor = NULL;
489 GError *error = NULL;
491 argv[0] = const_cast<gchar*>("dbus-daemon");
492 argv[1] = const_cast<gchar*>("--config-file="TEST_DBUS_DAEMON_CONF_FILE);
493 argv[2] = const_cast<gchar*>("--print-address=<<fd>>");
496 if (pipe(pipe_fd)== -1) {
497 GSpawnFlags flags = G_SPAWN_SEARCH_PATH;
498 cerr << "Failed to open temp file :" << error->message;
499 argv[2] = g_strdup_printf ("--print-address=1");
500 g_spawn_async_with_pipes (NULL, argv, NULL, flags, NULL, NULL, &__daemon_pid, NULL, NULL, &tmp_fd, &error);
502 GSpawnFlags flags = (GSpawnFlags)(G_SPAWN_SEARCH_PATH | G_SPAWN_LEAVE_DESCRIPTORS_OPEN);
504 argv[2] = g_strdup_printf ("--print-address=%d", pipe_fd[1]);
505 g_spawn_async (NULL, argv, NULL, flags, NULL, NULL, &__daemon_pid, &error);
508 test_assert (error == NULL, std::string("Failed to span daemon : ") + error->message);
509 test_assert (__daemon_pid != 0, "Failed to get daemon pid");
510 sleep (5); /* 5 seconds */
512 channel = g_io_channel_unix_new (tmp_fd);
513 g_io_channel_read_line (channel, &bus_address, NULL, &len, &error);
514 test_assert (error == NULL, "Failed to daemon address : " << error->message);
515 g_io_channel_unref (channel);
517 if (pipe_fd[0]) close (pipe_fd[0]);
518 if (pipe_fd[1]) close (pipe_fd[1]);
520 if (bus_address) bus_address[len] = '\0';
521 test_assert (bus_address != NULL && bus_address[0] != 0, "Failed to get dbus-daemon address");
523 cout << "Dbus daemon start at : " << bus_address << "\n";
525 setenv("DBUS_SESSION_BUS_ADDRESS", bus_address, TRUE);
527 g_free (bus_address);
528 #endif /* USE_SESSION_BUS */
536 #ifdef USE_SESSION_BUS
537 if (__daemon_pid) kill (__daemon_pid, SIGTERM);
538 #endif /* USE_SESSION_BUS */
541 int main (int argc, const char *argv[])
545 if (test_setup () != true) {
546 cerr << "Test setup failur!!!\n";
550 if (pipe(__pipe) < 0) {
551 cerr << "Failed to create pipe. Cannot run tests!!!" ;
555 if ( child_pid < 0) {
556 cerr << "Failed to fork process, Cannot run tests!!!";
559 else if (child_pid != 0)
562 GMainLoop *m_loop = g_main_loop_new (NULL, FALSE);
564 TEST_CASE (test_register_local_port);
565 TEST_CASE (test_register_trusted_local_port);
566 TEST_CASE(test_get_local_port_name);
567 TEST_CASE(test_check_trusted_local_port);
569 g_unix_signal_add (SIGTERM, _on_term, m_loop);
571 g_main_loop_run (m_loop);
572 g_main_loop_unref (m_loop);
577 TEST_CASE(test_check_remote_port);
578 TEST_CASE(test_check_remote_trusted_port);
579 TEST_CASE(test_send_message);
580 TEST_CASE(test_send_bidirectional_message);
581 TEST_CASE(test_send_trusted_message);
582 TEST_CASE(test_send_bidirectional_trusted_message);
584 kill (getppid(), SIGTERM);