2008-06-13 Mark Doffman <mark.doffman@codethink.co.uk>
[platform/core/uifw/at-spi2-atk.git] / tests / apps / test-application.c
1 /*
2  * AT-SPI - Assistive Technology Service Provider Interface
3  * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap)
4  *
5  * Copyright 2008 Codethink Ltd.
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Library General Public
9  * License as published by the Free Software Foundation; either
10  * version 2 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Library General Public License for more details.
16  *
17  * You should have received a copy of the GNU Library General Public
18  * License along with this library; if not, write to the
19  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20  * Boston, MA 02111-1307, USA.
21  */
22
23 /*
24  * Testing AT-SPI requires both a test application and AT client. 
25  * Test applications are built using the Dummy ATK implementation: MyAtk.
26  * This file contains the entry point for all test applications.
27  * Each test is built as a GModule, and this program loads the 
28  * test module, as well as the AT-SPI module. The test module will
29  * provide its own implementation of atk_get_root, and as such provide
30  * all the application state for the test.
31  */
32
33 #include <stdlib.h>
34 #include <glib.h>
35 #include <gmodule.h>
36 #include <atk/atk.h>
37 #include <dbus/dbus.h>
38
39 /* The test module, GModule containing interface for an atk-test */
40 static GModule *test_module;
41 static gpointer test_module_get_root;
42 static gpointer test_module_next;
43 static gpointer test_module_finished;
44
45 static DBusConnection *dbus_bus;
46 static GMainLoop *mainloop;
47
48 /* Test module interface */
49 /*************************/
50
51 typedef AtkObject *(*TestModuleGetRoot) (void);
52
53 /* Calls into the test module to get the root atk object */
54 static AtkObject *
55 get_root(void)
56 {
57   return ((TestModuleGetRoot) test_module_get_root)();
58 }
59
60 typedef void (*VoidVoid) (void);
61
62 /* Called to move to next stage of test.*/
63 static void
64 next(void)
65 {
66   ((VoidVoid) test_module_next)();
67 }
68
69
70 /*************************/
71
72 /* The AtkUtil class is called to find the root accessible and to deal
73  * with events. Its an incomplete class, its v-table needs to be filled in.
74  */
75 static void
76 setup_atk_util(void)
77 {
78   AtkUtilClass *klass;
79
80   klass = g_type_class_ref(ATK_TYPE_UTIL);
81   klass->get_root = get_root;
82   g_type_class_unref(klass);
83 }
84
85 typedef void (*GtkModuleInit) (int *argc, char **argv[]);
86
87 /* AT-SPI is a gtk module that must be loaded and initialized */
88 static void
89 load_atspi_module(const char *path, int *argc, char **argv[])
90 {
91   GModule *bridge;
92   gpointer init;
93
94   bridge = g_module_open(path, G_MODULE_BIND_LOCAL|G_MODULE_BIND_LAZY);
95   if (!bridge)
96     g_error("Couldn't load atk-bridge module : %s\n", path);
97
98   if (!g_module_symbol(bridge, "gtk_module_init", &init))
99     g_error("Couldn't load symbol \"gtk_module_init\"\n");
100
101   ((GtkModuleInit) init)(argc, argv);
102 }
103
104 typedef void (*TestModuleInit) (gchar *path);
105
106 static void
107 load_test_module(const char *path, const char *tdpath)
108 {
109   gpointer init;
110
111   test_module = g_module_open(path, G_MODULE_BIND_LOCAL|G_MODULE_BIND_LAZY);
112   if (!test_module)
113     g_error("Couldn't load test module : %s\n", path);
114
115   if (!g_module_symbol(test_module, "test_init", &init))
116     g_error("Couldn't load symbol \"test_init\"\n");
117
118   if (!g_module_symbol(test_module, "test_get_root", &test_module_get_root))
119     g_error("Couldn't load symbol \"test_get_root\"\n");
120
121   if (!g_module_symbol(test_module, "test_next", &test_module_next))
122     g_error("Couldn't load symbol \"test_next\"\n");
123
124   if (!g_module_symbol(test_module, "test_finished", &test_module_finished))
125     g_error("Couldn't load symbol \"test_finished\"\n");
126
127   ((TestModuleInit) init)((gchar *)tdpath);
128 }
129
130 static const char* introspection_string = 
131 "<node name=\"/org/codethink/atspi/test\">"
132 "       <interface name=\"org.codethink.atspi.test\">"
133 "               <method name=\"next\"/>"
134 "               <signal name=\"started\"/>"
135 "       </interface>"
136 "</node>";
137
138 static DBusHandlerResult
139 message_handler (DBusConnection *bus, DBusMessage *message, void *user_data)
140 {
141   const char *iface = dbus_message_get_interface (message);
142   const char *member = dbus_message_get_member (message);
143   DBusHandlerResult result = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
144   gboolean exit = FALSE;
145
146   DBusMessage *reply = NULL;
147
148   g_print("\nRecieved test interface message\n");
149
150   g_return_val_if_fail(iface != NULL, DBUS_HANDLER_RESULT_NOT_YET_HANDLED);
151   
152   if (!strcmp(iface, "org.codethink.atspi.test"))
153     {
154       if (!strcmp(member, "next"))
155         {
156           next();
157           reply = dbus_message_new_method_return (message);
158           g_assert(reply != NULL);
159           result = DBUS_HANDLER_RESULT_HANDLED;
160         }
161
162       if (!strcmp(member, "finished"))
163         {
164           ((VoidVoid) test_module_finished)();
165           reply = dbus_message_new_method_return (message);
166           g_assert(reply != NULL);
167           result = DBUS_HANDLER_RESULT_HANDLED;
168           exit = TRUE;
169         }
170     }
171
172   if (!strcmp(iface, "org.freedesktop.DBus.Introspectable"))
173     {
174       if (!strcmp(member, "Introspect"))
175         {
176           reply = dbus_message_new_method_return (message);
177           g_assert(reply != NULL);
178           dbus_message_append_args(reply, DBUS_TYPE_STRING, &introspection_string,
179                                    DBUS_TYPE_INVALID);
180           result = DBUS_HANDLER_RESULT_HANDLED;
181         }
182     }
183
184   if (reply)
185     {
186       dbus_connection_send (bus, reply, NULL);
187       dbus_message_unref (reply);
188     }
189
190   if (exit == TRUE)
191     {
192       dbus_connection_flush(bus);
193       dbus_connection_unref(bus);
194       g_main_loop_quit(mainloop);
195       abort();
196     }
197   return result;
198 }
199
200 static DBusObjectPathVTable test_vtable =
201 {
202   NULL,
203   &message_handler,
204   NULL, NULL, NULL, NULL
205 };
206
207 static void
208 init_dbus_interface(void)
209 {
210   DBusError error;
211
212   dbus_error_init(&error);
213   dbus_bus = dbus_bus_get(DBUS_BUS_SESSION, &error);
214   g_print("\nUnique D-Bus name is: %s\n", dbus_bus_get_unique_name(dbus_bus));
215
216   if (!dbus_bus)
217     g_error("Couldn't get the session bus - %s\n", error.message);
218
219   g_assert(dbus_connection_register_object_path(dbus_bus,
220                                                 "/org/codethink/atspi/test",
221                                                 &test_vtable,
222                                                 NULL));
223
224   dbus_connection_setup_with_g_main(dbus_bus, g_main_context_default());
225 }
226
227 static void
228 send_started_signal(void)
229 {
230   DBusMessage* sig;
231   DBusMessageIter args;
232
233   sig = dbus_message_new_signal("/org/codethink/atspi/test", "org.codethink.atspi.test", "started");
234   g_assert(sig != NULL);
235   if (!dbus_connection_send(dbus_bus, sig, NULL))
236     g_error("Out of memory");
237   dbus_connection_flush(dbus_bus);
238   dbus_message_unref(sig);
239 }
240
241 /*Command line data*/
242 static gchar *tmodule_path = NULL;
243 static gchar *amodule_path = NULL;
244 static gchar *tdata_path = NULL;
245
246 static GOptionEntry optentries[] = 
247 {
248   {"test-module", 0, 0, G_OPTION_ARG_STRING, &tmodule_path, "Module containing test scenario", NULL},
249   {"test-atspi-library", 0, 0, G_OPTION_ARG_STRING, &amodule_path, "Gtk module with atk-atspi adaptor", NULL},
250   {"test-data-directory", 0, 0, G_OPTION_ARG_STRING, &tdata_path, "Path to directory of test data", NULL},
251   {NULL}
252 };
253
254 /* main
255  * 
256  * Entry point for all test applications.
257  */
258 main(int argc, char *argv[])
259 {
260   GOptionContext *opt;
261   GError *err = NULL;
262
263   /*Parse command options*/
264   opt = g_option_context_new(NULL);
265   g_option_context_add_main_entries(opt, optentries, NULL);
266   g_option_context_set_ignore_unknown_options(opt, TRUE);
267   
268   if (!g_option_context_parse(opt, &argc, &argv, &err))
269       g_error("Option parsing failed: %s\n", err->message);
270
271   if (tmodule_path == NULL)
272       g_error("No test module provided");
273   if (amodule_path == NULL)
274       g_error("No atspi module provided");
275
276   g_type_init();
277
278   setup_atk_util();
279   load_test_module(tmodule_path, tdata_path);
280   load_atspi_module(amodule_path, &argc, &argv);
281   init_dbus_interface();
282   send_started_signal();
283
284   mainloop = g_main_loop_new (NULL, FALSE);
285   g_main_loop_run (mainloop);
286
287   return 0;
288 }