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