Change SmackExecLabel to SmackProcessLabel
[profile/ivi/message-port.git] / tests / test-app.cpp
1 /* vi: set et sw=4 ts=4 cino=t0,(0: */
2 /* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 /*
4  * This file is part of message-port.
5  *
6  * Copyright (C) 2013 Intel Corporation.
7  *
8  * Contact: Amarnath Valluri <amarnath.valluri@linux.intel.com>
9  *
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.
14  *
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.
19  *
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
23  * 02110-1301 USA
24  */
25
26 #include "config.h"
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 ()
33 #include <stdio.h>        // 
34 #include <glib.h>
35 #include <glib-unix.h>    // g_unix_signal_add()
36
37 using namespace std;
38
39 struct AsyncTestData {
40     GMainLoop *m_loop;
41     bool result;
42 }; 
43 static int __pipe[2];
44 #ifdef USE_SESSION_BUS
45 static pid_t __daemon_pid = 0;
46 #endif // USE_SESSION_BUS
47
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"
52
53 #define TEST_CASE(case) \
54     do { \
55         if (case() != true) { \
56             cerr << #case << ": FAIL\n"; \
57             return -1; \
58         } \
59         else cout << #case << ": SUCCESS\n"; \
60     }while (0)
61
62
63 #define test_assert(expr, msg) \
64     do { \
65         if ((expr) == false) {\
66             cerr << __FUNCTION__ << "-" << __LINE__ << ": assert(" << #expr << ") : " << msg << "\n"; \
67             return false; \
68         } \
69     } while(0);
70
71
72 std::string toString (int a)
73 {
74     char str[256];
75
76     snprintf (str, 255, "%d", a);
77
78     return std::string(str);
79 }
80
81 std::string toString (messageport_error_e err)
82 {
83     return toString ((int)err);
84 }
85
86 class RemotePort;
87
88 class LocalPort {
89
90 protected:
91     static void onMessage (int portId, const char *remoteAppId, const char *remotePort, bool isTrusted, bundle *message);
92
93 public:
94     typedef void (*MessageHandler)(LocalPort *port, bundle *message, RemotePort *remotePort, void *userdata);
95
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) {
98         if (Register ()) {
99             cachedPorts[m_portId] = this;
100         }
101     }
102
103     ~LocalPort() { 
104         cachedPorts.erase(m_portId);
105     }
106
107     bool Register () {
108         int res ;
109         res = m_trusted ? messageport_register_trusted_local_port (m_name.c_str(), onMessage)
110                         : messageport_register_local_port (m_name.c_str(), onMessage);
111
112         if (res < 0) {
113             cerr << "Failed to register port '"<< m_name << "'";
114             m_err = (messageport_error_e) res;
115             return false;
116         }
117         
118         m_portId = res;
119
120         return true;
121     }
122
123     bool SendMessage (const std::string &app_id, const std::string &port_name, bool is_trusted, bundle *data)
124     {
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);
127         if (m_err < 0) {
128             cerr << "Fail to send bidirectional message to '" << app_id << "/" << port_name << ":" << m_err ;
129             return false;
130         }
131
132         return true;
133     }
134
135     const std::string& name () const {
136         return m_name;
137     }
138
139     bool isTrusted () const {
140         return m_trusted;
141     }
142
143     int id () const {
144         return m_portId;
145     }
146
147     messageport_error_e lastError () {
148         return (messageport_error_e) m_err;
149     }
150
151 private:
152     string m_name;
153     bool   m_trusted;
154     int    m_portId;
155     int    m_err;
156     LocalPort::MessageHandler m_msgCb;
157     void  *m_cbData;
158
159     static std::map<int,LocalPort*> cachedPorts ;
160 };
161 std::map<int,LocalPort*> LocalPort::cachedPorts ;
162
163 class RemotePort {
164 public:
165     RemotePort (const string &appId, const string &portName, bool isTrusted)
166         :m_appId(appId), m_portName(portName), m_isTrusted (isTrusted), m_isValid (false)
167     {
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";
172         }
173     }
174
175     ~RemotePort () { }
176
177     bool sendMessage (bundle *b) {
178         
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);
181
182         return m_err == MESSAGEPORT_ERROR_NONE;
183     }
184
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;
189     }
190
191     bool isValid () const {
192         return m_isValid;
193     }
194
195     messageport_error_e lastError () const {
196         return m_err;
197     }
198
199     const string & appId () const {
200         return m_appId;
201     }
202
203     const string & portName () const {
204         return m_portName;
205     }
206
207     bool isTrusted () const {
208         return m_isTrusted;
209     }
210 private:
211     string m_appId;
212     string m_portName;
213     bool   m_isTrusted;
214     messageport_error_e m_err;
215     bool   m_isValid;
216 };
217
218 void LocalPort::onMessage (int portId, const char *remoteAppId, const char *portName, bool isTrusted, bundle *message)
219 {
220     LocalPort * port = LocalPort::cachedPorts[portId];
221     if (port) {
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);
226
227         delete remotePort;
228     }
229     else cerr <<"No cached Port found\n" ;
230 }
231
232 static void
233 _onParentGotMessage (LocalPort *port, bundle *data, RemotePort *remotePort, void *userdata)
234 {
235     /* Write acknoledgement */
236     string ok("OK");
237     int len = ok.length() + 1;
238     if ( write (__pipe[1], ok.c_str(), len) < len) {
239         cerr << "WRITE failed" ;
240     }
241
242     if (remotePort) {
243         bundle *reply = bundle_create ();
244         bundle_add (reply, "Results", "GOT_IT");
245         remotePort->sendMessage (reply);
246
247         bundle_free (reply);
248     }
249 }
250
251 static void
252 _onChildGotMessage (LocalPort *port, bundle *data, RemotePort *remotePort, void *userdata)
253 {
254     AsyncTestData *test_data = (AsyncTestData *)userdata;
255     string ack("OK");
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";
260     }
261
262     if (test_data) {
263         test_data->result = TRUE;
264         g_main_loop_quit (test_data->m_loop);
265     }
266
267 }
268
269 static bool
270 test_register_local_port ()
271 {
272     static LocalPort *port = new LocalPort(TEST_PARENT_PORT, false, _onParentGotMessage, NULL);
273
274     test_assert (port->Register() == true, "Failed to register port : " + toString(port->lastError ()));
275
276     return true;
277 }
278
279 static bool
280 test_register_trusted_local_port ()
281 {
282     static LocalPort *trused_port = new LocalPort(TEST_PARENT_TRUSTED_PORT, true, _onParentGotMessage, NULL);
283
284     test_assert (trused_port->Register() == true, "Failed to regiser trusted port :" + toString (trused_port->lastError ()));
285
286     return true;
287 }
288
289 static gboolean
290 test_get_local_port_name()
291 {
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());
295  
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());
299
300     return true;
301 }
302
303 static gboolean
304 test_check_trusted_local_port ()
305 {
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());
309
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());
313
314     return true;
315 }
316
317 static bool
318 test_check_remote_port ()
319 {
320     RemotePort p(toString(getppid()), TEST_PARENT_PORT, false);
321
322     test_assert (p.isValid() == true, "Could not get remote port : " + toString(p.lastError()));
323
324     return true;
325 }
326
327 static bool
328 test_check_remote_trusted_port ()
329 {
330     RemotePort p(toString(getppid()), TEST_PARENT_TRUSTED_PORT, true);
331
332     test_assert (p.isValid() == true, "Could not get remote trusted port : " + toString(p.lastError()));
333
334     return true;
335 }
336
337 static bool
338 test_send_message ()
339 {
340     bool res;
341     bundle *b = bundle_create ();
342     bundle_add (b, "Name", "Amarnath");
343     bundle_add (b, "Email", "amarnath.valluri@intel.com");
344
345     RemotePort port (toString (getppid()), TEST_PARENT_PORT, false);
346
347     res = port.sendMessage (b);
348     bundle_free (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()));
352
353     gchar result[32];
354
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");
357
358     return true;
359 }
360
361 static bool
362 test_send_trusted_message ()
363 {
364     bool res;
365     bundle *b = bundle_create ();
366     bundle_add (b, "Name", "Amarnath");
367     bundle_add (b, "Email", "amarnath.valluri@intel.com");
368
369     RemotePort port (toString (getppid()), TEST_PARENT_TRUSTED_PORT, true);
370
371     res = port.sendMessage (b);
372     bundle_free (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()));
376
377     gchar result[32];
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");
380
381     return true;
382 }
383
384 static gboolean
385 _update_test_result (gpointer userdata)
386 {
387     AsyncTestData *test_data = (AsyncTestData *)userdata;
388     test_data->result = false;
389     g_main_loop_quit (test_data->m_loop);
390
391     return FALSE;
392 }
393
394 static bool
395 test_send_bidirectional_message ()
396 {
397     bool res;
398     bundle *b = NULL;;
399     AsyncTestData *test_data = new AsyncTestData();
400     test_data->m_loop = g_main_loop_new (NULL, FALSE);
401
402     LocalPort localPort(TEST_CHILD_PORT, false, _onChildGotMessage, test_data);
403
404     test_assert (localPort.Register() == true, "Failed to register local port: Error: " + toString(localPort.lastError()));
405
406     RemotePort remotePort (toString (getppid()), TEST_PARENT_PORT, false);
407
408     test_assert (remotePort.isValid() == true, "Invalid remote port, Erorr: " + toString(remotePort.lastError()));
409
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);
414     bundle_free (b);
415
416     test_assert (res == true, "Fail to send bidirectional message , Error : " + toString(remotePort.lastError()));
417
418     gchar result[32];
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");
421
422     g_timeout_add_seconds (5, _update_test_result, test_data);
423
424     g_main_loop_run (test_data->m_loop);
425     bool child_got_message = test_data->result;
426
427     g_main_loop_unref (test_data->m_loop);
428     delete test_data ;
429
430     test_assert (child_got_message == true, "Timeout, Child did not recieved reply");
431
432     return true;
433 }
434
435 static bool
436 test_send_bidirectional_trusted_message()
437 {
438     bool res;
439     bundle *b = NULL;;
440     AsyncTestData *test_data = new AsyncTestData();
441     test_data->m_loop = g_main_loop_new (NULL, FALSE);
442
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()));
445
446     RemotePort remotePort (toString (getppid()), TEST_PARENT_TRUSTED_PORT, true);
447     test_assert (remotePort.isValid() == true, "Invalid remote port, Erorr: " + toString(remotePort.lastError()));
448
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);
453     bundle_free (b);
454
455     test_assert (res == true, "Fail to send bidirectional message , Error : " + toString(remotePort.lastError()));
456
457     gchar result[32];
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");
460
461     g_timeout_add_seconds (5, _update_test_result, test_data);
462
463     g_main_loop_run (test_data->m_loop);
464     bool child_got_message = test_data->result;
465
466     g_main_loop_unref (test_data->m_loop);
467     delete test_data ;
468
469     test_assert (child_got_message == true, "Timeout, Child did not recieved reply");
470
471     return true;
472 }
473
474 static gboolean
475 _on_term (gpointer userdata)
476 {
477     g_main_loop_quit ((GMainLoop *)userdata);
478
479     return FALSE;
480 }
481
482 static bool
483 test_setup ()
484 {
485 #ifdef USE_SESSION_BUS
486     GIOChannel *channel = NULL;
487     gchar *bus_address = NULL;
488     gint tmp_fd = 0;
489     gint pipe_fd[2];
490     gchar *argv[4] ;
491     gsize len = 0;
492     const gchar *dbus_monitor = NULL;
493     GError *error = NULL;
494
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>>");
498     argv[3] = NULL;
499
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);
505     } else {
506         GSpawnFlags flags = (GSpawnFlags)(G_SPAWN_SEARCH_PATH | G_SPAWN_LEAVE_DESCRIPTORS_OPEN);
507         tmp_fd = pipe_fd[0];
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);
510         g_free (argv[2]);
511     }
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 */
515
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);
520
521     if (pipe_fd[0]) close (pipe_fd[0]);
522     if (pipe_fd[1]) close (pipe_fd[1]);
523
524     if (bus_address) bus_address[len] = '\0';
525     test_assert (bus_address != NULL && bus_address[0] != 0, "Failed to get dbus-daemon address");
526
527     cout << "Dbus daemon start at : " << bus_address << "\n";
528
529     setenv("DBUS_SESSION_BUS_ADDRESS", bus_address, TRUE);
530
531     g_free (bus_address);
532 #endif /* USE_SESSION_BUS */
533
534     return true;
535 }
536
537 static void
538 test_cleanup ()
539 {
540 #ifdef USE_SESSION_BUS
541     if (__daemon_pid) kill (__daemon_pid, SIGTERM);
542 #endif /* USE_SESSION_BUS */
543 }
544
545 int main (int argc, const char *argv[])
546 {
547     pid_t child_pid;
548
549     if (test_setup () != true) {
550         cerr << "Test setup failur!!!\n";
551         return -1;
552     }
553
554     if (pipe(__pipe) < 0) {
555         cerr << "Failed to create pipe. Cannot run tests!!!" ;
556         return -1;
557     }
558     child_pid = fork ();
559     if ( child_pid < 0) {
560         cerr << "Failed to fork process, Cannot run tests!!!";
561         return -1;
562     }
563      else if (child_pid != 0) 
564     {
565         /* parent process */
566         GMainLoop *m_loop = g_main_loop_new (NULL, FALSE);
567
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); 
572
573         g_unix_signal_add (SIGTERM, _on_term, m_loop);
574
575         g_main_loop_run (m_loop);
576         g_main_loop_unref (m_loop);
577     }
578     else {
579         /* child porcess */
580         sleep (3);
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);
587
588         kill (getppid(), SIGTERM);
589     }
590     test_cleanup ();
591
592     return 0;
593 }
594