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