bus: Assign a serial number for messages from the driver
[platform/upstream/dbus.git] / test / test-service.c
1 #include <config.h>
2
3 #include "test-utils.h"
4 #ifdef HAVE_UNISTD_H
5 #include <unistd.h>
6 #endif
7
8 static DBusLoop *loop;
9 static dbus_bool_t already_quit = FALSE;
10 static dbus_bool_t hello_from_self_reply_received = FALSE;
11
12 static void
13 quit (void)
14 {
15   if (!already_quit)
16     {
17       _dbus_loop_quit (loop);
18       already_quit = TRUE;
19     }
20 }
21
22 static void die (const char *message) _DBUS_GNUC_NORETURN;
23
24 static void
25 die (const char *message)
26 {
27   fprintf (stderr, "*** test-service: %s", message);
28   exit (1);
29 }
30
31 static void
32 check_hello_from_self_reply (DBusPendingCall *pcall, 
33                              void *user_data)
34 {
35   DBusMessage *reply;
36   DBusMessage *echo_message, *echo_reply = NULL;
37   DBusError error;
38   DBusConnection *connection;
39   
40   int type;
41   
42   dbus_error_init (&error);
43  
44   connection = dbus_bus_get (DBUS_BUS_STARTER, &error);
45   if (connection == NULL)
46     {
47       fprintf (stderr, "*** Failed to open connection to activating message bus: %s\n",
48                error.message);
49       dbus_error_free (&error);
50       die("no memory");
51     }
52
53   
54   echo_message = (DBusMessage *)user_data;
55     
56   reply = dbus_pending_call_steal_reply (pcall);
57     
58   type = dbus_message_get_type (reply);
59     
60   if (type == DBUS_MESSAGE_TYPE_METHOD_RETURN)
61     {
62       const char *s;
63       printf ("Reply from HelloFromSelf received\n");
64      
65       if (!dbus_message_get_args (echo_message,
66                               &error,
67                               DBUS_TYPE_STRING, &s,
68                               DBUS_TYPE_INVALID))
69         {
70             echo_reply = dbus_message_new_error (echo_message,
71                                       error.name,
72                                       error.message);
73
74             if (echo_reply == NULL)
75               die ("No memory\n");
76
77         } 
78       else
79         {  
80           echo_reply = dbus_message_new_method_return (echo_message);
81           if (echo_reply == NULL)
82             die ("No memory\n");
83   
84           if (!dbus_message_append_args (echo_reply,
85                                  DBUS_TYPE_STRING, &s,
86                                  DBUS_TYPE_INVALID))
87             die ("No memory");
88         }
89         
90       if (!dbus_connection_send (connection, echo_reply, NULL))
91         die ("No memory\n");
92       
93       dbus_message_unref (echo_reply);
94     }
95   else if (dbus_set_error_from_message (&error, reply))
96     {
97       printf ("Error type in reply: %s\n", error.message);
98
99       if (strcmp (error.name, DBUS_ERROR_NO_MEMORY) != 0)
100         {
101             echo_reply = dbus_message_new_error (echo_reply,
102                                       error.name,
103                                       error.message);
104
105             if (echo_reply == NULL)
106               die ("No memory\n");
107
108             if (!dbus_connection_send (connection, echo_reply, NULL))
109               die ("No memory\n");
110
111             dbus_message_unref (echo_reply);
112         }
113       dbus_error_free (&error);
114     }
115   else
116      _dbus_assert_not_reached ("Unexpected message received");
117
118   hello_from_self_reply_received = TRUE;
119   
120   dbus_message_unref (reply);
121   dbus_message_unref (echo_message);
122   dbus_pending_call_unref (pcall);
123   dbus_connection_unref (connection);
124 }
125
126 static DBusHandlerResult
127 handle_run_hello_from_self (DBusConnection     *connection,
128                                                DBusMessage        *message)
129 {
130   DBusError error;
131   DBusMessage *reply, *self_message;
132   DBusPendingCall *pcall;
133   char *s;
134
135   _dbus_verbose ("sending reply to Echo method\n");
136   
137   dbus_error_init (&error);
138   
139   if (!dbus_message_get_args (message,
140                               &error,
141                               DBUS_TYPE_STRING, &s,
142                               DBUS_TYPE_INVALID))
143     {
144       reply = dbus_message_new_error (message,
145                                       error.name,
146                                       error.message);
147
148       if (reply == NULL)
149         die ("No memory\n");
150
151       if (!dbus_connection_send (connection, reply, NULL))
152         die ("No memory\n");
153
154       dbus_message_unref (reply);
155
156       return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
157     }
158     printf ("Sending HelloFromSelf\n");
159
160  _dbus_verbose ("*** Sending message to self\n");
161  self_message = dbus_message_new_method_call ("org.freedesktop.DBus.TestSuiteEchoService",
162                                           "/org/freedesktop/TestSuite",
163                                           "org.freedesktop.TestSuite",
164                                           "HelloFromSelf");
165   
166   if (self_message == NULL)
167     die ("No memory");
168   
169   if (!dbus_connection_send_with_reply (connection, self_message, &pcall, -1))
170     die("No memory");
171   
172   dbus_message_ref (message);
173   if (!dbus_pending_call_set_notify (pcall, check_hello_from_self_reply, (void *)message, NULL))
174     die("No memory");
175     
176   printf ("Sent HelloFromSelf\n");
177   return DBUS_HANDLER_RESULT_HANDLED;
178 }
179
180 static DBusHandlerResult
181 handle_echo (DBusConnection     *connection,
182              DBusMessage        *message)
183 {
184   DBusError error;
185   DBusMessage *reply;
186   char *s;
187
188   _dbus_verbose ("sending reply to Echo method\n");
189   
190   dbus_error_init (&error);
191   
192   if (!dbus_message_get_args (message,
193                               &error,
194                               DBUS_TYPE_STRING, &s,
195                               DBUS_TYPE_INVALID))
196     {
197       reply = dbus_message_new_error (message,
198                                       error.name,
199                                       error.message);
200
201       if (reply == NULL)
202         die ("No memory\n");
203
204       if (!dbus_connection_send (connection, reply, NULL))
205         die ("No memory\n");
206
207       dbus_message_unref (reply);
208
209       return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
210     }
211
212   reply = dbus_message_new_method_return (message);
213   if (reply == NULL)
214     die ("No memory\n");
215   
216   if (!dbus_message_append_args (reply,
217                                  DBUS_TYPE_STRING, &s,
218                                  DBUS_TYPE_INVALID))
219     die ("No memory");
220   
221   if (!dbus_connection_send (connection, reply, NULL))
222     die ("No memory\n");
223
224   fprintf (stderr, "Echo service echoed string: \"%s\"\n", s);
225   
226   dbus_message_unref (reply);
227     
228   return DBUS_HANDLER_RESULT_HANDLED;
229 }
230
231 static DBusHandlerResult
232 handle_delay_echo (DBusConnection     *connection,
233                    DBusMessage        *message)
234 {
235   DBusError error;
236   DBusMessage *reply;
237   char *s;
238
239   _dbus_verbose ("sleeping for a short time\n");
240
241   _dbus_sleep_milliseconds (50);
242
243   _dbus_verbose ("sending reply to DelayEcho method\n");
244   
245   dbus_error_init (&error);
246   
247   if (!dbus_message_get_args (message,
248                               &error,
249                               DBUS_TYPE_STRING, &s,
250                               DBUS_TYPE_INVALID))
251     {
252       reply = dbus_message_new_error (message,
253                                       error.name,
254                                       error.message);
255
256       if (reply == NULL)
257         die ("No memory\n");
258
259       if (!dbus_connection_send (connection, reply, NULL))
260         die ("No memory\n");
261
262       dbus_message_unref (reply);
263
264       return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
265     }
266
267   reply = dbus_message_new_method_return (message);
268   if (reply == NULL)
269     die ("No memory\n");
270   
271   if (!dbus_message_append_args (reply,
272                                  DBUS_TYPE_STRING, &s,
273                                  DBUS_TYPE_INVALID))
274     die ("No memory");
275   
276   if (!dbus_connection_send (connection, reply, NULL))
277     die ("No memory\n");
278
279   fprintf (stderr, "DelayEcho service echoed string: \"%s\"\n", s);
280   
281   dbus_message_unref (reply);
282     
283   return DBUS_HANDLER_RESULT_HANDLED;
284 }
285
286
287 static void
288 path_unregistered_func (DBusConnection  *connection,
289                         void            *user_data)
290 {
291   /* connection was finalized */
292 }
293
294 static DBusHandlerResult
295 path_message_func (DBusConnection  *connection,
296                    DBusMessage     *message,
297                    void            *user_data)
298 {
299   if (dbus_message_is_method_call (message,
300                                    "org.freedesktop.TestSuite",
301                                    "Echo"))
302     return handle_echo (connection, message);
303   else if (dbus_message_is_method_call (message,
304                                         "org.freedesktop.TestSuite",
305                                         "DelayEcho"))
306     return handle_delay_echo (connection, message);
307   else if (dbus_message_is_method_call (message,
308                                         "org.freedesktop.TestSuite",
309                                         "Exit"))
310     {
311       quit ();
312       return DBUS_HANDLER_RESULT_HANDLED;
313     }
314   else if (dbus_message_is_method_call (message,
315                                         "org.freedesktop.TestSuite",
316                                         "EmitFoo"))
317     {
318       /* Emit the Foo signal */
319       DBusMessage *signal;
320       double v_DOUBLE;
321
322       _dbus_verbose ("emitting signal Foo\n");
323       
324       signal = dbus_message_new_signal ("/org/freedesktop/TestSuite",
325                                         "org.freedesktop.TestSuite",
326                                         "Foo");
327       if (signal == NULL)
328         die ("No memory\n");
329
330       v_DOUBLE = 42.6;
331       if (!dbus_message_append_args (signal,
332                                      DBUS_TYPE_DOUBLE, &v_DOUBLE,
333                                      DBUS_TYPE_INVALID))
334         die ("No memory");
335   
336       if (!dbus_connection_send (connection, signal, NULL))
337         die ("No memory\n");
338       
339       return DBUS_HANDLER_RESULT_HANDLED;
340     }
341     
342   else if (dbus_message_is_method_call (message,
343                                    "org.freedesktop.TestSuite",
344                                    "RunHelloFromSelf"))
345     {
346       return handle_run_hello_from_self (connection, message);
347     }
348   else if (dbus_message_is_method_call (message,
349                                         "org.freedesktop.TestSuite",
350                                         "HelloFromSelf"))
351     {
352         DBusMessage *reply;
353         printf ("Received the HelloFromSelf message\n");
354         
355         reply = dbus_message_new_method_return (message);
356         if (reply == NULL)
357           die ("No memory");
358         
359         if (!dbus_connection_send (connection, reply, NULL))
360           die ("No memory");
361
362         return DBUS_HANDLER_RESULT_HANDLED;
363     }
364   else
365     return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
366 }
367
368 static DBusObjectPathVTable
369 echo_vtable = {
370   path_unregistered_func,
371   path_message_func,
372   NULL,
373 };
374
375
376 static const char* echo_path = "/org/freedesktop/TestSuite" ;
377
378 static DBusHandlerResult
379 filter_func (DBusConnection     *connection,
380              DBusMessage        *message,
381              void               *user_data)
382 {
383   if (dbus_message_is_signal (message,
384                               DBUS_INTERFACE_LOCAL,
385                               "Disconnected"))
386     {
387       quit ();
388       return DBUS_HANDLER_RESULT_HANDLED;
389     }
390   else
391     {
392       return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
393     }
394 }
395
396 int
397 main (int    argc,
398       char **argv)
399 {
400   DBusError error;
401   int result;
402   DBusConnection *connection;
403   const char *name;
404 #ifndef DBUS_WIN
405   dbus_bool_t do_fork = FALSE;
406 #endif
407   if (argc != 3)
408     {
409       name = "org.freedesktop.DBus.TestSuiteEchoService";
410     }
411   else
412     {
413       name = argv[1];
414 #ifndef DBUS_WIN
415       do_fork = strcmp (argv[2], "fork") == 0;
416 #endif
417     }
418
419   /* The bare minimum for simulating a program "daemonizing"; the intent
420    * is to test services which move from being legacy init scripts to
421    * activated services.
422    * https://bugzilla.redhat.com/show_bug.cgi?id=545267
423    */
424 #ifndef DBUS_WIN
425    if (do_fork)
426     {
427       pid_t pid = fork ();
428       if (pid != 0)
429         exit (0);
430       sleep (1);
431     }
432 #endif
433
434   dbus_error_init (&error);
435   connection = dbus_bus_get (DBUS_BUS_STARTER, &error);
436   if (connection == NULL)
437     {
438       fprintf (stderr, "*** Failed to open connection to activating message bus: %s\n",
439                error.message);
440       dbus_error_free (&error);
441       return 1;
442     }
443
444   loop = _dbus_loop_new ();
445   if (loop == NULL)
446     die ("No memory\n");
447   
448   if (!test_connection_setup (loop, connection))
449     die ("No memory\n");
450
451   if (!dbus_connection_add_filter (connection,
452                                    filter_func, NULL, NULL))
453     die ("No memory");
454
455   if (!dbus_connection_register_object_path (connection,
456                                              echo_path,
457                                              &echo_vtable,
458                                              (void*) 0xdeadbeef))
459     die ("No memory");
460
461   {
462     void *d;
463     if (!dbus_connection_get_object_path_data (connection, echo_path, &d))
464       die ("No memory");
465     if (d != (void*) 0xdeadbeef)
466       die ("dbus_connection_get_object_path_data() doesn't seem to work right\n");
467   }
468
469   result = dbus_bus_request_name (connection, name,
470                                   0, &error);
471   if (dbus_error_is_set (&error))
472     {
473       fprintf (stderr, "Error %s\n", error.message);
474       _dbus_verbose ("*** Failed to acquire service: %s\n",
475                      error.message);
476       dbus_error_free (&error);
477       exit (1);
478     }
479
480   if (result != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER)
481     {
482       fprintf (stderr, "Unable to acquire service: code %d\n", result);
483       _dbus_verbose ("*** Failed to acquire service: %d\n", result);
484       exit (1);
485     }
486
487   _dbus_verbose ("*** Test service entering main loop\n");
488   _dbus_loop_run (loop);
489   
490   test_connection_shutdown (loop, connection);
491
492   dbus_connection_remove_filter (connection, filter_func, NULL);
493   
494   dbus_connection_unref (connection);
495
496   _dbus_loop_unref (loop);
497   loop = NULL;
498   
499   dbus_shutdown ();
500
501   _dbus_verbose ("*** Test service exiting\n");
502   
503   return 0;
504 }