1 /* -*- mode: C; c-basic-offset: 4; indent-tabs-mode: nil; -*- */
2 
3 #include <string.h>
4 #include "ibus.h"
5 
6 static IBusBus *bus;
7 
8 static void
print_engines(const GList * engines)9 print_engines (const GList *engines)
10 {
11     for (; engines; engines = g_list_next (engines)) {
12         IBusEngineDesc *engine_desc = IBUS_ENGINE_DESC (engines->data);
13         g_assert (engine_desc);
14 #if 0
15         g_debug ("%s (id:%s, icon:%s)",
16                  ibus_engine_desc_get_longname (engine_desc),
17                  ibus_engine_desc_get_name (engine_desc),
18                  ibus_engine_desc_get_icon (engine_desc));
19 #endif
20     }
21 }
22 
23 #ifndef IBUS_DISABLE_DEPRECATED
24 static void
test_list_active_engines(void)25 test_list_active_engines (void)
26 {
27     GList *engines;
28     IBUS_TYPE_ENGINE_DESC;
29 
30     engines = ibus_bus_list_active_engines (bus);
31     print_engines (engines);
32 
33     g_list_foreach (engines, (GFunc) g_object_unref, NULL);
34     g_list_free (engines);
35 }
36 #endif /* IBUS_DISABLE_DEPRECATED */
37 
38 static void
test_list_engines(void)39 test_list_engines (void)
40 {
41     GList *engines;
42     IBUS_TYPE_ENGINE_DESC;
43 
44     engines = ibus_bus_list_engines (bus);
45     print_engines (engines);
46 
47     g_list_foreach (engines, (GFunc) g_object_unref, NULL);
48     g_list_free (engines);
49 }
50 
51 static void
name_owner_changed_cb(IBusBus * bus,gchar * name,gchar * old,gchar * new,gpointer data)52 name_owner_changed_cb (IBusBus  *bus,
53                        gchar    *name,
54                        gchar    *old,
55                        gchar    *new,
56                        gpointer  data)
57 {
58     g_debug ("%s: bus=%s, old=%s, new=%s", G_STRFUNC, name, old, new);
59 }
60 
61 static void call_next_async_function (void);
62 
63 static void
finish_request_name_async(GObject * source_object,GAsyncResult * res,gpointer user_data)64 finish_request_name_async (GObject *source_object,
65                            GAsyncResult *res,
66                            gpointer user_data)
67 {
68     GError *error = NULL;
69     guint id = ibus_bus_request_name_async_finish (bus, res, &error);
70 
71     g_assert (id != 0);
72 
73     g_debug ("request name returned %d: ", id);
74 
75     switch (id) {
76     case IBUS_BUS_REQUEST_NAME_REPLY_PRIMARY_OWNER:
77         g_debug ("got ownership");
78         break;
79     case IBUS_BUS_REQUEST_NAME_REPLY_IN_QUEUE:
80         g_debug ("got queued");
81         break;
82     case IBUS_BUS_REQUEST_NAME_REPLY_EXISTS:
83         g_debug ("request already in queue");
84         break;
85     case IBUS_BUS_REQUEST_NAME_REPLY_ALREADY_OWNER:
86         g_debug ("already owner");
87         break;
88     default:
89         g_assert_not_reached ();
90     }
91 
92     if (error) {
93         g_warning ("Error %s: %s", G_STRFUNC, error->message);
94         g_error_free (error);
95     }
96 
97     g_debug ("ibus_bus_request_name_async_finish: OK");
98     call_next_async_function ();
99 }
100 
101 static void
start_request_name_async(void)102 start_request_name_async (void)
103 {
104     ibus_bus_set_watch_dbus_signal (bus, TRUE);
105     ibus_bus_set_watch_ibus_signal (bus, TRUE);
106 
107     g_signal_connect (bus, "name-owner-changed",
108                       (GCallback) name_owner_changed_cb, NULL);
109 
110     ibus_bus_request_name_async (bus,
111                                  "org.freedesktop.IBus.IBusBusTest",
112                                  IBUS_BUS_NAME_FLAG_REPLACE_EXISTING,
113                                  -1, /* timeout */
114                                  NULL, /* cancellable */
115                                  finish_request_name_async,
116                                  NULL); /* user_data */
117 }
118 
119 
120 static void
finish_name_has_owner_async(GObject * source_object,GAsyncResult * res,gpointer user_data)121 finish_name_has_owner_async (GObject *source_object,
122                              GAsyncResult *res,
123                              gpointer user_data)
124 {
125     GError *error = NULL;
126     gboolean has_owner = ibus_bus_name_has_owner_async_finish (bus,
127                                                                res,
128                                                                &error);
129     g_assert (has_owner);
130     g_debug ("ibus_bus_name_has_owner_async_finish: OK");
131     call_next_async_function ();
132 }
133 
134 static void
start_name_has_owner_async(void)135 start_name_has_owner_async (void)
136 {
137     ibus_bus_name_has_owner_async (bus,
138                                    "org.freedesktop.IBus.IBusBusTest",
139                                    -1, /* timeout */
140                                    NULL, /* cancellable */
141                                    finish_name_has_owner_async,
142                                    NULL); /* user_data */
143 }
144 
145 static void
finish_get_name_owner_async(GObject * source_object,GAsyncResult * res,gpointer user_data)146 finish_get_name_owner_async (GObject *source_object,
147                              GAsyncResult *res,
148                              gpointer user_data)
149 {
150     GError *error = NULL;
151     gchar *owner = ibus_bus_get_name_owner_async_finish (bus,
152                                                          res,
153                                                          &error);
154     g_assert (owner);
155     g_free (owner);
156     g_debug ("ibus_bus_name_get_name_owner_async_finish: OK");
157     call_next_async_function ();
158 }
159 
160 static void
start_get_name_owner_async(void)161 start_get_name_owner_async (void)
162 {
163     ibus_bus_get_name_owner_async (bus,
164                                    "org.freedesktop.IBus.IBusBusTest",
165                                    -1, /* timeout */
166                                    NULL, /* cancellable */
167                                    finish_get_name_owner_async,
168                                    NULL); /* user_data */
169 }
170 
171 static void
finish_release_name_async(GObject * source_object,GAsyncResult * res,gpointer user_data)172 finish_release_name_async (GObject *source_object,
173                            GAsyncResult *res,
174                            gpointer user_data)
175 {
176     GError *error = NULL;
177     guint id = ibus_bus_release_name_async_finish (bus,
178                                                    res,
179                                                    &error);
180     g_assert (id != 0);
181     g_debug ("ibus_bus_release_name_async_finish: OK");
182     call_next_async_function ();
183 }
184 
185 static void
start_release_name_async(void)186 start_release_name_async (void)
187 {
188     ibus_bus_release_name_async (bus,
189                                  "org.freedesktop.IBus.IBusBusTest",
190                                  -1, /* timeout */
191                                  NULL, /* cancellable */
192                                  finish_release_name_async,
193                                  NULL); /* user_data */
194 }
195 
196 static void
finish_add_match_async(GObject * source_object,GAsyncResult * res,gpointer user_data)197 finish_add_match_async (GObject *source_object,
198                         GAsyncResult *res,
199                         gpointer user_data)
200 {
201     GError *error = NULL;
202     gboolean result = ibus_bus_add_match_async_finish (bus,
203                                                        res,
204                                                        &error);
205     g_assert (result);
206     g_debug ("ibus_bus_add_match_finish: OK");
207     call_next_async_function ();
208 }
209 
210 static void
start_add_match_async(void)211 start_add_match_async (void)
212 {
213     ibus_bus_add_match_async (bus,
214                               "type='signal'",
215                               -1, /* timeout */
216                               NULL, /* cancellable */
217                               finish_add_match_async,
218                               NULL); /* user_data */
219 }
220 
221 static void
finish_remove_match_async(GObject * source_object,GAsyncResult * res,gpointer user_data)222 finish_remove_match_async (GObject *source_object,
223                            GAsyncResult *res,
224                            gpointer user_data)
225 {
226     GError *error = NULL;
227     gboolean result = ibus_bus_remove_match_async_finish (bus,
228                                                           res,
229                                                           &error);
230     g_assert (result);
231     g_debug ("ibus_bus_remove_match_finish: OK");
232     call_next_async_function ();
233 }
234 
235 static void
start_remove_match_async(void)236 start_remove_match_async (void)
237 {
238     ibus_bus_remove_match_async (bus,
239                                  "type='signal'",
240                                  -1, /* timeout */
241                                  NULL, /* cancellable */
242                                  finish_remove_match_async,
243                                  NULL); /* user_data */
244 }
245 
246 static int create_input_context_count = 0;
247 static void
finish_create_input_context_async_success(GObject * source_object,GAsyncResult * res,gpointer user_data)248 finish_create_input_context_async_success (GObject      *source_object,
249                                           GAsyncResult *res,
250                                           gpointer      user_data)
251 {
252     GMainLoop *loop = (GMainLoop *)user_data;
253     GError *error = NULL;
254     IBusInputContext *context =
255           ibus_bus_create_input_context_async_finish (bus, res, &error);
256 
257     g_assert (IBUS_IS_INPUT_CONTEXT (context));
258     g_object_unref (context);
259     if (--create_input_context_count == 0)
260         g_main_loop_quit (loop);
261 }
262 
263 static void
finish_create_input_context_async_failed(GObject * source_object,GAsyncResult * res,gpointer user_data)264 finish_create_input_context_async_failed (GObject      *source_object,
265                                           GAsyncResult *res,
266                                           gpointer      user_data)
267 {
268     GMainLoop *loop = (GMainLoop *)user_data;
269     GError *error = NULL;
270     IBusInputContext *context =
271             ibus_bus_create_input_context_async_finish (bus, res, &error);
272 
273     g_assert (context == NULL);
274     g_assert (error != NULL);
275     g_error_free (error);
276     if (--create_input_context_count <= 0)
277         g_main_loop_quit (loop);
278 }
279 
280 static void
test_create_input_context_async(void)281 test_create_input_context_async (void)
282 {
283     GMainLoop *loop = NULL;
284     GCancellable *cancellable = NULL;
285 
286     /* create an IC */
287     create_input_context_count = 1;
288     loop = g_main_loop_new (NULL, TRUE);
289     ibus_bus_create_input_context_async (bus,
290             "test-async",
291             -1, /* timeout */
292             NULL, /* cancellable */
293             finish_create_input_context_async_success,
294             loop); /* user_data */
295     g_main_loop_run (loop);
296     g_main_loop_unref (loop);
297 
298     /* call create, and then cancel */
299     create_input_context_count = 1;
300     loop = g_main_loop_new (NULL, TRUE);
301     cancellable = g_cancellable_new ();
302     ibus_bus_create_input_context_async (bus,
303             "test-async",
304             -1, /* timeout */
305             cancellable, /* cancellable */
306             finish_create_input_context_async_failed,
307             loop); /* user_data */
308     g_cancellable_cancel (cancellable);
309     g_object_unref (cancellable);
310     g_main_loop_run (loop);
311     g_main_loop_unref (loop);
312 
313     /* create four IC, and cancel two */
314     create_input_context_count = 4;
315     loop = g_main_loop_new (NULL, TRUE);
316     cancellable = g_cancellable_new ();
317     ibus_bus_create_input_context_async (bus,
318             "test-async",
319             -1, /* timeout */
320             cancellable, /* cancellable */
321             finish_create_input_context_async_failed,
322             loop); /* user_data */
323     ibus_bus_create_input_context_async (bus,
324             "test-async",
325             -1, /* timeout */
326             NULL, /* cancellable */
327             finish_create_input_context_async_success,
328             loop); /* user_data */
329     ibus_bus_create_input_context_async (bus,
330             "test-async",
331             -1, /* timeout */
332             NULL, /* cancellable */
333             finish_create_input_context_async_success,
334             loop); /* user_data */
335     ibus_bus_create_input_context_async (bus,
336             "test-async",
337             -1, /* timeout */
338             cancellable, /* cancellable */
339             finish_create_input_context_async_failed,
340             loop); /* user_data */
341     g_cancellable_cancel (cancellable);
342     g_object_unref (cancellable);
343 
344     g_main_loop_run (loop);
345     g_main_loop_unref (loop);
346 }
347 
348 static void
finish_current_input_context_async(GObject * source_object,GAsyncResult * res,gpointer user_data)349 finish_current_input_context_async (GObject *source_object,
350                                     GAsyncResult *res,
351                                     gpointer user_data)
352 {
353     GError *error = NULL;
354     g_free (ibus_bus_current_input_context_async_finish (bus,
355                                                          res,
356                                                          &error));
357     // no null check.
358     g_debug ("ibus_bus_current_input_context_finish: OK");
359     call_next_async_function ();
360 }
361 
362 static void
start_current_input_context_async(void)363 start_current_input_context_async (void)
364 {
365     ibus_bus_current_input_context_async (bus,
366                                           -1, /* timeout */
367                                           NULL, /* cancellable */
368                                           finish_current_input_context_async,
369                                           NULL); /* user_data */
370 }
371 
372 static void
finish_list_engines_async(GObject * source_object,GAsyncResult * res,gpointer user_data)373 finish_list_engines_async (GObject *source_object,
374                            GAsyncResult *res,
375                            gpointer user_data)
376 {
377     GError *error = NULL;
378     GList *engines = ibus_bus_list_engines_async_finish (bus,
379                                                          res,
380                                                          &error);
381     // no null check.
382     g_list_foreach (engines, (GFunc) g_object_unref, NULL);
383     g_list_free (engines);
384     g_debug ("ibus_bus_list_engines_finish: OK");
385     call_next_async_function ();
386 }
387 
388 static void
start_list_engines_async(void)389 start_list_engines_async (void)
390 {
391     ibus_bus_list_engines_async (bus,
392                                  -1, /* timeout */
393                                  NULL, /* cancellable */
394                                  finish_list_engines_async,
395                                  NULL); /* user_data */
396 }
397 
398 #ifndef IBUS_DISABLE_DEPRECATED
399 static void
finish_list_active_engines_async(GObject * source_object,GAsyncResult * res,gpointer user_data)400 finish_list_active_engines_async (GObject *source_object,
401                                   GAsyncResult *res,
402                                   gpointer user_data)
403 {
404     GError *error = NULL;
405     GList *engines = ibus_bus_list_active_engines_async_finish (bus,
406                                                                 res,
407                                                                 &error);
408     // no null check.
409     g_list_foreach (engines, (GFunc) g_object_unref, NULL);
410     g_list_free (engines);
411     g_debug ("ibus_bus_list_active_engines_finish: OK");
412     call_next_async_function ();
413 }
414 
415 static void
start_list_active_engines_async(void)416 start_list_active_engines_async (void)
417 {
418     ibus_bus_list_active_engines_async (bus,
419                                         -1, /* timeout */
420                                         NULL, /* cancellable */
421                                         finish_list_active_engines_async,
422                                         NULL); /* user_data */
423 }
424 
425 static void
finish_get_use_sys_layout_async(GObject * source_object,GAsyncResult * res,gpointer user_data)426 finish_get_use_sys_layout_async (GObject *source_object,
427                                  GAsyncResult *res,
428                                  gpointer user_data)
429 {
430     GError *error = NULL;
431     ibus_bus_get_use_sys_layout_async_finish (bus,
432                                               res,
433                                               &error);
434     g_debug ("ibus_bus_get_use_sys_layout_finish: OK");
435     call_next_async_function ();
436 }
437 
438 static void
start_get_use_sys_layout_async(void)439 start_get_use_sys_layout_async (void)
440 {
441     ibus_bus_get_use_sys_layout_async (bus,
442                                        -1, /* timeout */
443                                        NULL, /* cancellable */
444                                        finish_get_use_sys_layout_async,
445                                        NULL); /* user_data */
446 }
447 
448 static void
finish_get_use_global_engine_async(GObject * source_object,GAsyncResult * res,gpointer user_data)449 finish_get_use_global_engine_async (GObject *source_object,
450                                     GAsyncResult *res,
451                                     gpointer user_data)
452 {
453     GError *error = NULL;
454     ibus_bus_get_use_global_engine_async_finish (bus,
455                                                  res,
456                                                  &error);
457     g_debug ("ibus_bus_get_use_global_engine_finish: OK");
458     call_next_async_function ();
459 }
460 
461 static void
start_get_use_global_engine_async(void)462 start_get_use_global_engine_async (void)
463 {
464     ibus_bus_get_use_global_engine_async (bus,
465                                           -1, /* timeout */
466                                           NULL, /* cancellable */
467                                           finish_get_use_global_engine_async,
468                                           NULL); /* user_data */
469 }
470 
471 static void
finish_is_global_engine_enabled_async(GObject * source_object,GAsyncResult * res,gpointer user_data)472 finish_is_global_engine_enabled_async (GObject *source_object,
473                                        GAsyncResult *res,
474                                        gpointer user_data)
475 {
476     GError *error = NULL;
477     ibus_bus_is_global_engine_enabled_async_finish (bus,
478                                                     res,
479                                                     &error);
480     g_debug ("ibus_bus_is_global_engine_enabled_finish: OK");
481     call_next_async_function ();
482 }
483 
484 static void
start_is_global_engine_enabled_async(void)485 start_is_global_engine_enabled_async (void)
486 {
487     ibus_bus_is_global_engine_enabled_async (bus,
488                                              -1, /* timeout */
489                                              NULL, /* cancellable */
490                                              finish_is_global_engine_enabled_async,
491                                              NULL); /* user_data */
492 }
493 #endif /* IBUS_DISABLE_DEPRECATED */
494 
495 static void
finish_get_global_engine_async(GObject * source_object,GAsyncResult * res,gpointer user_data)496 finish_get_global_engine_async (GObject *source_object,
497                                 GAsyncResult *res,
498                                 gpointer user_data)
499 {
500     GError *error = NULL;
501     IBusEngineDesc *desc = ibus_bus_get_global_engine_async_finish (bus,
502                                                                     res,
503                                                                     &error);
504     if (desc)
505         g_object_unref (desc);
506     g_debug ("ibus_bus_get_global_engine_finish: OK");
507     call_next_async_function ();
508 }
509 
510 static void
start_get_global_engine_async(void)511 start_get_global_engine_async (void)
512 {
513     ibus_bus_get_global_engine_async (bus,
514                                       -1, /* timeout */
515                                       NULL, /* cancellable */
516                                       finish_get_global_engine_async,
517                                       NULL); /* user_data */
518 }
519 
520 static void
finish_set_global_engine_async(GObject * source_object,GAsyncResult * res,gpointer user_data)521 finish_set_global_engine_async (GObject *source_object,
522                                 GAsyncResult *res,
523                                 gpointer user_data)
524 {
525     GError *error = NULL;
526     ibus_bus_set_global_engine_async_finish (bus,
527                                              res,
528                                              &error);
529     g_debug ("ibus_bus_set_global_engine_finish: OK");
530     call_next_async_function ();
531 }
532 
533 static void
start_set_global_engine_async(void)534 start_set_global_engine_async (void)
535 {
536     ibus_bus_set_global_engine_async (bus,
537                                       "anthy",
538                                       -1, /* timeout */
539                                       NULL, /* cancellable */
540                                       finish_set_global_engine_async,
541                                       NULL); /* user_data */
542 }
543 
544 static void
finish_preload_engines_async(GObject * source_object,GAsyncResult * res,gpointer user_data)545 finish_preload_engines_async (GObject      *source_object,
546                               GAsyncResult *res,
547                               gpointer      user_data)
548 {
549     GError *error = NULL;
550     ibus_bus_preload_engines_async_finish (bus, res, &error);
551     g_debug ("ibus_bus_preload_engines_async_finish: OK");
552     call_next_async_function ();
553 }
554 
555 static void
start_preload_engines_async(void)556 start_preload_engines_async (void)
557 {
558     const gchar *preload_engines[] = { "xkb:us::eng", NULL };
559 
560     ibus_bus_preload_engines_async (
561             bus,
562             preload_engines,
563             -1, /* timeout */
564             NULL, /* cancellable */
565             finish_preload_engines_async,
566             NULL); /* user_data */
567 }
568 
569 static void
test_get_address(void)570 test_get_address (void)
571 {
572     GVariant *result;
573 
574     result = ibus_bus_get_ibus_property (bus, "Address");
575     g_variant_get_string (result, NULL);
576     g_variant_unref (result);
577 }
578 
579 static void
test_get_current_input_context(void)580 test_get_current_input_context (void)
581 {
582     GVariant *result;
583 
584     result = ibus_bus_get_ibus_property (bus, "CurrentInputContext");
585     g_variant_get_string (result, NULL);
586     g_variant_unref (result);
587 }
588 
589 static void
test_get_engines(void)590 test_get_engines (void)
591 {
592     GVariant *result, *var;
593     GVariantIter *iter;
594     GList *engines = NULL;
595 
596     result = ibus_bus_get_ibus_property (bus, "Engines");
597     iter = g_variant_iter_new (result);
598     while (g_variant_iter_loop (iter, "v", &var)) {
599         IBusSerializable *serializable = ibus_serializable_deserialize (var);
600         g_object_ref_sink (serializable);
601         engines = g_list_append (engines, serializable);
602     }
603     g_variant_iter_free (iter);
604     g_variant_unref (result);
605 
606     print_engines (engines);
607 
608     g_list_foreach (engines, (GFunc) g_object_unref, NULL);
609     g_list_free (engines);
610 }
611 
612 static void
test_get_global_engine(void)613 test_get_global_engine (void)
614 {
615     GVariant *result, *obj;
616     IBusEngineDesc *desc = NULL;
617 
618     if (!ibus_bus_set_global_engine (bus, "xkb:us::eng"))
619         return;
620 
621     result = ibus_bus_get_ibus_property (bus, "GlobalEngine");
622     g_assert (result);
623 
624     obj = g_variant_get_variant (result);
625     g_assert (obj);
626 
627     desc = IBUS_ENGINE_DESC (ibus_serializable_deserialize (obj));
628     g_assert (desc);
629     g_assert_cmpstr (ibus_engine_desc_get_name (desc), ==, "xkb:us::eng");
630 
631     g_variant_unref (obj);
632     g_variant_unref (result);
633 
634     g_object_unref (desc);
635 }
636 
637 static void
test_set_preload_engines(void)638 test_set_preload_engines (void)
639 {
640     const gchar *preload_engines[] = { "xkb:us::eng", "xkb:jp::jpn", NULL };
641     GVariant *variant;
642 
643     variant = g_variant_new_strv (preload_engines, -1);
644     ibus_bus_set_ibus_property (bus, "PreloadEngines", variant);
645 }
646 
647 static void
finish_get_address_async(GObject * source_object,GAsyncResult * res,gpointer user_data)648 finish_get_address_async (GObject      *source_object,
649                           GAsyncResult *res,
650                           gpointer      user_data)
651 {
652     GError *error = NULL;
653     GVariant *result;
654 
655     result = ibus_bus_get_ibus_property_async_finish (bus, res, &error);
656     g_variant_get_string (result, NULL);
657     g_variant_unref (result);
658     g_debug ("finish_get_address_async: OK");
659     call_next_async_function ();
660 }
661 
662 static void
start_get_address_async(void)663 start_get_address_async (void)
664 {
665     ibus_bus_get_ibus_property_async (
666             bus,
667             "Address",
668             -1, /* timeout */
669             NULL, /* cancellable */
670             finish_get_address_async,
671             NULL); /* user_data */
672 }
673 
674 static void
finish_get_current_input_context_async(GObject * source_object,GAsyncResult * res,gpointer user_data)675 finish_get_current_input_context_async (GObject      *source_object,
676                                         GAsyncResult *res,
677                                         gpointer      user_data)
678 {
679     GError *error = NULL;
680     GVariant *result;
681 
682     result = ibus_bus_get_ibus_property_async_finish (bus, res, &error);
683     g_variant_get_string (result, NULL);
684     g_variant_unref (result);
685     g_debug ("finish_get_current_input_context_async: OK");
686     call_next_async_function ();
687 }
688 
689 static void
start_get_current_input_context_async(void)690 start_get_current_input_context_async (void)
691 {
692     ibus_bus_get_ibus_property_async (
693             bus,
694             "CurrentInputContext",
695             -1, /* timeout */
696             NULL, /* cancellable */
697             finish_get_current_input_context_async,
698             NULL); /* user_data */
699 }
700 
701 static void
finish_get_engines_async(GObject * source_object,GAsyncResult * res,gpointer user_data)702 finish_get_engines_async (GObject      *source_object,
703                           GAsyncResult *res,
704                           gpointer      user_data)
705 {
706     GError *error = NULL;
707     GVariant *result, *var;
708     GVariantIter *iter;
709     GList *engines = NULL;
710 
711     result = ibus_bus_get_ibus_property_async_finish (bus, res, &error);
712     iter = g_variant_iter_new (result);
713     while (g_variant_iter_loop (iter, "v", &var)) {
714         IBusSerializable *serializable = ibus_serializable_deserialize (var);
715         g_object_ref_sink (serializable);
716         engines = g_list_append (engines, serializable);
717     }
718     g_variant_iter_free (iter);
719     g_variant_unref (result);
720 
721     print_engines (engines);
722 
723     g_list_foreach (engines, (GFunc) g_object_unref, NULL);
724     g_list_free (engines);
725 
726     g_debug ("finish_get_engines_async: OK");
727     call_next_async_function ();
728 }
729 
730 static void
start_get_engines_async(void)731 start_get_engines_async (void)
732 {
733     ibus_bus_get_ibus_property_async (
734             bus,
735             "Engines",
736             -1, /* timeout */
737             NULL, /* cancellable */
738             finish_get_engines_async,
739             NULL); /* user_data */
740 }
741 
742 static void
finish_get_prop_global_engine_async(GObject * source_object,GAsyncResult * res,gpointer user_data)743 finish_get_prop_global_engine_async (GObject *source_object,
744                                      GAsyncResult *res,
745                                      gpointer user_data)
746 {
747     GError *error = NULL;
748     GVariant *result, *obj;
749     IBusEngineDesc *desc = NULL;
750 
751     result = ibus_bus_get_ibus_property_async_finish (bus, res, &error);
752     obj = g_variant_get_variant (result);
753     desc = IBUS_ENGINE_DESC (ibus_serializable_deserialize (obj));
754     g_variant_unref (obj);
755     g_variant_unref (result);
756 
757     if (desc)
758         g_object_unref (desc);
759 
760     g_debug ("finish_get_prop_global_engine_async: OK");
761     call_next_async_function ();
762 }
763 
764 static void
start_get_prop_global_engine_async(void)765 start_get_prop_global_engine_async (void)
766 {
767     ibus_bus_get_ibus_property_async (
768             bus,
769             "GlobalEngine",
770             -1, /* timeout */
771             NULL, /* cancellable */
772             finish_get_prop_global_engine_async,
773             NULL); /* user_data */
774 }
775 
776 static void
finish_set_preload_engines_async(GObject * source_object,GAsyncResult * res,gpointer user_data)777 finish_set_preload_engines_async (GObject      *source_object,
778                                   GAsyncResult *res,
779                                   gpointer      user_data)
780 {
781     GError *error = NULL;
782 
783     ibus_bus_set_ibus_property_async_finish (bus, res, &error);
784     g_debug ("finish_set_preload_engines_async: OK");
785     call_next_async_function ();
786 }
787 
788 static void
start_set_preload_engines_async(void)789 start_set_preload_engines_async (void)
790 {
791     const gchar *preload_engines[] = { "xkb:us::eng", "xkb:jp::jpn", NULL };
792     GVariant *variant;
793 
794     variant = g_variant_new_strv (preload_engines, -1);
795     ibus_bus_set_ibus_property_async (
796             bus,
797             "PreloadEngines",
798             variant,
799             -1, /* timeout */
800             NULL, /* cancellable */
801             finish_set_preload_engines_async,
802             NULL); /* user_data */
803 }
804 
805 static void
finish_exit_async(GObject * source_object,GAsyncResult * res,gpointer user_data)806 finish_exit_async (GObject *source_object,
807                    GAsyncResult *res,
808                    gpointer user_data)
809 {
810     GError *error = NULL;
811     gboolean result = ibus_bus_exit_async_finish (bus,
812                                                   res,
813                                                   &error);
814     g_assert (result);
815     g_debug ("ibus_bus_exit_finish: OK");
816     g_usleep (G_USEC_PER_SEC);
817     call_next_async_function ();
818 }
819 
820 static void
start_exit_async(void)821 start_exit_async (void)
822 {
823     /* When `./runtest ibus-bus` runs, ibus-daemon sometimes failed to
824      * restart because closing a file descriptor was failed in
825      * bus/server.c:_restart_server() with a following error:
826      *     "inotify read(): Bad file descriptor"
827      * Now g_usleep() is added here to write down the buffer and not to
828      * fail to restart ibus-daemon.
829      */
830     g_usleep (G_USEC_PER_SEC);
831     ibus_bus_exit_async (bus,
832                          TRUE, /* restart */
833                          -1, /* timeout */
834                          NULL, /* cancellable */
835                          finish_exit_async,
836                          NULL); /* user_data */
837 }
838 
839 static gboolean
test_async_apis_finish(gpointer user_data)840 test_async_apis_finish (gpointer user_data)
841 {
842     /* INFO: g_warning() causes SEGV with runtest script */
843     if (ibus_get_address () == NULL)
844         g_warning ("ibus-daemon does not restart yet from start_exit_async().");
845     ibus_quit ();
846     return FALSE;
847 }
848 
849 static void
test_get_engines_by_names(void)850 test_get_engines_by_names (void)
851 {
852     IBusEngineDesc **engines = NULL;
853     const gchar *names[] = {
854         "xkb:us::eng",
855         "xkb:ca:eng:eng",
856         "xkb:fr::fra",
857         "xkb:jp::jpn",
858         "invalid_engine_name",
859         NULL,
860     };
861 
862     engines = ibus_bus_get_engines_by_names (bus, names);
863 
864     g_assert(engines != NULL);
865     IBusEngineDesc **p;
866 
867     gint i = 0;
868     for (p = engines; *p != NULL; p++) {
869         g_assert (IBUS_IS_ENGINE_DESC (*p));
870         g_assert_cmpstr (names[i], ==, ibus_engine_desc_get_name (*p));
871         i++;
872         g_object_unref (*p);
873     }
874 
875     // The last engine does not exist.
876     g_assert_cmpint (i, ==, G_N_ELEMENTS(names) - 2);
877 
878     g_free (engines);
879 
880     engines = NULL;
881 }
882 
883 static void
test_async_apis(void)884 test_async_apis (void)
885 {
886     g_debug ("start");
887     call_next_async_function ();
888     ibus_main ();
889 }
890 
891 static void
call_next_async_function(void)892 call_next_async_function (void)
893 {
894     static void (*async_functions[])(void) = {
895         start_request_name_async,
896         start_name_has_owner_async,
897         start_get_name_owner_async,
898         start_release_name_async,
899         start_add_match_async,
900         start_remove_match_async,
901         start_current_input_context_async,
902         // FIXME test ibus_bus_register_component_async.
903         start_list_engines_async,
904         start_list_active_engines_async,
905         start_get_use_sys_layout_async,
906         start_get_use_global_engine_async,
907         start_is_global_engine_enabled_async,
908         start_set_global_engine_async,
909         start_get_global_engine_async,
910         start_preload_engines_async,
911         start_get_address_async,
912         start_get_current_input_context_async,
913         start_get_engines_async,
914         start_get_prop_global_engine_async,
915         start_set_preload_engines_async,
916         start_exit_async,
917     };
918     static guint index = 0;
919 
920     /* Use g_timeout_add to make sure test_async_apis finishes even if
921      * async_functions is empty.
922      */
923     if (index >= G_N_ELEMENTS (async_functions))
924         g_timeout_add (1, test_async_apis_finish, NULL);
925     else
926         (*async_functions[index++])();
927 }
928 
929 static void
_bus_connected_cb(IBusBus * bus,gpointer user_data)930 _bus_connected_cb (IBusBus *bus,
931                    gpointer user_data)
932 {
933     g_assert (ibus_bus_is_connected (bus));
934     ibus_quit ();
935 }
936 
937 static void
test_bus_new_async(void)938 test_bus_new_async (void)
939 {
940     g_object_unref (bus);
941     bus = ibus_bus_new_async ();
942     g_signal_connect (bus, "connected", G_CALLBACK (_bus_connected_cb), NULL);
943     ibus_main ();
944 }
945 
946 gint
main(gint argc,gchar ** argv)947 main (gint    argc,
948       gchar **argv)
949 {
950     gint result;
951     ibus_init ();
952     g_test_init (&argc, &argv, NULL);
953     bus = ibus_bus_new ();
954     g_object_unref (bus);
955     bus = ibus_bus_new (); // crosbug.com/17293
956 
957     if (!ibus_bus_is_connected (bus)) {
958         g_warning ("Not connected to ibus-daemon");
959         g_object_unref (bus);
960         return -1;
961     }
962 
963     g_test_add_func ("/ibus/list-engines", test_list_engines);
964     g_test_add_func ("/ibus/list-active-engines", test_list_active_engines);
965     g_test_add_func ("/ibus/create-input-context-async",
966                      test_create_input_context_async);
967     g_test_add_func ("/ibus/get-engines-by-names", test_get_engines_by_names);
968     g_test_add_func ("/ibus/get-address", test_get_address);
969     g_test_add_func ("/ibus/get-current-input-context",
970                      test_get_current_input_context);
971     g_test_add_func ("/ibus/get-engines", test_get_engines);
972     g_test_add_func ("/ibus/get-global-engine", test_get_global_engine);
973     g_test_add_func ("/ibus/set-preload-engines", test_set_preload_engines);
974     g_test_add_func ("/ibus/async-apis", test_async_apis);
975     g_test_add_func ("/ibus/bus-new-async", test_bus_new_async);
976     g_test_add_func ("/ibus/bus-new-async/list-engines", test_list_engines);
977     g_test_add_func ("/ibus/bus-new-async/list-active-engines", test_list_active_engines);
978     g_test_add_func ("/ibus/bus-new-async/create-input-context-async",
979                      test_create_input_context_async);
980     g_test_add_func ("/ibus/bus-new-async/get-engines-by-names", test_get_engines_by_names);
981     g_test_add_func ("/ibus/bus-new-async/async-apis", test_async_apis);
982 
983     result = g_test_run ();
984     g_object_unref (bus);
985 
986     return result;
987 }
988