Fix TIVI-2638 Enable SmackExecLabel=User for messageport
[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 static pid_t __daemon_pid = 0;
45
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"
50
51 #define TEST_CASE(case) \
52     do { \
53         if (case() != true) { \
54             cerr << #case << ": FAIL\n"; \
55             return -1; \
56         } \
57         else cout << #case << ": SUCCESS\n"; \
58     }while (0)
59
60
61 #define test_assert(expr, msg) \
62     do { \
63         if ((expr) == false) {\
64             cerr << __FUNCTION__ << "-" << __LINE__ << ": assert(" << #expr << ") : " << msg << "\n"; \
65             return false; \
66         } \
67     } while(0);
68
69
70 std::string toString (int a)
71 {
72     char str[256];
73
74     snprintf (str, 255, "%d", a);
75
76     return std::string(str);
77 }
78
79 std::string toString (messageport_error_e err)
80 {
81     return toString ((int)err);
82 }
83
84 class RemotePort;
85
86 class LocalPort {
87
88 protected:
89     static void onMessage (int portId, const char *remoteAppId, const char *remotePort, bool isTrusted, bundle *message);
90
91 public:
92     typedef void (*MessageHandler)(LocalPort *port, bundle *message, RemotePort *remotePort, void *userdata);
93
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) {
96         if (Register ()) {
97             cachedPorts[m_portId] = this;
98         }
99     }
100
101     ~LocalPort() { 
102         cachedPorts.erase(m_portId);
103     }
104
105     bool Register () {
106         int res ;
107         res = m_trusted ? messageport_register_trusted_local_port (m_name.c_str(), onMessage)
108                         : messageport_register_local_port (m_name.c_str(), onMessage);
109
110         if (res < 0) {
111             cerr << "Failed to register port '"<< m_name << "'";
112             m_err = (messageport_error_e) res;
113             return false;
114         }
115         
116         m_portId = res;
117
118         return true;
119     }
120
121     bool SendMessage (const std::string &app_id, const std::string &port_name, bool is_trusted, bundle *data)
122     {
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);
125         if (m_err < 0) {
126             cerr << "Fail to send bidirectional message to '" << app_id << "/" << port_name << ":" << m_err ;
127             return false;
128         }
129
130         return true;
131     }
132
133     const std::string& name () const {
134         return m_name;
135     }
136
137     bool isTrusted () const {
138         return m_trusted;
139     }
140
141     int id () const {
142         return m_portId;
143     }
144
145     messageport_error_e lastError () {
146         return (messageport_error_e) m_err;
147     }
148
149 private:
150     string m_name;
151     bool   m_trusted;
152     int    m_portId;
153     int    m_err;
154     LocalPort::MessageHandler m_msgCb;
155     void  *m_cbData;
156
157     static std::map<int,LocalPort*> cachedPorts ;
158 };
159 std::map<int,LocalPort*> LocalPort::cachedPorts ;
160
161 class RemotePort {
162 public:
163     RemotePort (const string &appId, const string &portName, bool isTrusted)
164         :m_appId(appId), m_portName(portName), m_isTrusted (isTrusted), m_isValid (false)
165     {
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";
170         }
171     }
172
173     ~RemotePort () { }
174
175     bool sendMessage (bundle *b) {
176         
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);
179
180         return m_err == MESSAGEPORT_ERROR_NONE;
181     }
182
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;
187     }
188
189     bool isValid () const {
190         return m_isValid;
191     }
192
193     messageport_error_e lastError () const {
194         return m_err;
195     }
196
197     const string & appId () const {
198         return m_appId;
199     }
200
201     const string & portName () const {
202         return m_portName;
203     }
204
205     bool isTrusted () const {
206         return m_isTrusted;
207     }
208 private:
209     string m_appId;
210     string m_portName;
211     bool   m_isTrusted;
212     messageport_error_e m_err;
213     bool   m_isValid;
214 };
215
216 void LocalPort::onMessage (int portId, const char *remoteAppId, const char *portName, bool isTrusted, bundle *message)
217 {
218     LocalPort * port = LocalPort::cachedPorts[portId];
219     if (port) {
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);
224
225         delete remotePort;
226     }
227     else cerr <<"No cached Port found\n" ;
228 }
229
230 static void
231 _onParentGotMessage (LocalPort *port, bundle *data, RemotePort *remotePort, void *userdata)
232 {
233     /* Write acknoledgement */
234     string ok("OK");
235     int len = ok.length() + 1;
236     if ( write (__pipe[1], ok.c_str(), len) < len) {
237         cerr << "WRITE failed" ;
238     }
239
240     if (remotePort) {
241         bundle *reply = bundle_create ();
242         bundle_add (reply, "Results", "GOT_IT");
243         remotePort->sendMessage (reply);
244
245         bundle_free (reply);
246     }
247 }
248
249 static void
250 _onChildGotMessage (LocalPort *port, bundle *data, RemotePort *remotePort, void *userdata)
251 {
252     AsyncTestData *test_data = (AsyncTestData *)userdata;
253     string ack("OK");
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";
258     }
259
260     if (test_data) {
261         test_data->result = TRUE;
262         g_main_loop_quit (test_data->m_loop);
263     }
264
265 }
266
267 static bool
268 test_register_local_port ()
269 {
270     static LocalPort *port = new LocalPort(TEST_PARENT_PORT, false, _onParentGotMessage, NULL);
271
272     test_assert (port->Register() == true, "Failed to register port : " + toString(port->lastError ()));
273
274     return true;
275 }
276
277 static bool
278 test_register_trusted_local_port ()
279 {
280     static LocalPort *trused_port = new LocalPort(TEST_PARENT_TRUSTED_PORT, true, _onParentGotMessage, NULL);
281
282     test_assert (trused_port->Register() == true, "Failed to regiser trusted port :" + toString (trused_port->lastError ()));
283
284     return true;
285 }
286
287 static gboolean
288 test_get_local_port_name()
289 {
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());
293  
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());
297
298     return true;
299 }
300
301 static gboolean
302 test_check_trusted_local_port ()
303 {
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());
307
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());
311
312     return true;
313 }
314
315 static bool
316 test_check_remote_port ()
317 {
318     RemotePort p(toString(getppid()), TEST_PARENT_PORT, false);
319
320     test_assert (p.isValid() == true, "Could not get remote port : " + toString(p.lastError()));
321
322     return true;
323 }
324
325 static bool
326 test_check_remote_trusted_port ()
327 {
328     RemotePort p(toString(getppid()), TEST_PARENT_TRUSTED_PORT, true);
329
330     test_assert (p.isValid() == true, "Could not get remote trusted port : " + toString(p.lastError()));
331
332     return true;
333 }
334
335 static bool
336 test_send_message ()
337 {
338     bool res;
339     bundle *b = bundle_create ();
340     bundle_add (b, "Name", "Amarnath");
341     bundle_add (b, "Email", "amarnath.valluri@intel.com");
342
343     RemotePort port (toString (getppid()), TEST_PARENT_PORT, false);
344
345     res = port.sendMessage (b);
346     bundle_free (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()));
350
351     gchar result[32];
352
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");
355
356     return true;
357 }
358
359 static bool
360 test_send_trusted_message ()
361 {
362     bool res;
363     bundle *b = bundle_create ();
364     bundle_add (b, "Name", "Amarnath");
365     bundle_add (b, "Email", "amarnath.valluri@intel.com");
366
367     RemotePort port (toString (getppid()), TEST_PARENT_TRUSTED_PORT, true);
368
369     res = port.sendMessage (b);
370     bundle_free (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()));
374
375     gchar result[32];
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");
378
379     return true;
380 }
381
382 static gboolean
383 _update_test_result (gpointer userdata)
384 {
385     AsyncTestData *test_data = (AsyncTestData *)userdata;
386     test_data->result = false;
387     g_main_loop_quit (test_data->m_loop);
388 }
389
390 static bool
391 test_send_bidirectional_message ()
392 {
393     bool res;
394     bundle *b = NULL;;
395     AsyncTestData *test_data = new AsyncTestData();
396     test_data->m_loop = g_main_loop_new (NULL, FALSE);
397
398     LocalPort localPort(TEST_CHILD_PORT, false, _onChildGotMessage, test_data);
399
400     test_assert (localPort.Register() == true, "Failed to register local port: Error: " + toString(localPort.lastError()));
401
402     RemotePort remotePort (toString (getppid()), TEST_PARENT_PORT, false);
403
404     test_assert (remotePort.isValid() == true, "Invalid remote port, Erorr: " + toString(remotePort.lastError()));
405
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);
410     bundle_free (b);
411
412     test_assert (res == true, "Fail to send bidirectional message , Error : " + toString(remotePort.lastError()));
413
414     gchar result[32];
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");
417
418     g_timeout_add_seconds (5, _update_test_result, test_data);
419
420     g_main_loop_run (test_data->m_loop);
421     bool child_got_message = test_data->result;
422
423     g_main_loop_unref (test_data->m_loop);
424     delete test_data ;
425
426     test_assert (child_got_message == true, "Timeout, Child did not recieved reply");
427
428     return true;
429 }
430
431 static bool
432 test_send_bidirectional_trusted_message()
433 {
434     bool res;
435     bundle *b = NULL;;
436     AsyncTestData *test_data = new AsyncTestData();
437     test_data->m_loop = g_main_loop_new (NULL, FALSE);
438
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()));
441
442     RemotePort remotePort (toString (getppid()), TEST_PARENT_TRUSTED_PORT, true);
443     test_assert (remotePort.isValid() == true, "Invalid remote port, Erorr: " + toString(remotePort.lastError()));
444
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);
449     bundle_free (b);
450
451     test_assert (res == true, "Fail to send bidirectional message , Error : " + toString(remotePort.lastError()));
452
453     gchar result[32];
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");
456
457     g_timeout_add_seconds (5, _update_test_result, test_data);
458
459     g_main_loop_run (test_data->m_loop);
460     bool child_got_message = test_data->result;
461
462     g_main_loop_unref (test_data->m_loop);
463     delete test_data ;
464
465     test_assert (child_got_message == true, "Timeout, Child did not recieved reply");
466
467     return true;
468 }
469
470 static gboolean
471 _on_term (gpointer userdata)
472 {
473     g_main_loop_quit ((GMainLoop *)userdata);
474
475     return FALSE;
476 }
477
478 static bool
479 test_setup ()
480 {
481 #ifdef USE_SESSION_BUS
482     GIOChannel *channel = NULL;
483     gchar *bus_address = NULL;
484     gint tmp_fd = 0;
485     gint pipe_fd[2];
486     gchar *argv[4] ;
487     gsize len = 0;
488     const gchar *dbus_monitor = NULL;
489     GError *error = NULL;
490
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>>");
494     argv[3] = NULL;
495
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);
501     } else {
502         GSpawnFlags flags = (GSpawnFlags)(G_SPAWN_SEARCH_PATH | G_SPAWN_LEAVE_DESCRIPTORS_OPEN);
503         tmp_fd = pipe_fd[0];
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);
506         g_free (argv[2]);
507     }
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 */
511
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);
516
517     if (pipe_fd[0]) close (pipe_fd[0]);
518     if (pipe_fd[1]) close (pipe_fd[1]);
519
520     if (bus_address) bus_address[len] = '\0';
521     test_assert (bus_address != NULL && bus_address[0] != 0, "Failed to get dbus-daemon address");
522
523     cout << "Dbus daemon start at : " << bus_address << "\n";
524
525     setenv("DBUS_SESSION_BUS_ADDRESS", bus_address, TRUE);
526
527     g_free (bus_address);
528 #endif /* USE_SESSION_BUS */
529
530     return true;
531 }
532
533 static void
534 test_cleanup ()
535 {
536 #ifdef USE_SESSION_BUS
537     if (__daemon_pid) kill (__daemon_pid, SIGTERM);
538 #endif /* USE_SESSION_BUS */
539 }
540
541 int main (int argc, const char *argv[])
542 {
543     pid_t child_pid;
544
545     if (test_setup () != true) {
546         cerr << "Test setup failur!!!\n";
547         return -1;
548     }
549
550     if (pipe(__pipe) < 0) {
551         cerr << "Failed to create pipe. Cannot run tests!!!" ;
552         return -1;
553     }
554     child_pid = fork ();
555     if ( child_pid < 0) {
556         cerr << "Failed to fork process, Cannot run tests!!!";
557         return -1;
558     }
559      else if (child_pid != 0) 
560     {
561         /* parent process */
562         GMainLoop *m_loop = g_main_loop_new (NULL, FALSE);
563
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); 
568
569         g_unix_signal_add (SIGTERM, _on_term, m_loop);
570
571         g_main_loop_run (m_loop);
572         g_main_loop_unref (m_loop);
573     }
574     else {
575         /* child porcess */
576         sleep (3);
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);
583
584         kill (getppid(), SIGTERM);
585     }
586     test_cleanup ();
587
588     return 0;
589 }
590