stktest: Templatize GetInkey related agent methods
[platform/upstream/ofono.git] / tools / stktest.c
1 /*
2  *
3  *  oFono - Open Source Telephony
4  *
5  *  Copyright (C) 2008-2011  Intel Corporation. All rights reserved.
6  *
7  *  This program is free software; you can redistribute it and/or modify
8  *  it under the terms of the GNU General Public License version 2 as
9  *  published by the Free Software Foundation.
10  *
11  *  This program is distributed in the hope that it will be useful,
12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *  GNU General Public License for more details.
15  *
16  *  You should have received a copy of the GNU General Public License
17  *  along with this program; if not, write to the Free Software
18  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
19  *
20  */
21
22 #ifdef HAVE_CONFIG_H
23 #include <config.h>
24 #endif
25
26 #include <stdio.h>
27 #include <errno.h>
28 #include <fcntl.h>
29 #include <unistd.h>
30 #include <stdlib.h>
31 #include <string.h>
32 #include <signal.h>
33 #include <netinet/in.h>
34 #include <arpa/inet.h>
35
36 #include <gdbus.h>
37 #include <gatchat/gatserver.h>
38
39 #include "unit/stk-test-data.h"
40
41 #define OFONO_SERVICE   "org.ofono"
42 #define STKTEST_PATH    "/stktest"
43 #define STKTEST_ERROR   "org.ofono.stktest.Error"
44 #define OFONO_ERROR     "org.ofono.Error"
45 #define OFONO_MANAGER_INTERFACE         OFONO_SERVICE ".Manager"
46 #define OFONO_MODEM_INTERFACE           OFONO_SERVICE ".Modem"
47 #define OFONO_STK_INTERFACE             OFONO_SERVICE ".SimToolkit"
48 #define OFONO_STKAGENT_INTERFACE        OFONO_SERVICE ".SimToolkitAgent"
49
50 #define LISTEN_PORT     12765
51
52 enum test_state {
53         TEST_STATE_POWERING_UP = 1,
54         TEST_STATE_REGISTERING_AGENT,
55         TEST_STATE_RUNNING,
56         TEST_STATE_POWERING_DOWN,
57 };
58
59 enum test_result {
60         TEST_RESULT_NOT_RUN = 0,
61         TEST_RESULT_PASSED,
62         TEST_RESULT_FAILED
63 };
64
65 typedef DBusMessage *(*display_text_cb_t)(DBusMessage *msg, const char *text,
66                                                 unsigned char icon_id,
67                                                 gboolean urgent);
68 typedef DBusMessage *(*get_inkey_cb_t)(DBusMessage *msg, const char *alpha,
69                                                 unsigned char icon_id);
70 typedef void (*terminal_response_func)(const unsigned char *pdu,
71                                         unsigned int len);
72
73 struct test {
74         char *name;
75         char *method;
76         unsigned char *req_pdu;
77         unsigned int req_len;
78         unsigned char *rsp_pdu;
79         unsigned int rsp_len;
80         void *agent_func;
81         terminal_response_func tr_func;
82         enum test_result result;
83 };
84
85 static GMainLoop *main_loop = NULL;
86 static volatile sig_atomic_t __terminated = 0;
87 static GList *tests = NULL;
88 static GList *cur_test = NULL;
89
90 /* DBus related */
91 static DBusConnection *conn;
92 static gboolean ofono_running = FALSE;
93 static guint modem_changed_watch;
94 static enum test_state state;
95 static DBusMessage *pending = NULL;
96
97 /* Emulator setup */
98 static guint server_watch;
99 static GAtServer *emulator;
100
101 /* Emulated modem state variables */
102 static int modem_mode = 0;
103
104 void __stktest_test_next();
105 void __stktest_test_finish(gboolean successful);
106 static gboolean create_tcp(void);
107
108 #define STKTEST_AGENT_ASSERT(expr)                                      \
109         do {                                                            \
110                 if (!(expr)) {                                          \
111                         g_printerr("Assertion Failed %s:%d %s\n",       \
112                                         __FILE__, __LINE__, #expr);     \
113                         __stktest_test_finish(FALSE);                   \
114                         return stktest_error_failed(msg);               \
115                 }                                                       \
116         } while (0)
117
118 #define STKTEST_RESPONSE_ASSERT(expect_pdu, expect_pdu_len,             \
119                                 got_pdu, got_pdu_len)                   \
120         do {                                                            \
121                 if ((expect_pdu_len) != (got_pdu_len)) {                \
122                         g_printerr("Assertion Failed %s:%d"             \
123                                         " Wrong response len"           \
124                                         " want: %d, got: %d\n",         \
125                                         __FILE__, __LINE__,             \
126                                         expect_pdu_len, got_pdu_len);   \
127                         __stktest_test_finish(FALSE);                   \
128                         return;                                         \
129                 }                                                       \
130                                                                         \
131                 if (memcmp(expect_pdu, got_pdu, expect_pdu_len) != 0) { \
132                         g_printerr("Assertion Failed %s:%d"             \
133                                         "Wrong response\n",             \
134                                         __FILE__, __LINE__);            \
135                         __stktest_test_finish(FALSE);                   \
136                         return;                                         \
137                 }                                                       \
138         } while (0)
139
140 static const char *to_hex(const unsigned char *data, unsigned int len)
141 {
142         static char buf[512+1];
143         unsigned int i;
144
145         for (i = 0; i < len; i++)
146                 sprintf(buf + i * 2, "%02hhX", data[i]);
147
148         buf[i*2] = '\0';
149
150         return buf;
151 }
152
153 static void send_proactive_command(const unsigned char *pdu, unsigned int len)
154 {
155         char buf[1024];
156
157         sprintf(buf, "+CUSATP: %s", to_hex(pdu, len));
158         g_at_server_send_unsolicited(emulator, buf);
159 }
160
161 static DBusMessage *stktest_error_invalid_args(DBusMessage *msg)
162 {
163         return g_dbus_create_error(msg, STKTEST_ERROR ".InvalidArguments",
164                                         "Invalid arguments provided");
165 }
166
167 static DBusMessage *stktest_error_failed(DBusMessage *msg)
168 {
169         return g_dbus_create_error(msg, STKTEST_ERROR ".Failed",
170                                         "Operation failed");
171 }
172
173 static DBusMessage *stktest_error_end_session(DBusMessage *msg)
174 {
175         return g_dbus_create_error(msg, OFONO_ERROR ".EndSession",
176                                         "End Session Request");
177 }
178
179 static DBusMessage *stktest_error_go_back(DBusMessage *msg)
180 {
181         return g_dbus_create_error(msg, OFONO_ERROR ".GoBack",
182                                         "Go Back Request");
183 }
184
185 static DBusMessage *stktest_error_busy(DBusMessage *msg)
186 {
187         return g_dbus_create_error(msg, OFONO_ERROR ".Busy",
188                                         "UI Busy");
189 }
190
191 static DBusMessage *agent_release(DBusConnection *conn, DBusMessage *msg,
192                                         void *data)
193 {
194         g_print("Got Release\n");
195
196         if (pending) {
197                 dbus_message_unref(pending);
198                 pending = NULL;
199         }
200
201         return dbus_message_new_method_return(msg);
202 }
203
204 static DBusMessage *agent_cancel(DBusConnection *conn, DBusMessage *msg,
205                                         void *data)
206 {
207         if (pending) {
208                 dbus_message_unref(pending);
209                 pending = NULL;
210         }
211
212         return NULL;
213 }
214
215 static DBusMessage *agent_display_text(DBusConnection *conn, DBusMessage *msg,
216                                         void *data)
217 {
218         const char *text;
219         unsigned char icon_id;
220         dbus_bool_t urgent;
221         struct test *test;
222         display_text_cb_t func;
223         DBusMessage *reply;
224
225         if (dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &text,
226                                                 DBUS_TYPE_BYTE, &icon_id,
227                                                 DBUS_TYPE_BOOLEAN, &urgent,
228                                                 DBUS_TYPE_INVALID) == FALSE)
229                 return stktest_error_invalid_args(msg);
230
231         if (cur_test == NULL)
232                 return stktest_error_failed(msg);
233
234         test = cur_test->data;
235         func = test->agent_func;
236
237         if (strcmp(test->method, "DisplayText")) {
238                 g_printerr("Wrong method called!\n");
239                 __stktest_test_finish(FALSE);
240                 return stktest_error_failed(msg);
241         }
242
243         if (func == NULL) {
244                 g_printerr("DisplayText not expected to be called");
245                 __stktest_test_finish(FALSE);
246                 return stktest_error_failed(msg);
247         }
248
249         reply = func(msg, text, icon_id, urgent);
250         if (reply == NULL)
251                 pending = dbus_message_ref(msg);
252
253         return reply;
254 }
255
256 #define GET_INKEY_TEMPLATE(func, method_name)                           \
257 static DBusMessage *func(DBusConnection *conn, DBusMessage *msg,        \
258                                 void *data)                             \
259 {                                                                       \
260         const char *alpha;                                              \
261         unsigned char icon_id;                                          \
262         struct test *test;                                              \
263         get_inkey_cb_t func;                                            \
264         DBusMessage *reply;                                             \
265                                                                         \
266         if (dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &alpha,  \
267                                         DBUS_TYPE_BYTE, &icon_id,       \
268                                         DBUS_TYPE_INVALID) == FALSE)    \
269                 return stktest_error_invalid_args(msg);                 \
270                                                                         \
271         if (cur_test == NULL)                                           \
272                 return stktest_error_failed(msg);                       \
273                                                                         \
274         test = cur_test->data;                                          \
275         func = test->agent_func;                                        \
276                                                                         \
277         if (strcmp(test->method, method_name)) {                        \
278                 g_printerr("Wrong method called!\n");                   \
279                 __stktest_test_finish(FALSE);                           \
280                 return stktest_error_failed(msg);                       \
281         }                                                               \
282                                                                         \
283         if (func == NULL) {                                             \
284                 g_printerr(method_name " not expected to be called");   \
285                 __stktest_test_finish(FALSE);                           \
286                 return stktest_error_failed(msg);                       \
287         }                                                               \
288                                                                         \
289         reply = func(msg, alpha, icon_id);                              \
290         if (reply == NULL)                                              \
291                 pending = dbus_message_ref(msg);                        \
292                                                                         \
293         return reply;                                                   \
294 }                                                                       \
295
296 GET_INKEY_TEMPLATE(agent_request_key, "RequestKey")
297 GET_INKEY_TEMPLATE(agent_request_digit, "RequestDigit")
298
299 static void server_debug(const char *str, void *data)
300 {
301         g_print("%s: %s\n", (char *) data, str);
302 }
303
304 static void cgmi_cb(GAtServer *server, GAtServerRequestType type,
305                         GAtResult *cmd, gpointer user)
306 {
307         switch (type) {
308         case G_AT_SERVER_REQUEST_TYPE_COMMAND_ONLY:
309                 g_at_server_send_info(server, "oFono", TRUE);
310                 g_at_server_send_final(server, G_AT_SERVER_RESULT_OK);
311                 break;
312         case G_AT_SERVER_REQUEST_TYPE_SUPPORT:
313                 g_at_server_send_final(server, G_AT_SERVER_RESULT_OK);
314                 break;
315         default:
316                 g_at_server_send_final(server, G_AT_SERVER_RESULT_ERROR);
317         };
318 }
319
320 static void cgmm_cb(GAtServer *server, GAtServerRequestType type,
321                         GAtResult *cmd, gpointer user)
322 {
323         switch (type) {
324         case G_AT_SERVER_REQUEST_TYPE_COMMAND_ONLY:
325                 g_at_server_send_info(server, "oFono pre-1.0", TRUE);
326                 g_at_server_send_final(server, G_AT_SERVER_RESULT_OK);
327                 break;
328         case G_AT_SERVER_REQUEST_TYPE_SUPPORT:
329                 g_at_server_send_final(server, G_AT_SERVER_RESULT_OK);
330                 break;
331         default:
332                 g_at_server_send_final(server, G_AT_SERVER_RESULT_ERROR);
333         };
334 }
335
336 static void cgmr_cb(GAtServer *server, GAtServerRequestType type,
337                         GAtResult *cmd, gpointer user)
338 {
339         char buf[256];
340
341         switch (type) {
342         case G_AT_SERVER_REQUEST_TYPE_COMMAND_ONLY:
343                 sprintf(buf, "oFono pre-1.0 version: %s", VERSION);
344                 g_at_server_send_info(server, buf, TRUE);
345                 g_at_server_send_final(server, G_AT_SERVER_RESULT_OK);
346                 break;
347         case G_AT_SERVER_REQUEST_TYPE_SUPPORT:
348                 g_at_server_send_final(server, G_AT_SERVER_RESULT_OK);
349                 break;
350         default:
351                 g_at_server_send_final(server, G_AT_SERVER_RESULT_ERROR);
352         };
353 }
354
355 static void cgsn_cb(GAtServer *server, GAtServerRequestType type,
356                         GAtResult *cmd, gpointer user)
357 {
358         switch (type) {
359         case G_AT_SERVER_REQUEST_TYPE_COMMAND_ONLY:
360                 g_at_server_send_info(server, "123456789", TRUE);
361                 g_at_server_send_final(server, G_AT_SERVER_RESULT_OK);
362                 break;
363         case G_AT_SERVER_REQUEST_TYPE_SUPPORT:
364                 g_at_server_send_final(server, G_AT_SERVER_RESULT_OK);
365                 break;
366         default:
367                 g_at_server_send_final(server, G_AT_SERVER_RESULT_ERROR);
368         };
369 }
370
371 static gboolean send_ok(gpointer user)
372 {
373         GAtServer *server = user;
374
375         g_at_server_send_final(server, G_AT_SERVER_RESULT_OK);
376
377         return FALSE;
378 }
379
380 static void cfun_cb(GAtServer *server, GAtServerRequestType type,
381                         GAtResult *cmd, gpointer user)
382 {
383         char buf[12];
384
385         switch (type) {
386         case G_AT_SERVER_REQUEST_TYPE_SUPPORT:
387                 g_at_server_send_info(server, "+CFUN: (0-1,4)", TRUE);
388                 g_at_server_send_final(server, G_AT_SERVER_RESULT_OK);
389                 break;
390         case G_AT_SERVER_REQUEST_TYPE_QUERY:
391                 snprintf(buf, sizeof(buf), "+CFUN: %d", modem_mode);
392                 g_at_server_send_info(server, buf, TRUE);
393                 g_at_server_send_final(server, G_AT_SERVER_RESULT_OK);
394                 break;
395         case G_AT_SERVER_REQUEST_TYPE_SET:
396         {
397                 GAtResultIter iter;
398                 int mode;
399
400                 g_at_result_iter_init(&iter, cmd);
401                 g_at_result_iter_next(&iter, "");
402
403                 if (g_at_result_iter_next_number(&iter, &mode) == FALSE)
404                         goto error;
405
406                 if (mode != 0 && mode != 1)
407                         goto error;
408
409                 if (modem_mode == mode) {
410                         g_at_server_send_final(server, G_AT_SERVER_RESULT_OK);
411                         break;
412                 }
413
414                 modem_mode = mode;
415                 g_timeout_add_seconds(1, send_ok, server);
416                 break;
417         }
418         default:
419                 goto error;
420         };
421
422         return;
423
424 error:
425         g_at_server_send_final(server, G_AT_SERVER_RESULT_ERROR);
426 }
427
428 static void cusatt_cb(GAtServer *server, GAtServerRequestType type,
429                         GAtResult *cmd, gpointer user)
430 {
431         switch (type) {
432         case G_AT_SERVER_REQUEST_TYPE_SUPPORT:
433                 g_at_server_send_final(server, G_AT_SERVER_RESULT_OK);
434                 break;
435         case G_AT_SERVER_REQUEST_TYPE_QUERY:
436                 g_at_server_send_ext_final(server, "+CME ERROR: 4");
437                 break;
438         case G_AT_SERVER_REQUEST_TYPE_SET:
439         {
440                 GAtResultIter iter;
441                 const unsigned char *pdu;
442                 int len;
443                 struct test *test;
444                 terminal_response_func func;
445
446                 g_at_result_iter_init(&iter, cmd);
447                 g_at_result_iter_next(&iter, "");
448
449                 if (g_at_result_iter_next_hexstring(&iter, &pdu, &len) == FALSE)
450                         goto error;
451
452                 if (cur_test == NULL)
453                         goto error;
454
455                 g_at_server_send_final(server, G_AT_SERVER_RESULT_OK);
456
457                 test = cur_test->data;
458                 func = test->tr_func;
459                 func(pdu, len);
460                 break;
461         }
462         default:
463                 goto error;
464         };
465
466         return;
467
468 error:
469         g_at_server_send_final(server, G_AT_SERVER_RESULT_ERROR);
470 }
471
472 static void listen_again(gpointer user_data)
473 {
474         g_at_server_unref(emulator);
475         emulator = NULL;
476
477         if (create_tcp() == TRUE)
478                 return;
479
480         g_print("Error listening to socket\n");
481         g_main_loop_quit(main_loop);
482 }
483
484 static void setup_emulator(GAtServer *server)
485 {
486         g_at_server_set_debug(server, server_debug, "Server");
487
488         g_at_server_register(server, "+CGMI", cgmi_cb, NULL, NULL);
489         g_at_server_register(server, "+CGMM", cgmm_cb, NULL, NULL);
490         g_at_server_register(server, "+CGMR", cgmr_cb, NULL, NULL);
491         g_at_server_register(server, "+CGSN", cgsn_cb, NULL, NULL);
492         g_at_server_register(server, "+CFUN", cfun_cb, NULL, NULL);
493         g_at_server_register(server, "+CUSATT", cusatt_cb, NULL, NULL);
494
495         g_at_server_set_disconnect_function(server, listen_again, NULL);
496 }
497
498 static gboolean on_socket_connected(GIOChannel *chan, GIOCondition cond,
499                                                         gpointer user)
500 {
501         struct sockaddr saddr;
502         unsigned int len = sizeof(saddr);
503         int fd;
504         GIOChannel *client_io = NULL;
505
506         if (cond != G_IO_IN)
507                 goto error;
508
509         fd = accept(g_io_channel_unix_get_fd(chan), &saddr, &len);
510         if (fd == -1)
511                 goto error;
512
513         client_io = g_io_channel_unix_new(fd);
514
515         emulator = g_at_server_new(client_io);
516         g_at_server_set_echo(emulator, FALSE);
517         g_io_channel_unref(client_io);
518
519         if (emulator == NULL)
520                 goto error;
521
522         setup_emulator(emulator);
523
524 error:
525         server_watch = 0;
526         return FALSE;
527 }
528
529 static gboolean create_tcp(void)
530 {
531         struct sockaddr_in addr;
532         int sk;
533         int reuseaddr = 1;
534         GIOChannel *server_io;
535
536         sk = socket(PF_INET, SOCK_STREAM, 0);
537         if (sk < 0) {
538                 g_print("Can't create tcp/ip socket: %s (%d)\n",
539                                                 strerror(errno), errno);
540                 return FALSE;
541         }
542
543         memset(&addr, 0, sizeof(addr));
544
545         addr.sin_family = AF_INET;
546         addr.sin_addr.s_addr = INADDR_ANY;
547         addr.sin_port = htons(LISTEN_PORT);
548
549         setsockopt(sk, SOL_SOCKET, SO_REUSEADDR, &reuseaddr, sizeof(reuseaddr));
550         if (bind(sk, (struct sockaddr *) &addr, sizeof(struct sockaddr)) < 0) {
551                 g_print("Can't bind socket: %s (%d)", strerror(errno), errno);
552                 close(sk);
553                 return FALSE;
554         }
555
556         if (listen(sk, 1) < 0) {
557                 g_print("Can't listen on socket: %s (%d)",
558                                                 strerror(errno), errno);
559                 close(sk);
560                 return FALSE;
561         }
562
563         g_print("new tcp is created at tcp port %d\n", LISTEN_PORT);
564
565         server_io = g_io_channel_unix_new(sk);
566         g_io_channel_set_close_on_unref(server_io, TRUE);
567
568         server_watch = g_io_add_watch_full(server_io,
569                                 G_PRIORITY_DEFAULT,
570                                 G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
571                                 on_socket_connected, NULL, NULL);
572
573         g_io_channel_unref(server_io);
574
575         return TRUE;
576 }
577
578 static gboolean has_stk_interface(DBusMessageIter *iter)
579 {
580         DBusMessageIter entry;
581
582         dbus_message_iter_recurse(iter, &entry);
583
584         while (dbus_message_iter_get_arg_type(&entry) == DBUS_TYPE_STRING) {
585                 const char *interface;
586
587                 dbus_message_iter_get_basic(&entry, &interface);
588
589                 if (g_str_equal(interface, OFONO_STK_INTERFACE) == TRUE)
590                         return TRUE;
591
592                 dbus_message_iter_next(&entry);
593         }
594
595         return FALSE;
596 }
597
598 static int send_with_reply(const char *path, const char *interface,
599                                 const char *method, DBusPendingCall **call,
600                                 DBusPendingCallNotifyFunction cb,
601                                 void *user_data, DBusFreeFunction free_func,
602                                 int timeout, int type, ...)
603 {
604         DBusMessage *msg;
605         DBusPendingCall *c;
606         va_list args;
607         int err;
608
609         msg = dbus_message_new_method_call(OFONO_SERVICE, path,
610                                                 interface, method);
611         if (msg == NULL) {
612                 g_printerr("Unable to allocate new D-Bus %s message\n", method);
613                 err = -ENOMEM;
614                 goto fail;
615         }
616
617         va_start(args, type);
618
619         if (!dbus_message_append_args_valist(msg, type, args)) {
620                 va_end(args);
621                 err = -EIO;
622                 goto fail;
623         }
624
625         va_end(args);
626
627         if (timeout > 0)
628                 timeout *= 1000;
629
630         if (!dbus_connection_send_with_reply(conn, msg, &c, timeout)) {
631                 g_printerr("Sending %s failed\n", method);
632                 err = -EIO;
633                 goto fail;
634         }
635
636         if (call != NULL)
637                 *call = c;
638
639         dbus_pending_call_set_notify(c, cb, user_data, free_func);
640         dbus_pending_call_unref(c);
641
642         dbus_message_unref(msg);
643
644         return 0;
645
646 fail:
647         if (free_func && user_data)
648                 free_func(user_data);
649
650         if (msg)
651                 dbus_message_unref(msg);
652
653         return err;
654 }
655
656 static void set_property_reply(DBusPendingCall *call, void *user_data)
657 {
658         DBusMessage *reply = dbus_pending_call_steal_reply(call);
659         DBusError err;
660
661         dbus_error_init(&err);
662
663         if (dbus_set_error_from_message(&err, reply) == TRUE) {
664                 g_printerr("%s: %s\n", err.name, err.message);
665                 dbus_error_free(&err);
666         }
667
668         dbus_message_unref(reply);
669 }
670
671 static int set_property(const char *path, const char *interface,
672                         const char *key, int type, const void *val,
673                         DBusPendingCallNotifyFunction notify,
674                         gpointer user_data,
675                         DBusFreeFunction destroy)
676 {
677         DBusMessage *msg;
678         DBusMessageIter iter, value;
679         DBusPendingCall *call;
680         const char *signature;
681
682         msg = dbus_message_new_method_call(OFONO_SERVICE, path, interface,
683                                                 "SetProperty");
684         if (msg == NULL)
685                 return -ENOMEM;
686
687         dbus_message_set_auto_start(msg, FALSE);
688
689         dbus_message_iter_init_append(msg, &iter);
690
691         dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &key);
692
693         switch (type) {
694         case DBUS_TYPE_BOOLEAN:
695                 signature = DBUS_TYPE_BOOLEAN_AS_STRING;
696                 break;
697         default:
698                 dbus_message_unref(msg);
699                 return -EINVAL;
700         }
701
702         dbus_message_iter_open_container(&iter, DBUS_TYPE_VARIANT,
703                                                         signature, &value);
704         dbus_message_iter_append_basic(&value, type, val);
705         dbus_message_iter_close_container(&iter, &value);
706
707         if (dbus_connection_send_with_reply(conn, msg, &call, -1) == FALSE) {
708                 dbus_message_unref(msg);
709                 return -EIO;
710         }
711
712         dbus_message_unref(msg);
713
714         if (call == NULL)
715                 return -EINVAL;
716
717         dbus_pending_call_set_notify(call, notify, user_data, destroy);
718
719         dbus_pending_call_unref(call);
720
721         return 0;
722 }
723
724 static void register_agent_reply(DBusPendingCall *call, void *user_data)
725 {
726         DBusMessage *reply = dbus_pending_call_steal_reply(call);
727         DBusError err;
728         struct test *test;
729
730         dbus_error_init(&err);
731
732         if (dbus_set_error_from_message(&err, reply) == TRUE) {
733                 g_printerr("%s: %s\n", err.name, err.message);
734                 dbus_error_free(&err);
735         }
736
737         dbus_message_unref(reply);
738
739         state = TEST_STATE_RUNNING;
740         test = cur_test->data;
741         send_proactive_command(test->req_pdu, test->req_len);
742 }
743
744 static void register_agent()
745 {
746         const char *path = "/default";
747         int status;
748
749         g_print("Gained STK interface, registering agent...\n");
750
751         status = send_with_reply(STKTEST_PATH, OFONO_STK_INTERFACE,
752                                         "RegisterAgent", NULL,
753                                         register_agent_reply, NULL, NULL, 1,
754                                         DBUS_TYPE_OBJECT_PATH, &path,
755                                         DBUS_TYPE_INVALID);
756
757         if (status < 0) {
758                 g_printerr("Unable to register agent with oFono\n");
759                 g_main_loop_quit(main_loop);
760                 return;
761         }
762
763         state = TEST_STATE_REGISTERING_AGENT;
764 }
765
766 static gboolean modem_changed(DBusConnection *conn,
767                                 DBusMessage *msg, void *user_data)
768 {
769         DBusMessageIter iter, value;
770         const char *path, *key;
771         gboolean has_stk;
772
773         if (dbus_message_iter_init(msg, &iter) == FALSE)
774                 return TRUE;
775
776         path = dbus_message_get_path(msg);
777
778         if (g_str_equal(STKTEST_PATH, path) == FALSE)
779                 return TRUE;
780
781         dbus_message_iter_get_basic(&iter, &key);
782
783         dbus_message_iter_next(&iter);
784         dbus_message_iter_recurse(&iter, &value);
785
786         if (g_str_equal(key, "Interfaces") == FALSE)
787                 return TRUE;
788
789         has_stk = has_stk_interface(&value);
790
791         switch (state) {
792         case TEST_STATE_POWERING_UP:
793                 if (has_stk)
794                         register_agent();
795                 break;
796         case TEST_STATE_REGISTERING_AGENT:
797         case TEST_STATE_RUNNING:
798                 if (has_stk == FALSE)
799                         g_printerr("Unexpectedly lost STK interface\n");
800                 /* Fall through */
801         case TEST_STATE_POWERING_DOWN:
802                 break;
803         };
804
805         return TRUE;
806 }
807
808 static void powerup(void)
809 {
810         dbus_bool_t powered = TRUE;
811
812         state = TEST_STATE_POWERING_UP;
813         set_property(STKTEST_PATH, OFONO_MODEM_INTERFACE, "Powered",
814                         DBUS_TYPE_BOOLEAN, &powered,
815                         set_property_reply, NULL, NULL);
816 }
817
818 static void get_modems_reply(DBusPendingCall *call, void *user_data)
819 {
820         DBusMessage *reply = dbus_pending_call_steal_reply(call);
821         DBusMessageIter iter, list;
822         DBusError err;
823         gboolean found = FALSE;
824
825         dbus_error_init(&err);
826
827         if (dbus_set_error_from_message(&err, reply) == TRUE) {
828                 g_printerr("%s: %s\n", err.name, err.message);
829                 dbus_error_free(&err);
830                 goto done;
831         }
832
833         if (dbus_message_has_signature(reply, "a(oa{sv})") == FALSE)
834                 goto done;
835
836         if (dbus_message_iter_init(reply, &iter) == FALSE)
837                 goto done;
838
839         dbus_message_iter_recurse(&iter, &list);
840
841         while (dbus_message_iter_get_arg_type(&list) == DBUS_TYPE_STRUCT) {
842                 DBusMessageIter entry;
843                 const char *path;
844
845                 dbus_message_iter_recurse(&list, &entry);
846                 dbus_message_iter_get_basic(&entry, &path);
847
848                 if (g_str_equal(path, STKTEST_PATH))
849                         found = TRUE;
850
851                 dbus_message_iter_next(&list);
852         }
853
854 done:
855         dbus_message_unref(reply);
856
857         if (found == FALSE) {
858                 g_printerr("STK Test modem not found\n");
859                 g_main_loop_quit(main_loop);
860                 return;
861         }
862
863         g_print("Test modem found\n");
864
865         modem_changed_watch = g_dbus_add_signal_watch(conn, OFONO_SERVICE,
866                                                         STKTEST_PATH,
867                                                         OFONO_MODEM_INTERFACE,
868                                                         "PropertyChanged",
869                                                         modem_changed,
870                                                         NULL, NULL);
871
872         if (create_tcp() == FALSE) {
873                 g_printerr("Unable to listen on modem emulator socket\n");
874                 g_main_loop_quit(main_loop);
875         }
876
877         __stktest_test_next();
878 }
879
880 static int get_modems(DBusConnection *conn)
881 {
882         DBusMessage *msg;
883         DBusPendingCall *call;
884
885         msg = dbus_message_new_method_call(OFONO_SERVICE, "/",
886                                         OFONO_MANAGER_INTERFACE, "GetModems");
887         if (msg == NULL)
888                 return -ENOMEM;
889
890         dbus_message_set_auto_start(msg, FALSE);
891
892         g_print("getting modems\n");
893
894         if (dbus_connection_send_with_reply(conn, msg, &call, -1) == FALSE) {
895                 dbus_message_unref(msg);
896                 return -EIO;
897         }
898
899         dbus_message_unref(msg);
900
901         if (call == NULL)
902                 return -EINVAL;
903
904         dbus_pending_call_set_notify(call, get_modems_reply, conn, NULL);
905
906         dbus_pending_call_unref(call);
907
908         return 0;
909 }
910
911 static const GDBusMethodTable agent_methods[] = {
912         { GDBUS_METHOD("Release", NULL, NULL, agent_release) },
913         { GDBUS_ASYNC_METHOD("DisplayText",
914                 GDBUS_ARGS({ "text", "s" }, { "icon_id", "y" },
915                                 { "urgent", "b" }), NULL,
916                                 agent_display_text) },
917         { GDBUS_ASYNC_METHOD("RequestDigit",
918                 GDBUS_ARGS({ "alpha", "s" }, { "icon_id", "y" }),
919                 GDBUS_ARGS({ "digit", "s" }),
920                                 agent_request_digit) },
921         { GDBUS_ASYNC_METHOD("RequestKey",
922                 GDBUS_ARGS({ "alpha", "s" }, { "icon_id", "y" }),
923                 GDBUS_ARGS({ "key", "s" }),
924                                 agent_request_key) },
925         { GDBUS_NOREPLY_METHOD("Cancel", NULL, NULL, agent_cancel) },
926         { },
927 };
928
929 static void ofono_connect(DBusConnection *conn, void *user_data)
930 {
931         g_print("starting telephony interface\n");
932
933         if (!g_dbus_register_interface(conn, "/default",
934                                         OFONO_STKAGENT_INTERFACE,
935                                         agent_methods, NULL, NULL,
936                                         NULL, NULL)) {
937                 g_printerr("Unable to register local agent");
938                 g_main_loop_quit(main_loop);
939         }
940
941         ofono_running = TRUE;
942         get_modems(conn);
943 }
944
945 static void ofono_disconnect(DBusConnection *conn, void *user_data)
946 {
947         g_print("stopping telephony interface\n");
948
949         g_dbus_unregister_interface(conn, "/default", OFONO_STKAGENT_INTERFACE);
950
951         ofono_running = FALSE;
952
953         g_dbus_remove_watch(conn, modem_changed_watch);
954         modem_changed_watch = 0;
955
956         if (server_watch) {
957                 g_source_remove(server_watch);
958                 server_watch = 0;
959         }
960
961         g_at_server_unref(emulator);
962         emulator = NULL;
963 }
964
965 static void sig_term(int sig)
966 {
967         if (__terminated > 0)
968                 return;
969
970         __terminated = 1;
971
972         g_print("Terminating\n");
973
974         g_main_loop_quit(main_loop);
975 }
976
977 static void disconnect_callback(DBusConnection *conn, void *user_data)
978 {
979         g_printerr("D-Bus disconnect\n");
980
981         g_main_loop_quit(main_loop);
982 }
983
984 static gboolean end_session_and_finish(gpointer user_data)
985 {
986         g_at_server_send_unsolicited(emulator, "+CUSATEND");
987         __stktest_test_finish(TRUE);
988
989         return FALSE;
990 }
991
992 static void expect_response_and_finish(const unsigned char *pdu,
993                                         unsigned int len)
994 {
995         struct test *test = cur_test->data;
996
997         STKTEST_RESPONSE_ASSERT(test->rsp_pdu, test->rsp_len, pdu, len);
998
999         g_idle_add(end_session_and_finish, NULL);
1000 }
1001
1002 static void expect_response(const unsigned char *pdu, unsigned int len)
1003 {
1004         struct test *test = cur_test->data;
1005
1006         STKTEST_RESPONSE_ASSERT(test->rsp_pdu, test->rsp_len, pdu, len);
1007 }
1008
1009 static gboolean poweroff_not_canceled_after_3(gpointer user_data)
1010 {
1011         __stktest_test_finish(pending != NULL);
1012         return FALSE;
1013 }
1014
1015 static gboolean end_session_and_not_canceled_after_3(gpointer user_data)
1016 {
1017         g_at_server_send_unsolicited(emulator, "+CUSATEND");
1018         g_timeout_add_seconds(3, poweroff_not_canceled_after_3, NULL);
1019
1020         return FALSE;
1021 }
1022
1023 static void expect_response_and_not_canceled_after_3(const unsigned char *pdu,
1024                                                         unsigned int len)
1025 {
1026         struct test *test = cur_test->data;
1027
1028         STKTEST_RESPONSE_ASSERT(test->rsp_pdu, test->rsp_len, pdu, len);
1029
1030         g_idle_add(end_session_and_not_canceled_after_3, NULL);
1031 }
1032
1033 static gboolean poweroff_and_canceled_after_21(gpointer user_data)
1034 {
1035         __stktest_test_finish(pending == NULL);
1036         return FALSE;
1037 }
1038
1039 static gboolean end_session_and_canceled_after_21(gpointer user_data)
1040 {
1041         g_at_server_send_unsolicited(emulator, "+CUSATEND");
1042         g_timeout_add_seconds(21, poweroff_and_canceled_after_21, NULL);
1043
1044         return FALSE;
1045 }
1046
1047 static void expect_response_and_canceled_after_21(const unsigned char *pdu,
1048                                                         unsigned int len)
1049 {
1050         struct test *test = cur_test->data;
1051
1052         STKTEST_RESPONSE_ASSERT(test->rsp_pdu, test->rsp_len, pdu, len);
1053
1054         g_idle_add(end_session_and_canceled_after_21, NULL);
1055 }
1056
1057 static DBusMessage *test_display_text_11(DBusMessage *msg,
1058                                                 const char *text,
1059                                                 unsigned char icon_id,
1060                                                 gboolean urgent)
1061 {
1062         STKTEST_AGENT_ASSERT(g_str_equal(text, "Toolkit Test 1"));
1063         STKTEST_AGENT_ASSERT(icon_id == 0);
1064         STKTEST_AGENT_ASSERT(urgent == FALSE);
1065
1066         return dbus_message_new_method_return(msg);
1067 }
1068
1069 static DBusMessage *test_display_text_12(DBusMessage *msg,
1070                                                 const char *text,
1071                                                 unsigned char icon_id,
1072                                                 gboolean urgent)
1073 {
1074         STKTEST_AGENT_ASSERT(g_str_equal(text, "Toolkit Test 1"));
1075         STKTEST_AGENT_ASSERT(icon_id == 0);
1076         STKTEST_AGENT_ASSERT(urgent == FALSE);
1077
1078         return stktest_error_busy(msg);
1079 }
1080
1081 static DBusMessage *test_display_text_13(DBusMessage *msg,
1082                                                 const char *text,
1083                                                 unsigned char icon_id,
1084                                                 gboolean urgent)
1085 {
1086         STKTEST_AGENT_ASSERT(g_str_equal(text, "Toolkit Test 2"));
1087         STKTEST_AGENT_ASSERT(icon_id == 0);
1088         STKTEST_AGENT_ASSERT(urgent == TRUE);
1089
1090         return dbus_message_new_method_return(msg);
1091 }
1092
1093 static DBusMessage *test_display_text_14(DBusMessage *msg,
1094                                                 const char *text,
1095                                                 unsigned char icon_id,
1096                                                 gboolean urgent)
1097 {
1098         STKTEST_AGENT_ASSERT(g_str_equal(text, "Toolkit Test 3"));
1099         STKTEST_AGENT_ASSERT(icon_id == 0);
1100         STKTEST_AGENT_ASSERT(urgent == FALSE);
1101
1102         return dbus_message_new_method_return(msg);
1103 }
1104
1105 static DBusMessage *test_display_text_15(DBusMessage *msg,
1106                                                 const char *text,
1107                                                 unsigned char icon_id,
1108                                                 gboolean urgent)
1109 {
1110         STKTEST_AGENT_ASSERT(g_str_equal(text, "Toolkit Test 4"));
1111         STKTEST_AGENT_ASSERT(icon_id == 0);
1112         STKTEST_AGENT_ASSERT(urgent == FALSE);
1113
1114         return NULL;
1115 }
1116
1117 static DBusMessage *test_display_text_16(DBusMessage *msg,
1118                                                 const char *text,
1119                                                 unsigned char icon_id,
1120                                                 gboolean urgent)
1121 {
1122         STKTEST_AGENT_ASSERT(g_str_equal(text, "This command instructs the ME"
1123                                                 " to display a text message. "
1124                                                 "It allows the SIM to define "
1125                                                 "the priority of that message, "
1126                                                 "and the text string format. "
1127                                                 "Two types of prio"));
1128         STKTEST_AGENT_ASSERT(icon_id == 0);
1129         STKTEST_AGENT_ASSERT(urgent == FALSE);
1130
1131         return dbus_message_new_method_return(msg);
1132 }
1133
1134 static DBusMessage *test_display_text_17(DBusMessage *msg,
1135                                                 const char *text,
1136                                                 unsigned char icon_id,
1137                                                 gboolean urgent)
1138 {
1139         /* oFono gives rich text formatting in HTML */
1140         STKTEST_AGENT_ASSERT(g_str_equal(text, "&lt;GO-BACKWARDS&gt;"));
1141         STKTEST_AGENT_ASSERT(icon_id == 0);
1142         STKTEST_AGENT_ASSERT(urgent == FALSE);
1143
1144         return stktest_error_go_back(msg);
1145 }
1146
1147 static DBusMessage *test_display_text_18(DBusMessage *msg,
1148                                                 const char *text,
1149                                                 unsigned char icon_id,
1150                                                 gboolean urgent)
1151 {
1152         /* oFono gives rich text formatting in HTML */
1153         STKTEST_AGENT_ASSERT(g_str_equal(text, "&lt;ABORT&gt;"));
1154         STKTEST_AGENT_ASSERT(icon_id == 0);
1155         STKTEST_AGENT_ASSERT(urgent == FALSE);
1156
1157         return stktest_error_end_session(msg);
1158 }
1159
1160 static DBusMessage *test_display_text_21(DBusMessage *msg,
1161                                                 const char *text,
1162                                                 unsigned char icon_id,
1163                                                 gboolean urgent)
1164 {
1165         STKTEST_AGENT_ASSERT(g_str_equal(text, "&lt;TIME-OUT&gt;"));
1166         STKTEST_AGENT_ASSERT(icon_id == 0);
1167         STKTEST_AGENT_ASSERT(urgent == FALSE);
1168
1169         return NULL;
1170 }
1171
1172 static DBusMessage *test_display_text_31(DBusMessage *msg,
1173                                                 const char *text,
1174                                                 unsigned char icon_id,
1175                                                 gboolean urgent)
1176 {
1177         static const char *expected = "This command instructs the ME to display"
1178                                         " a text message, and/or an icon "
1179                                         "(see 6.5.4). It allows the "
1180                                         "SIM to define the priority of that "
1181                                         "message, and the text string format. "
1182                                         "Two types of priority are defined:- "
1183                                         "display normal priority text and/";
1184         STKTEST_AGENT_ASSERT(g_str_equal(text, expected));
1185         STKTEST_AGENT_ASSERT(icon_id == 0);
1186         STKTEST_AGENT_ASSERT(urgent == FALSE);
1187
1188         return dbus_message_new_method_return(msg);
1189 }
1190
1191 static DBusMessage *test_display_text_41(DBusMessage *msg,
1192                                                 const char *text,
1193                                                 unsigned char icon_id,
1194                                                 gboolean urgent)
1195 {
1196         STKTEST_AGENT_ASSERT(g_str_equal(text, "Toolkit Test 1"));
1197         STKTEST_AGENT_ASSERT(icon_id == 0);
1198         STKTEST_AGENT_ASSERT(urgent == FALSE);
1199
1200         return NULL;
1201 }
1202
1203 static DBusMessage *test_display_text_42(DBusMessage *msg,
1204                                                 const char *text,
1205                                                 unsigned char icon_id,
1206                                                 gboolean urgent)
1207 {
1208         STKTEST_AGENT_ASSERT(g_str_equal(text, "Toolkit Test 2"));
1209         STKTEST_AGENT_ASSERT(icon_id == 0);
1210         STKTEST_AGENT_ASSERT(urgent == FALSE);
1211
1212         return NULL;
1213 }
1214
1215 static gboolean user_response(gpointer user_data)
1216 {
1217         if (pending == NULL) {
1218                 __stktest_test_finish(FALSE);
1219                 return FALSE;
1220         }
1221
1222         g_dbus_send_reply(conn, pending, DBUS_TYPE_INVALID);
1223         dbus_message_unref(pending);
1224         pending = NULL;
1225
1226         __stktest_test_finish(TRUE);
1227
1228         return FALSE;
1229 }
1230
1231 static DBusMessage *test_display_text_43(DBusMessage *msg,
1232                                                 const char *text,
1233                                                 unsigned char icon_id,
1234                                                 gboolean urgent)
1235 {
1236         STKTEST_AGENT_ASSERT(g_str_equal(text, "Toolkit Test 3"));
1237         STKTEST_AGENT_ASSERT(icon_id == 0);
1238         STKTEST_AGENT_ASSERT(urgent == FALSE);
1239
1240         g_timeout_add_seconds(3, user_response, NULL);
1241         return NULL;
1242 }
1243
1244 static DBusMessage *test_display_text_51(DBusMessage *msg,
1245                                                 const char *text,
1246                                                 unsigned char icon_id,
1247                                                 gboolean urgent)
1248 {
1249         STKTEST_AGENT_ASSERT(g_str_equal(text, "Basic Icon"));
1250         STKTEST_AGENT_ASSERT(icon_id == 1);
1251         STKTEST_AGENT_ASSERT(urgent == FALSE);
1252
1253         return dbus_message_new_method_return(msg);
1254 }
1255
1256 static DBusMessage *test_display_text_52(DBusMessage *msg,
1257                                                 const char *text,
1258                                                 unsigned char icon_id,
1259                                                 gboolean urgent)
1260 {
1261         STKTEST_AGENT_ASSERT(g_str_equal(text, "Colour Icon"));
1262         STKTEST_AGENT_ASSERT(icon_id == 2);
1263         STKTEST_AGENT_ASSERT(urgent == FALSE);
1264
1265         return dbus_message_new_method_return(msg);
1266 }
1267
1268 static DBusMessage *test_display_text_53(DBusMessage *msg,
1269                                                 const char *text,
1270                                                 unsigned char icon_id,
1271                                                 gboolean urgent)
1272 {
1273         STKTEST_AGENT_ASSERT(g_str_equal(text, "Basic Icon"));
1274         STKTEST_AGENT_ASSERT(icon_id == 1);
1275         STKTEST_AGENT_ASSERT(urgent == FALSE);
1276
1277         return dbus_message_new_method_return(msg);
1278 }
1279
1280 static DBusMessage *test_display_text_61(DBusMessage *msg,
1281                                                 const char *text,
1282                                                 unsigned char icon_id,
1283                                                 gboolean urgent)
1284 {
1285         STKTEST_AGENT_ASSERT(g_str_equal(text, "ЗДРАВСТВУЙТЕ"));
1286         STKTEST_AGENT_ASSERT(icon_id == 0);
1287         STKTEST_AGENT_ASSERT(urgent == FALSE);
1288
1289         return dbus_message_new_method_return(msg);
1290 }
1291
1292 static DBusMessage *test_display_text_71(DBusMessage *msg,
1293                                                 const char *text,
1294                                                 unsigned char icon_id,
1295                                                 gboolean urgent)
1296 {
1297         STKTEST_AGENT_ASSERT(g_str_equal(text, "10 Second"));
1298         STKTEST_AGENT_ASSERT(icon_id == 0);
1299         STKTEST_AGENT_ASSERT(urgent == FALSE);
1300
1301         return NULL;
1302 }
1303
1304 static DBusMessage *test_display_text_81(DBusMessage *msg,
1305                                                 const char *text,
1306                                                 unsigned char icon_id,
1307                                                 gboolean urgent)
1308 {
1309         const char *expect =
1310                 "<div style=\"text-align: left;\"><span style=\"color: "
1311                 "#347235;background-color: #FFFF00;\">Text Attribute 1</span>"
1312                 "</div>";
1313
1314         STKTEST_AGENT_ASSERT(g_str_equal(text, expect));
1315         STKTEST_AGENT_ASSERT(icon_id == 0);
1316         STKTEST_AGENT_ASSERT(urgent == FALSE);
1317
1318         return dbus_message_new_method_return(msg);
1319 }
1320
1321 static DBusMessage *test_display_text_82(DBusMessage *msg,
1322                                                 const char *text,
1323                                                 unsigned char icon_id,
1324                                                 gboolean urgent)
1325 {
1326         const char *expect =
1327                 "<div style=\"text-align: center;\"><span style=\"color: "
1328                 "#347235;background-color: #FFFF00;\">Text Attribute 1</span>"
1329                 "</div>";
1330
1331         STKTEST_AGENT_ASSERT(g_str_equal(text, expect));
1332         STKTEST_AGENT_ASSERT(icon_id == 0);
1333         STKTEST_AGENT_ASSERT(urgent == FALSE);
1334
1335         return dbus_message_new_method_return(msg);
1336 }
1337
1338 static DBusMessage *test_display_text_83(DBusMessage *msg,
1339                                                 const char *text,
1340                                                 unsigned char icon_id,
1341                                                 gboolean urgent)
1342 {
1343         const char *expect =
1344                 "<div style=\"text-align: right;\"><span style=\"color: "
1345                 "#347235;background-color: #FFFF00;\">Text Attribute 1</span>"
1346                 "</div>";
1347
1348         STKTEST_AGENT_ASSERT(g_str_equal(text, expect));
1349         STKTEST_AGENT_ASSERT(icon_id == 0);
1350         STKTEST_AGENT_ASSERT(urgent == FALSE);
1351
1352         return dbus_message_new_method_return(msg);
1353 }
1354
1355 static DBusMessage *test_display_text_84(DBusMessage *msg,
1356                                                 const char *text,
1357                                                 unsigned char icon_id,
1358                                                 gboolean urgent)
1359 {
1360         const char *expect =
1361                 "<div style=\"text-align: left;\"><span style=\"font-size: "
1362                 "big;color: #347235;background-color: #FFFF00;\">"
1363                 "Text Attribute 1</span></div>";
1364
1365         STKTEST_AGENT_ASSERT(g_str_equal(text, expect));
1366         STKTEST_AGENT_ASSERT(icon_id == 0);
1367         STKTEST_AGENT_ASSERT(urgent == FALSE);
1368
1369         return dbus_message_new_method_return(msg);
1370 }
1371
1372 static DBusMessage *test_display_text_85(DBusMessage *msg,
1373                                                 const char *text,
1374                                                 unsigned char icon_id,
1375                                                 gboolean urgent)
1376 {
1377         const char *expect =
1378                 "<div style=\"text-align: left;\"><span style=\"font-size: "
1379                 "small;color: #347235;background-color: #FFFF00;\">"
1380                 "Text Attribute 1</span></div>";
1381
1382         STKTEST_AGENT_ASSERT(g_str_equal(text, expect));
1383         STKTEST_AGENT_ASSERT(icon_id == 0);
1384         STKTEST_AGENT_ASSERT(urgent == FALSE);
1385
1386         return dbus_message_new_method_return(msg);
1387 }
1388
1389 static DBusMessage *test_display_text_86(DBusMessage *msg,
1390                                                 const char *text,
1391                                                 unsigned char icon_id,
1392                                                 gboolean urgent)
1393 {
1394         const char *expect =
1395                 "<div style=\"text-align: left;\"><span style=\"font-weight: "
1396                 "bold;color: #347235;background-color: #FFFF00;\">"
1397                 "Text Attribute 1</span></div>";
1398
1399         STKTEST_AGENT_ASSERT(g_str_equal(text, expect));
1400         STKTEST_AGENT_ASSERT(icon_id == 0);
1401         STKTEST_AGENT_ASSERT(urgent == FALSE);
1402
1403         return dbus_message_new_method_return(msg);
1404 }
1405
1406 static DBusMessage *test_display_text_87(DBusMessage *msg,
1407                                                 const char *text,
1408                                                 unsigned char icon_id,
1409                                                 gboolean urgent)
1410 {
1411         const char *expect =
1412                 "<div style=\"text-align: left;\"><span style=\"font-style: "
1413                 "italic;color: #347235;background-color: #FFFF00;\">"
1414                 "Text Attribute 1</span></div>";
1415
1416         STKTEST_AGENT_ASSERT(g_str_equal(text, expect));
1417         STKTEST_AGENT_ASSERT(icon_id == 0);
1418         STKTEST_AGENT_ASSERT(urgent == FALSE);
1419
1420         return dbus_message_new_method_return(msg);
1421 }
1422
1423 static DBusMessage *test_display_text_88(DBusMessage *msg,
1424                                                 const char *text,
1425                                                 unsigned char icon_id,
1426                                                 gboolean urgent)
1427 {
1428         const char *expect =
1429                 "<div style=\"text-align: left;\"><span style=\""
1430                 "text-decoration: underline;color: #347235;"
1431                 "background-color: #FFFF00;\">Text Attribute 1</span></div>";
1432
1433         STKTEST_AGENT_ASSERT(g_str_equal(text, expect));
1434         STKTEST_AGENT_ASSERT(icon_id == 0);
1435         STKTEST_AGENT_ASSERT(urgent == FALSE);
1436
1437         return dbus_message_new_method_return(msg);
1438 }
1439
1440 static DBusMessage *test_display_text_89(DBusMessage *msg,
1441                                                 const char *text,
1442                                                 unsigned char icon_id,
1443                                                 gboolean urgent)
1444 {
1445         const char *expect =
1446                 "<div style=\"text-align: left;\"><span style=\""
1447                 "text-decoration: line-through;color: #347235;"
1448                 "background-color: #FFFF00;\">Text Attribute 1</span></div>";
1449
1450         STKTEST_AGENT_ASSERT(g_str_equal(text, expect));
1451         STKTEST_AGENT_ASSERT(icon_id == 0);
1452         STKTEST_AGENT_ASSERT(urgent == FALSE);
1453
1454         return dbus_message_new_method_return(msg);
1455 }
1456
1457 static DBusMessage *test_display_text_810(DBusMessage *msg,
1458                                                 const char *text,
1459                                                 unsigned char icon_id,
1460                                                 gboolean urgent)
1461 {
1462         const char *expect =
1463                 "<div style=\"text-align: left;\"><span style=\"color: "
1464                 "#347235;background-color: #FFFF00;\">Text Attribute 1</span>"
1465                 "</div>";
1466
1467         STKTEST_AGENT_ASSERT(g_str_equal(text, expect));
1468         STKTEST_AGENT_ASSERT(icon_id == 0);
1469         STKTEST_AGENT_ASSERT(urgent == FALSE);
1470
1471         return dbus_message_new_method_return(msg);
1472 }
1473
1474 static DBusMessage *test_display_text_91(DBusMessage *msg,
1475                                                 const char *text,
1476                                                 unsigned char icon_id,
1477                                                 gboolean urgent)
1478 {
1479         const char *expect = "你好";
1480
1481         STKTEST_AGENT_ASSERT(g_str_equal(text, expect));
1482         STKTEST_AGENT_ASSERT(icon_id == 0);
1483         STKTEST_AGENT_ASSERT(urgent == FALSE);
1484
1485         return dbus_message_new_method_return(msg);
1486 }
1487
1488 static DBusMessage *test_display_text_101(DBusMessage *msg,
1489                                                 const char *text,
1490                                                 unsigned char icon_id,
1491                                                 gboolean urgent)
1492 {
1493         const char *expect = "80ル";
1494
1495         STKTEST_AGENT_ASSERT(g_str_equal(text, expect));
1496         STKTEST_AGENT_ASSERT(icon_id == 0);
1497         STKTEST_AGENT_ASSERT(urgent == FALSE);
1498
1499         return dbus_message_new_method_return(msg);
1500 }
1501
1502 static DBusMessage *test_get_inkey_11(DBusMessage *msg,
1503                                         const char *alpha,
1504                                         unsigned char icon_id)
1505 {
1506         DBusMessage *reply;
1507         const char *ret = "+";
1508
1509         STKTEST_AGENT_ASSERT(g_str_equal(alpha, "Enter \"+\""));
1510         STKTEST_AGENT_ASSERT(icon_id == 0);
1511
1512         reply = dbus_message_new_method_return(msg);
1513         dbus_message_append_args(reply, DBUS_TYPE_STRING, &ret,
1514                                         DBUS_TYPE_INVALID);
1515
1516         return reply;
1517 }
1518
1519 static DBusMessage *test_get_inkey_12(DBusMessage *msg,
1520                                         const char *alpha,
1521                                         unsigned char icon_id)
1522 {
1523         DBusMessage *reply;
1524         const char *ret = "0";
1525
1526         STKTEST_AGENT_ASSERT(g_str_equal(alpha, "Enter \"0\""));
1527         STKTEST_AGENT_ASSERT(icon_id == 0);
1528
1529         reply = dbus_message_new_method_return(msg);
1530         dbus_message_append_args(reply, DBUS_TYPE_STRING, &ret,
1531                                         DBUS_TYPE_INVALID);
1532
1533         return reply;
1534 }
1535
1536 static DBusMessage *test_get_inkey_13(DBusMessage *msg,
1537                                         const char *alpha,
1538                                         unsigned char icon_id)
1539 {
1540         STKTEST_AGENT_ASSERT(g_str_equal(alpha, "&lt;GO-BACKWARDS&gt;"));
1541         STKTEST_AGENT_ASSERT(icon_id == 0);
1542
1543         return stktest_error_go_back(msg);
1544 }
1545
1546 static DBusMessage *test_get_inkey_14(DBusMessage *msg,
1547                                         const char *alpha,
1548                                         unsigned char icon_id)
1549 {
1550         STKTEST_AGENT_ASSERT(g_str_equal(alpha, "&lt;ABORT&gt;"));
1551         STKTEST_AGENT_ASSERT(icon_id == 0);
1552
1553         return stktest_error_end_session(msg);
1554 }
1555
1556 static DBusMessage *test_get_inkey_15(DBusMessage *msg,
1557                                         const char *alpha,
1558                                         unsigned char icon_id)
1559 {
1560         DBusMessage *reply;
1561         const char *ret = "q";
1562
1563         STKTEST_AGENT_ASSERT(g_str_equal(alpha, "Enter \"q\""));
1564         STKTEST_AGENT_ASSERT(icon_id == 0);
1565
1566         reply = dbus_message_new_method_return(msg);
1567         dbus_message_append_args(reply, DBUS_TYPE_STRING, &ret,
1568                                         DBUS_TYPE_INVALID);
1569
1570         return reply;
1571 }
1572
1573 static DBusMessage *test_get_inkey_16(DBusMessage *msg,
1574                                         const char *alpha,
1575                                         unsigned char icon_id)
1576 {
1577         DBusMessage *reply;
1578         const char *ret = "x";
1579         const char *expected =
1580                 "Enter \"x\". This command instructs the ME to display text, "
1581                 "and to expect the user to enter a single character. Any "
1582                 "response entered by the user shall be passed t";
1583
1584         STKTEST_AGENT_ASSERT(g_str_equal(alpha, expected));
1585         STKTEST_AGENT_ASSERT(icon_id == 0);
1586
1587         reply = dbus_message_new_method_return(msg);
1588         dbus_message_append_args(reply, DBUS_TYPE_STRING, &ret,
1589                                         DBUS_TYPE_INVALID);
1590
1591         return reply;
1592 }
1593
1594 static DBusMessage *test_get_inkey_21(DBusMessage *msg,
1595                                         const char *text, unsigned char icon_id)
1596 {
1597         STKTEST_AGENT_ASSERT(g_str_equal(text, "&lt;TIME-OUT&gt;"));
1598         STKTEST_AGENT_ASSERT(icon_id == 0);
1599
1600         return NULL;
1601 }
1602
1603 static DBusMessage *test_get_inkey_31(DBusMessage *msg,
1604                                         const char *alpha,
1605                                         unsigned char icon_id)
1606 {
1607         DBusMessage *reply;
1608         const char *ret = "+";
1609
1610         STKTEST_AGENT_ASSERT(g_str_equal(alpha, "ЗДРАВСТВУЙТЕ"));
1611         STKTEST_AGENT_ASSERT(icon_id == 0);
1612
1613         reply = dbus_message_new_method_return(msg);
1614         dbus_message_append_args(reply, DBUS_TYPE_STRING, &ret,
1615                                         DBUS_TYPE_INVALID);
1616
1617         return reply;
1618 }
1619
1620 static DBusMessage *test_get_inkey_32(DBusMessage *msg,
1621                                         const char *alpha,
1622                                         unsigned char icon_id)
1623 {
1624         DBusMessage *reply;
1625         const char *ret = "+";
1626         const char *expect = "ЗДРАВСТВУЙТЕЗДРАВСТВУЙТЕ"
1627                                 "ЗДРАВСТВУЙТЕЗДРАВСТВУЙТЕ"
1628                                 "ЗДРАВСТВУЙТЕЗДРАВСТВУЙ";
1629
1630         STKTEST_AGENT_ASSERT(g_str_equal(alpha, expect));
1631         STKTEST_AGENT_ASSERT(icon_id == 0);
1632
1633         reply = dbus_message_new_method_return(msg);
1634         dbus_message_append_args(reply, DBUS_TYPE_STRING, &ret,
1635                                         DBUS_TYPE_INVALID);
1636
1637         return reply;
1638 }
1639
1640 static DBusMessage *test_get_inkey_41(DBusMessage *msg,
1641                                         const char *alpha,
1642                                         unsigned char icon_id)
1643 {
1644         DBusMessage *reply;
1645         const char *ret = "Д";
1646
1647         STKTEST_AGENT_ASSERT(g_str_equal(alpha, "Enter"));
1648         STKTEST_AGENT_ASSERT(icon_id == 0);
1649
1650         reply = dbus_message_new_method_return(msg);
1651         dbus_message_append_args(reply, DBUS_TYPE_STRING, &ret,
1652                                         DBUS_TYPE_INVALID);
1653
1654         return reply;
1655 }
1656
1657 static void power_down_reply(DBusPendingCall *call, void *user_data)
1658 {
1659         __stktest_test_next();
1660 }
1661
1662 void __stktest_test_finish(gboolean successful)
1663 {
1664         struct test *test = cur_test->data;
1665         dbus_bool_t powered = FALSE;
1666
1667         test->result = successful ? TEST_RESULT_PASSED : TEST_RESULT_FAILED;
1668
1669         state = TEST_STATE_POWERING_DOWN;
1670         set_property(STKTEST_PATH, OFONO_MODEM_INTERFACE, "Powered",
1671                         DBUS_TYPE_BOOLEAN, &powered,
1672                         power_down_reply, NULL, NULL);
1673 }
1674
1675 void __stktest_test_next()
1676 {
1677         if (cur_test == NULL)
1678                 cur_test = tests;
1679         else
1680                 cur_test = cur_test->next;
1681
1682         if (cur_test == NULL) {
1683                 g_main_loop_quit(main_loop);
1684                 return;
1685         }
1686
1687         powerup();
1688 }
1689
1690 static void stktest_add_test(const char *name, const char *method,
1691                                 const unsigned char *req, unsigned int req_len,
1692                                 const unsigned char *rsp, unsigned int rsp_len,
1693                                 void *agent_func,
1694                                 terminal_response_func tr_func)
1695 {
1696         struct test *test = g_new0(struct test, 1);
1697
1698         test->name = g_strdup(name);
1699         test->method = g_strdup(method);
1700         test->req_pdu = g_memdup(req, req_len);
1701         test->req_len = req_len;
1702         test->rsp_pdu = g_memdup(rsp, rsp_len);
1703         test->rsp_len = rsp_len;
1704         test->agent_func = agent_func;
1705         test->tr_func = tr_func;
1706
1707         tests = g_list_append(tests, test);
1708 }
1709
1710 static void __stktest_test_init(void)
1711 {
1712         stktest_add_test("Display Text 1.1", "DisplayText",
1713                                 display_text_111, sizeof(display_text_111),
1714                                 display_text_response_111,
1715                                 sizeof(display_text_response_111),
1716                                 test_display_text_11,
1717                                 expect_response_and_finish);
1718         stktest_add_test("Display Text 1.2", "DisplayText",
1719                                 display_text_111, sizeof(display_text_111),
1720                                 display_text_response_121,
1721                                 sizeof(display_text_response_121),
1722                                 test_display_text_12,
1723                                 expect_response_and_finish);
1724         stktest_add_test("Display Text 1.3", "DisplayText",
1725                                 display_text_131, sizeof(display_text_131),
1726                                 display_text_response_131,
1727                                 sizeof(display_text_response_131),
1728                                 test_display_text_13,
1729                                 expect_response_and_finish);
1730         stktest_add_test("Display Text 1.4", "DisplayText",
1731                                 display_text_141, sizeof(display_text_141),
1732                                 display_text_response_141,
1733                                 sizeof(display_text_response_141),
1734                                 test_display_text_14,
1735                                 expect_response_and_finish);
1736         stktest_add_test("Display Text 1.5", "DisplayText",
1737                                 display_text_151, sizeof(display_text_151),
1738                                 display_text_response_151,
1739                                 sizeof(display_text_response_151),
1740                                 test_display_text_15,
1741                                 expect_response_and_finish);
1742         stktest_add_test("Display Text 1.6", "DisplayText",
1743                                 display_text_161, sizeof(display_text_161),
1744                                 display_text_response_161,
1745                                 sizeof(display_text_response_161),
1746                                 test_display_text_16,
1747                                 expect_response_and_finish);
1748         stktest_add_test("Display Text 1.7", "DisplayText",
1749                                 display_text_171, sizeof(display_text_171),
1750                                 display_text_response_171,
1751                                 sizeof(display_text_response_171),
1752                                 test_display_text_17,
1753                                 expect_response_and_finish);
1754         stktest_add_test("Display Text 1.8", "DisplayText",
1755                                 display_text_181, sizeof(display_text_181),
1756                                 display_text_response_181,
1757                                 sizeof(display_text_response_181),
1758                                 test_display_text_18,
1759                                 expect_response_and_finish);
1760         stktest_add_test("Display Text 1.9", "DisplayText",
1761                                 display_text_191, sizeof(display_text_191),
1762                                 display_text_response_191,
1763                                 sizeof(display_text_response_191),
1764                                 NULL, expect_response_and_finish);
1765         stktest_add_test("Display Text 2.1", "DisplayText",
1766                                 display_text_211, sizeof(display_text_211),
1767                                 display_text_response_211,
1768                                 sizeof(display_text_response_211),
1769                                 test_display_text_21,
1770                                 expect_response_and_finish);
1771         stktest_add_test("Display Text 3.1", "DisplayText",
1772                                 display_text_311, sizeof(display_text_311),
1773                                 display_text_response_311,
1774                                 sizeof(display_text_response_311),
1775                                 test_display_text_31,
1776                                 expect_response_and_finish);
1777         stktest_add_test("Display Text 4.1", "DisplayText",
1778                                 display_text_411, sizeof(display_text_411),
1779                                 display_text_response_411,
1780                                 sizeof(display_text_response_411),
1781                                 test_display_text_41,
1782                                 expect_response_and_not_canceled_after_3);
1783         stktest_add_test("Display Text 4.2", "DisplayText",
1784                                 display_text_421, sizeof(display_text_421),
1785                                 display_text_response_421,
1786                                 sizeof(display_text_response_421),
1787                                 test_display_text_42,
1788                                 expect_response_and_canceled_after_21);
1789         stktest_add_test("Display Text 4.3", "DisplayText",
1790                                 display_text_431, sizeof(display_text_431),
1791                                 display_text_response_431,
1792                                 sizeof(display_text_response_431),
1793                                 test_display_text_43, expect_response);
1794         stktest_add_test("Display Text 5.1A", "DisplayText",
1795                                 display_text_511, sizeof(display_text_511),
1796                                 display_text_response_511a,
1797                                 sizeof(display_text_response_511a),
1798                                 test_display_text_51,
1799                                 expect_response_and_finish);
1800         stktest_add_test("Display Text 5.2A", "DisplayText",
1801                                 display_text_521, sizeof(display_text_521),
1802                                 display_text_response_521a,
1803                                 sizeof(display_text_response_521a),
1804                                 test_display_text_52,
1805                                 expect_response_and_finish);
1806         stktest_add_test("Display Text 5.3A", "DisplayText",
1807                                 display_text_531, sizeof(display_text_531),
1808                                 display_text_response_531a,
1809                                 sizeof(display_text_response_531a),
1810                                 test_display_text_53,
1811                                 expect_response_and_finish);
1812         stktest_add_test("Display Text 6.1", "DisplayText",
1813                                 display_text_611, sizeof(display_text_611),
1814                                 display_text_response_611,
1815                                 sizeof(display_text_response_611),
1816                                 test_display_text_61,
1817                                 expect_response_and_finish);
1818         stktest_add_test("Display Text 7.1", "DisplayText",
1819                                 display_text_711, sizeof(display_text_711),
1820                                 display_text_response_711,
1821                                 sizeof(display_text_response_711),
1822                                 test_display_text_71,
1823                                 expect_response_and_finish);
1824         /*
1825          * We skip parts where the UI is asked to display simple text to ensure
1826          * that the alignment, font is set up correctly and not 'remembered'
1827          * from a previous state.  oFono does not keep any state of the
1828          * previous commands
1829          */
1830         stktest_add_test("Display Text 8.1", "DisplayText",
1831                                 display_text_811, sizeof(display_text_811),
1832                                 display_text_response_811,
1833                                 sizeof(display_text_response_811),
1834                                 test_display_text_81,
1835                                 expect_response_and_finish);
1836         stktest_add_test("Display Text 8.2", "DisplayText",
1837                                 display_text_821, sizeof(display_text_821),
1838                                 display_text_response_821,
1839                                 sizeof(display_text_response_821),
1840                                 test_display_text_82,
1841                                 expect_response_and_finish);
1842         stktest_add_test("Display Text 8.3", "DisplayText",
1843                                 display_text_831, sizeof(display_text_831),
1844                                 display_text_response_831,
1845                                 sizeof(display_text_response_831),
1846                                 test_display_text_83,
1847                                 expect_response_and_finish);
1848         stktest_add_test("Display Text 8.4", "DisplayText",
1849                                 display_text_841, sizeof(display_text_841),
1850                                 display_text_response_841,
1851                                 sizeof(display_text_response_841),
1852                                 test_display_text_84,
1853                                 expect_response_and_finish);
1854         stktest_add_test("Display Text 8.5", "DisplayText",
1855                                 display_text_851, sizeof(display_text_851),
1856                                 display_text_response_851,
1857                                 sizeof(display_text_response_851),
1858                                 test_display_text_85,
1859                                 expect_response_and_finish);
1860         stktest_add_test("Display Text 8.6", "DisplayText",
1861                                 display_text_861, sizeof(display_text_861),
1862                                 display_text_response_861,
1863                                 sizeof(display_text_response_861),
1864                                 test_display_text_86,
1865                                 expect_response_and_finish);
1866         stktest_add_test("Display Text 8.7", "DisplayText",
1867                                 display_text_871, sizeof(display_text_871),
1868                                 display_text_response_871,
1869                                 sizeof(display_text_response_871),
1870                                 test_display_text_87,
1871                                 expect_response_and_finish);
1872         stktest_add_test("Display Text 8.8", "DisplayText",
1873                                 display_text_881, sizeof(display_text_881),
1874                                 display_text_response_881,
1875                                 sizeof(display_text_response_881),
1876                                 test_display_text_88,
1877                                 expect_response_and_finish);
1878         stktest_add_test("Display Text 8.9", "DisplayText",
1879                                 display_text_891, sizeof(display_text_891),
1880                                 display_text_response_891,
1881                                 sizeof(display_text_response_891),
1882                                 test_display_text_89,
1883                                 expect_response_and_finish);
1884         stktest_add_test("Display Text 8.10", "DisplayText",
1885                                 display_text_8101, sizeof(display_text_8101),
1886                                 display_text_response_8101,
1887                                 sizeof(display_text_response_8101),
1888                                 test_display_text_810,
1889                                 expect_response_and_finish);
1890         stktest_add_test("Display Text 9.1", "DisplayText",
1891                                 display_text_911, sizeof(display_text_911),
1892                                 display_text_response_911,
1893                                 sizeof(display_text_response_911),
1894                                 test_display_text_91,
1895                                 expect_response_and_finish);
1896         stktest_add_test("Display Text 10.1", "DisplayText",
1897                                 display_text_1011, sizeof(display_text_1011),
1898                                 display_text_response_1011,
1899                                 sizeof(display_text_response_1011),
1900                                 test_display_text_101,
1901                                 expect_response_and_finish);
1902         stktest_add_test("Get Inkey 1.1", "RequestDigit",
1903                                 get_inkey_111, sizeof(get_inkey_111),
1904                                 get_inkey_response_111,
1905                                 sizeof(get_inkey_response_111),
1906                                 test_get_inkey_11,
1907                                 expect_response_and_finish);
1908         stktest_add_test("Get Inkey 1.2", "RequestDigit",
1909                                 get_inkey_121, sizeof(get_inkey_121),
1910                                 get_inkey_response_121,
1911                                 sizeof(get_inkey_response_121),
1912                                 test_get_inkey_12,
1913                                 expect_response_and_finish);
1914         stktest_add_test("Get Inkey 1.3", "RequestDigit",
1915                                 get_inkey_131, sizeof(get_inkey_131),
1916                                 get_inkey_response_131,
1917                                 sizeof(get_inkey_response_131),
1918                                 test_get_inkey_13,
1919                                 expect_response_and_finish);
1920         stktest_add_test("Get Inkey 1.4", "RequestDigit",
1921                                 get_inkey_141, sizeof(get_inkey_141),
1922                                 get_inkey_response_141,
1923                                 sizeof(get_inkey_response_141),
1924                                 test_get_inkey_14,
1925                                 expect_response_and_finish);
1926         stktest_add_test("Get Inkey 1.5", "RequestKey",
1927                                 get_inkey_151, sizeof(get_inkey_151),
1928                                 get_inkey_response_151,
1929                                 sizeof(get_inkey_response_151),
1930                                 test_get_inkey_15,
1931                                 expect_response_and_finish);
1932         stktest_add_test("Get Inkey 1.6", "RequestKey",
1933                                 get_inkey_161, sizeof(get_inkey_161),
1934                                 get_inkey_response_161,
1935                                 sizeof(get_inkey_response_161),
1936                                 test_get_inkey_16,
1937                                 expect_response_and_finish);
1938         stktest_add_test("Get Inkey 2.1", "RequestDigit",
1939                                 get_inkey_211, sizeof(get_inkey_211),
1940                                 get_inkey_response_211,
1941                                 sizeof(get_inkey_response_211),
1942                                 test_get_inkey_21,
1943                                 expect_response_and_finish);
1944         stktest_add_test("Get Inkey 3.1", "RequestDigit",
1945                                 get_inkey_311, sizeof(get_inkey_311),
1946                                 get_inkey_response_311,
1947                                 sizeof(get_inkey_response_311),
1948                                 test_get_inkey_31,
1949                                 expect_response_and_finish);
1950         stktest_add_test("Get Inkey 3.2", "RequestDigit",
1951                                 get_inkey_321, sizeof(get_inkey_321),
1952                                 get_inkey_response_321,
1953                                 sizeof(get_inkey_response_321),
1954                                 test_get_inkey_32,
1955                                 expect_response_and_finish);
1956         stktest_add_test("Get Inkey 4.1", "RequestKey",
1957                                 get_inkey_411, sizeof(get_inkey_411),
1958                                 get_inkey_response_411,
1959                                 sizeof(get_inkey_response_411),
1960                                 test_get_inkey_41,
1961                                 expect_response_and_finish);
1962 }
1963
1964 static void test_destroy(gpointer user_data)
1965 {
1966         struct test *test = user_data;
1967
1968         g_free(test->name);
1969         g_free(test->method);
1970         g_free(test->req_pdu);
1971         g_free(test->rsp_pdu);
1972
1973         g_free(test);
1974 }
1975
1976 static void __stktest_test_summarize(void)
1977 {
1978         GList *l;
1979         unsigned int not_run = 0;
1980         unsigned int passed = 0;
1981         unsigned int failed = 0;
1982
1983         g_print("\n\nTest Summary\n");
1984         g_print("============\n");
1985
1986         for (l = tests; l; l = l->next) {
1987                 struct test *test = l->data;
1988
1989                 g_print("%-60s", test->name);
1990
1991                 switch (test->result) {
1992                 case TEST_RESULT_NOT_RUN:
1993                         g_print("Not Run\n");
1994                         not_run += 1;
1995                         break;
1996                 case TEST_RESULT_PASSED:
1997                         g_print("Passed\n");
1998                         passed += 1;
1999                         break;
2000                 case TEST_RESULT_FAILED:
2001                         g_print("Failed\n");
2002                         failed += 1;
2003                 break;
2004                 }
2005         }
2006
2007         g_print("\nTotal: %d, Passed: %d(%.1f%%), Failed: %d, NotRun: %d\n",
2008                         not_run + passed + failed, passed,
2009                         (float) passed * 100 / (not_run + passed + failed),
2010                         failed, not_run);
2011 }
2012
2013 static void __stktest_test_cleanup(void)
2014 {
2015         g_list_free_full(tests, test_destroy);
2016         tests = NULL;
2017         cur_test = NULL;
2018 }
2019
2020 static gboolean option_version = FALSE;
2021
2022 static GOptionEntry options[] = {
2023         { "version", 'v', 0, G_OPTION_ARG_NONE, &option_version,
2024                                 "Show version information and exit" },
2025         { NULL },
2026 };
2027
2028 int main(int argc, char **argv)
2029 {
2030         GOptionContext *context;
2031         GError *error = NULL;
2032         DBusError err;
2033         guint watch;
2034         struct sigaction sa;
2035
2036         context = g_option_context_new(NULL);
2037         g_option_context_add_main_entries(context, options, NULL);
2038
2039         if (g_option_context_parse(context, &argc, &argv, &error) == FALSE) {
2040                 if (error != NULL) {
2041                         g_printerr("%s\n", error->message);
2042                         g_error_free(error);
2043                 } else
2044                         g_printerr("An unknown error occurred\n");
2045                 exit(1);
2046         }
2047
2048         g_option_context_free(context);
2049
2050         if (option_version == TRUE) {
2051                 printf("%s\n", VERSION);
2052                 exit(0);
2053         }
2054
2055         __stktest_test_init();
2056
2057         main_loop = g_main_loop_new(NULL, FALSE);
2058
2059         dbus_error_init(&err);
2060
2061         conn = g_dbus_setup_bus(DBUS_BUS_SYSTEM, NULL, &err);
2062         if (conn == NULL) {
2063                 if (dbus_error_is_set(&err) == TRUE) {
2064                         fprintf(stderr, "%s\n", err.message);
2065                         dbus_error_free(&err);
2066                 } else
2067                         fprintf(stderr, "Can't register with system bus\n");
2068                 exit(1);
2069         }
2070
2071         g_dbus_set_disconnect_function(conn, disconnect_callback, NULL, NULL);
2072
2073         memset(&sa, 0, sizeof(sa));
2074         sa.sa_handler = sig_term;
2075         sigaction(SIGINT, &sa, NULL);
2076         sigaction(SIGTERM, &sa, NULL);
2077
2078         watch = g_dbus_add_service_watch(conn, OFONO_SERVICE,
2079                                 ofono_connect, ofono_disconnect, NULL, NULL);
2080
2081         g_main_loop_run(main_loop);
2082
2083         g_dbus_remove_watch(conn, watch);
2084
2085         if (ofono_running == TRUE)
2086                 ofono_disconnect(conn, NULL);
2087
2088         dbus_connection_unref(conn);
2089
2090         g_main_loop_unref(main_loop);
2091
2092         __stktest_test_summarize();
2093         __stktest_test_cleanup();
2094
2095         return 0;
2096 }