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