packaging: Bump to 1.17
[platform/upstream/ofono.git] / unit / test-mux.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 <unistd.h>
27 #include <stdlib.h>
28 #include <string.h>
29 #include <sys/socket.h>
30 #include <netinet/in.h>
31 #include <arpa/inet.h>
32
33 #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
34
35 #include <glib.h>
36 #include <glib/gprintf.h>
37
38 #include "gatmux.h"
39 #include "gsm0710.h"
40
41 static int do_connect(const char *address, unsigned short port)
42 {
43         struct sockaddr_in addr;
44         int sk, err;
45
46         sk = socket(PF_INET, SOCK_STREAM, 0);
47         if (sk < 0)
48                 return sk;
49
50         memset(&addr, 0, sizeof(addr));
51         addr.sin_family = AF_INET;
52         addr.sin_addr.s_addr = inet_addr(address);
53         addr.sin_port = htons(port);
54
55         err = connect(sk, (struct sockaddr *) &addr, sizeof(addr));
56         if (err < 0) {
57                 close(sk);
58                 return err;
59         }
60
61         return sk;
62 }
63
64 static GMainLoop *mainloop;
65 static GAtMux *mux;
66
67 static gboolean cleanup_callback(gpointer data)
68 {
69         g_at_mux_unref(mux);
70
71         g_main_loop_quit(mainloop);
72
73         return FALSE;
74 }
75
76 static gboolean chat_cleanup(gpointer data)
77 {
78         GAtChat *chat = data;
79
80         g_at_chat_unref(chat);
81
82         return FALSE;
83 }
84
85 static void chat_callback(gboolean ok, GAtResult *result, gpointer user_data)
86 {
87         GAtResultIter iter;
88
89         g_at_result_iter_init(&iter, result);
90
91         g_print("chat: callback [ok %d]\n", ok);
92
93         g_print("%s\n", g_at_result_final_response(result));
94
95         g_idle_add(chat_cleanup, user_data);
96 }
97
98 static void mux_debug(const char *str, void *data)
99 {
100         g_print("%s: %s\n", (char *) data, str);
101 }
102
103 static void mux_setup(GAtMux *m, gpointer data)
104 {
105         GAtChat *chat = data;
106         GIOChannel *io;
107         GAtSyntax *syntax;
108
109         mux = m;
110
111         g_print("mux_setup: %p\n", mux);
112
113         if (mux == NULL) {
114                 g_at_chat_unref(chat);
115                 g_main_loop_quit(mainloop);
116                 return;
117         }
118
119         g_at_mux_start(mux);
120
121         io = g_at_mux_create_channel(mux);
122         syntax = g_at_syntax_new_gsm_permissive();
123         chat = g_at_chat_new(io, syntax);
124         g_at_syntax_unref(syntax);
125         g_io_channel_unref(io);
126
127         g_at_chat_set_debug(chat, mux_debug, "CHAT1");
128         g_at_chat_set_wakeup_command(chat, "\r", 1000, 5000);
129         g_at_chat_send(chat, "AT+CGMI", NULL, NULL, NULL, NULL);
130         g_at_chat_send(chat, "AT+CGMR", NULL, chat_callback, chat, NULL);
131
132         io = g_at_mux_create_channel(mux);
133         syntax = g_at_syntax_new_gsm_permissive();
134         chat = g_at_chat_new(io, syntax);
135         g_at_syntax_unref(syntax);
136         g_io_channel_unref(io);
137
138         g_at_chat_set_debug(chat, mux_debug, "CHAT2");
139         g_at_chat_set_wakeup_command(chat, "\r", 1000, 5000);
140         g_at_chat_send(chat, "AT+CGMI", NULL, NULL, NULL, NULL);
141         g_at_chat_send(chat, "AT+CGMR", NULL, chat_callback, chat, NULL);
142
143         io = g_at_mux_create_channel(mux);
144         syntax = g_at_syntax_new_gsm_permissive();
145         chat = g_at_chat_new(io, syntax);
146         g_at_syntax_unref(syntax);
147         g_io_channel_unref(io);
148
149         g_at_chat_set_debug(chat, mux_debug, "CHAT3");
150         g_at_chat_set_wakeup_command(chat, "\r", 1000, 5000);
151         g_at_chat_send(chat, "AT+CGMI", NULL, NULL, NULL, NULL);
152         g_at_chat_send(chat, "AT+CGMR", NULL, chat_callback, chat, NULL);
153
154         io = g_at_mux_create_channel(mux);
155         syntax = g_at_syntax_new_gsm_permissive();
156         chat = g_at_chat_new(io, syntax);
157         g_at_syntax_unref(syntax);
158         g_io_channel_unref(io);
159
160         g_at_chat_set_debug(chat, mux_debug, "CHAT4");
161         g_at_chat_set_wakeup_command(chat, "\r", 1000, 5000);
162         g_at_chat_send(chat, "AT+CGMI", NULL, NULL, NULL, NULL);
163         g_at_chat_send(chat, "AT+CGMR", NULL, chat_callback, chat, NULL);
164
165         g_timeout_add_seconds(7, cleanup_callback, NULL);
166 }
167
168 static void mux_init(gboolean ok, GAtResult *result, gpointer data)
169 {
170         GAtChat *chat = data;
171
172         g_print("mux_init: %d\n", ok);
173
174         if (ok == FALSE) {
175                 g_at_chat_unref(chat);
176                 g_main_loop_quit(mainloop);
177                 return;
178         }
179
180         g_at_mux_setup_gsm0710(chat, mux_setup, chat, NULL);
181 }
182
183 static void test_mux(void)
184 {
185         GIOChannel *io;
186         GAtChat *chat;
187         GAtSyntax *syntax;
188         int sk;
189
190         sk = do_connect("192.168.0.202", 2000);
191         if (sk < 0) {
192                 g_printerr("connect failed\n");
193                 return;
194         }
195
196         mux = NULL;
197         io = g_io_channel_unix_new(sk);
198         g_io_channel_set_close_on_unref(io, TRUE);
199
200         syntax = g_at_syntax_new_gsm_permissive();
201         chat = g_at_chat_new(io, syntax);
202         g_at_syntax_unref(syntax);
203
204         g_io_channel_unref(io);
205
206         if (chat == NULL) {
207                 g_printerr("Chat creation failed\n");
208                 return;
209         }
210
211         g_at_chat_set_debug(chat, mux_debug, "MUX");
212         g_at_chat_set_wakeup_command(chat, "\r", 1000, 5000);
213         g_at_chat_send(chat, "ATE0", NULL, mux_init, chat, NULL);
214
215         mainloop = g_main_loop_new(NULL, FALSE);
216
217         g_main_loop_run(mainloop);
218         g_main_loop_unref(mainloop);
219 }
220
221 static void test_basic(void)
222 {
223         if (g_test_trap_fork(60 * 1000 * 1000, 0) == TRUE) {
224                 test_mux();
225                 exit(0);
226         }
227
228         g_test_trap_assert_passed();
229         //g_test_trap_assert_stderr("failed");
230 }
231
232 /* DLC 1, Open Channel */
233 static const guint8 basic_open[] = { 0xF9, 0x07, 0x3F, 0x01, 0xDE, 0xF9 };
234
235 /* DLC 1, Close Channel */
236 static char const basic_close[] = { 0xF9, 0x07, 0x53, 0x01, 0x3F, 0xF9 };
237
238 /* DLC 1, Data */
239 static const guint8 basic_data[] = { 0x12, 0x34, 0x56 };
240 static const guint8 basic_data_result[] =
241         { 0xF9, 0x07, 0xEF, 0x07, 0x12, 0x34, 0x56, 0xD3, 0xF9 };
242
243 /* DLC 1, Long Data */
244 static const guint8 basic_long_frame[] =
245 {       0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0,
246         0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0,
247         0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0,
248         0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0,
249         0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0,
250         0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0,
251         0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0,
252         0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0,
253         0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0,
254         0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0,
255         0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0,
256         0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0,
257         0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0,
258         0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0,
259         0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0,
260         0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0,
261         0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0,
262 };
263
264 static const guint8 basic_long_frame_result[] =
265 {       0xF9, 0x07, 0xEF, 0x10, 0x01, 0x12, 0x34, 0x56,
266         0x78, 0x9A, 0xBC, 0xDE, 0xF0, 0x12, 0x34, 0x56,
267         0x78, 0x9A, 0xBC, 0xDE, 0xF0, 0x12, 0x34, 0x56,
268         0x78, 0x9A, 0xBC, 0xDE, 0xF0, 0x12, 0x34, 0x56,
269         0x78, 0x9A, 0xBC, 0xDE, 0xF0, 0x12, 0x34, 0x56,
270         0x78, 0x9A, 0xBC, 0xDE, 0xF0, 0x12, 0x34, 0x56,
271         0x78, 0x9A, 0xBC, 0xDE, 0xF0, 0x12, 0x34, 0x56,
272         0x78, 0x9A, 0xBC, 0xDE, 0xF0, 0x12, 0x34, 0x56,
273         0x78, 0x9A, 0xBC, 0xDE, 0xF0, 0x12, 0x34, 0x56,
274         0x78, 0x9A, 0xBC, 0xDE, 0xF0, 0x12, 0x34, 0x56,
275         0x78, 0x9A, 0xBC, 0xDE, 0xF0, 0x12, 0x34, 0x56,
276         0x78, 0x9A, 0xBC, 0xDE, 0xF0, 0x12, 0x34, 0x56,
277         0x78, 0x9A, 0xBC, 0xDE, 0xF0, 0x12, 0x34, 0x56,
278         0x78, 0x9A, 0xBC, 0xDE, 0xF0, 0x12, 0x34, 0x56,
279         0x78, 0x9A, 0xBC, 0xDE, 0xF0, 0x12, 0x34, 0x56,
280         0x78, 0x9A, 0xBC, 0xDE, 0xF0, 0x12, 0x34, 0x56,
281         0x78, 0x9A, 0xBC, 0xDE, 0xF0, 0x12, 0x34, 0x56,
282         0x78, 0x9A, 0xBC, 0xDE, 0xF0, 0x88, 0xF9
283 };
284
285 static void test_fill_basic(void)
286 {
287         guint8 control_frame[6];
288         guint8 data_frame[128];
289         guint8 long_frame[256];
290         int s;
291
292         s = gsm0710_basic_fill_frame(control_frame, 1, GSM0710_OPEN_CHANNEL,
293                                         NULL, 0);
294         g_assert(s == sizeof(basic_open));
295         g_assert(memcmp(basic_open, control_frame, s) == 0);
296
297         s = gsm0710_basic_fill_frame(control_frame, 1, GSM0710_CLOSE_CHANNEL,
298                                         NULL, 0);
299         g_assert(s == sizeof(basic_close));
300         g_assert(memcmp(basic_close, control_frame, s) == 0);
301
302         s = gsm0710_basic_fill_frame(data_frame, 1, GSM0710_DATA,
303                                         basic_data, sizeof(basic_data));
304         g_assert(s == sizeof(basic_data_result));
305         g_assert(memcmp(basic_data_result, data_frame, s) == 0);
306
307         s = gsm0710_basic_fill_frame(long_frame, 1, GSM0710_DATA,
308                                         basic_long_frame,
309                                         sizeof(basic_long_frame));
310         g_assert(s == sizeof(basic_long_frame_result));
311         g_assert(memcmp(basic_long_frame_result, long_frame, s) == 0);
312 }
313
314 /* DLC 1, Open Channel */
315 static const guint8 advanced_open[] = { 0x7E, 0x07, 0x3F, 0x89, 0x7E };
316
317 /* DLC 1, Close Channel */
318 static const guint8 advanced_close[] = { 0x7E, 0x07, 0x53, 0xC8, 0x7E };
319
320 /* DLC 1, Data */
321 static const guint8 advanced_data[] = { 0x12, 0x34, 0x56 };
322 static const guint8 advanced_data_result[] =
323         { 0x7E, 0x07, 0xEF, 0x12, 0x34, 0x56, 0x05, 0x7E };
324
325 /* DLC 1, Quoted data */
326 static const guint8 advanced_quoted_data[] =
327         { 0x12, 0x34, 0x56, 0x7E, 0x78, 0x7D };
328 static const guint8 advanced_quoted_data_result[] =
329         { 0x7E, 0x07, 0xEF, 0x12, 0x34, 0x56, 0x7D, 0x5E, 0x78,
330                 0x7D, 0x5D, 0x05, 0x7E };
331
332 static void test_fill_advanced(void)
333 {
334         guint8 control_frame[8];
335         guint8 data_frame[128];
336         int s;
337
338         s = gsm0710_advanced_fill_frame(control_frame, 1, GSM0710_OPEN_CHANNEL,
339                                         NULL, 0);
340         g_assert(s == sizeof(advanced_open));
341         g_assert(memcmp(advanced_open, control_frame, s) == 0);
342
343         s = gsm0710_advanced_fill_frame(control_frame, 1, GSM0710_CLOSE_CHANNEL,
344                                         NULL, 0);
345         g_assert(s == sizeof(advanced_close));
346         g_assert(memcmp(advanced_close, control_frame, s) == 0);
347
348         s = gsm0710_advanced_fill_frame(data_frame, 1, GSM0710_DATA,
349                                         advanced_data, sizeof(advanced_data));
350         g_assert(s == sizeof(advanced_data_result));
351         g_assert(memcmp(advanced_data_result, data_frame, s) == 0);
352
353         s = gsm0710_advanced_fill_frame(data_frame, 1, GSM0710_DATA,
354                                         advanced_quoted_data,
355                                         sizeof(advanced_quoted_data));
356         g_assert(s == sizeof(advanced_quoted_data_result));
357         g_assert(memcmp(advanced_quoted_data_result, data_frame, s) == 0);
358 }
359
360 static guint8 basic_input[] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xF9, 0x07, 0xEF,
361         0x07, 0x12, 0x34, 0x56, 0xD3, 0xF9, 0x07, 0xEF, 0x07, 0x12, 0x34, 0x56,
362         0xD3, 0xF9 };
363
364 static guint8 basic_input2[] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xF9, 0x07, 0xEF,
365         0x07, 0x12, 0x34, 0x56, 0xD3, 0xF9, 0xF9, 0x07, 0xEF, 0x07, 0x12,
366         0x34, 0x56, 0xD3, 0xF9 };
367
368 static int basic_garbage_size = 4;
369 static int basic_frame_size = 7;
370
371 static const guint8 basic_output[] = { 0x12, 0x34, 0x56 };
372
373 static void test_extract_basic(void)
374 {
375         int total = 0;
376         int nread;
377         guint8 dlc;
378         guint8 ctrl;
379         guint8 *frame;
380         int frame_size;
381
382         frame = NULL;
383         frame_size = 0;
384
385         nread = gsm0710_basic_extract_frame(basic_input + total,
386                                                 basic_garbage_size, &dlc, &ctrl,
387                                                 &frame, &frame_size);
388
389         g_assert(frame == NULL);
390         g_assert(frame_size == 0);
391
392         total += nread;
393
394         /* Try to read with just the open flag */
395         nread = gsm0710_basic_extract_frame(basic_input + total,
396                                                 basic_frame_size + 1,
397                                                 &dlc, &ctrl,
398                                                 &frame, &frame_size);
399
400         g_assert(nread == 0);
401         g_assert(frame == NULL);
402
403         /* Now read with the close flag as well */
404         nread = gsm0710_basic_extract_frame(basic_input + total,
405                                                 basic_frame_size + 2,
406                                                 &dlc, &ctrl,
407                                                 &frame, &frame_size);
408
409         /* Extracted the open flag + frame */
410         g_assert(nread == basic_frame_size + 1);
411         g_assert(frame_size == sizeof(basic_output));
412         g_assert(memcmp(basic_output, frame, frame_size) == 0);
413
414         total += nread;
415
416         nread = gsm0710_basic_extract_frame(basic_input + total,
417                                                 sizeof(basic_input) - total,
418                                                 &dlc, &ctrl,
419                                                 &frame, &frame_size);
420
421         g_assert(nread == (int)(sizeof(basic_input) - total - 1));
422         g_assert(frame_size == sizeof(basic_output));
423         g_assert(memcmp(basic_output, frame, frame_size) == 0);
424
425         total += nread;
426
427         nread = gsm0710_basic_extract_frame(basic_input + total,
428                                                 sizeof(basic_input) - total,
429                                                 &dlc, &ctrl,
430                                                 &frame, &frame_size);
431         g_assert(nread == 0);
432
433         total = 0;
434
435         nread = gsm0710_basic_extract_frame(basic_input2 + total,
436                                                 sizeof(basic_input2) - total,
437                                                 &dlc, &ctrl,
438                                                 &frame, &frame_size);
439
440         g_assert(nread == basic_garbage_size + basic_frame_size + 1);
441         g_assert(frame_size == sizeof(basic_output));
442         g_assert(memcmp(basic_output, frame, frame_size) == 0);
443
444         total += nread;
445
446         nread = gsm0710_basic_extract_frame(basic_input2 + total,
447                                                 sizeof(basic_input2) - total,
448                                                 &dlc, &ctrl,
449                                                 &frame, &frame_size);
450
451         g_assert(frame_size == sizeof(basic_output));
452         g_assert(memcmp(basic_output, frame, frame_size) == 0);
453
454         total += nread;
455
456         g_assert(total == sizeof(basic_input2) - 1);
457 }
458
459 static guint8 advanced_input[] =
460         { 0xFF, 0xFF, 0xFF, 0x7E, 0x07, 0xEF, 0x12, 0x34, 0x56, 0x05, 0x7E,
461                 0x07, 0xEF, 0x12, 0x34, 0x56, 0x05, 0x7E };
462
463 static guint8 advanced_input2[] =
464         { 0xFF, 0xFF, 0xFF, 0x7E, 0x07, 0xEF, 0x12, 0x34, 0x56, 0x05, 0x7E,
465                 0x07, 0xEF, 0x12, 0x34, 0x56, 0x05, 0x7E };
466
467 static int advanced_garbage_size = 3;
468 static int advanced_frame_size = 6;
469
470 static const guint8 advanced_output[] = { 0x12, 0x34, 0x56 };
471
472 static void test_extract_advanced(void)
473 {
474         int total = 0;
475         int nread;
476         guint8 dlc;
477         guint8 ctrl;
478         guint8 *frame;
479         int frame_size;
480
481         frame = NULL;
482         frame_size = 0;
483
484         nread = gsm0710_advanced_extract_frame(advanced_input + total,
485                                                 advanced_garbage_size,
486                                                 &dlc, &ctrl,
487                                                 &frame, &frame_size);
488
489         g_assert(frame == NULL);
490         g_assert(frame_size == 0);
491
492         total += nread;
493
494         /* Try to read with just the open flag */
495         nread = gsm0710_advanced_extract_frame(advanced_input + total,
496                                                 advanced_frame_size + 1,
497                                                 &dlc, &ctrl,
498                                                 &frame, &frame_size);
499
500         g_assert(nread == 0);
501         g_assert(frame == NULL);
502
503         /* Now read with the close flag as well */
504         nread = gsm0710_advanced_extract_frame(advanced_input + total,
505                                                 advanced_frame_size + 2,
506                                                 &dlc, &ctrl,
507                                                 &frame, &frame_size);
508
509         /* Extracted the open flag + frame */
510         g_assert(nread == advanced_frame_size + 1);
511         g_assert(frame_size == sizeof(advanced_output));
512         g_assert(memcmp(advanced_output, frame, frame_size) == 0);
513
514         total += nread;
515
516         nread = gsm0710_advanced_extract_frame(advanced_input + total,
517                                                 sizeof(advanced_input) - total,
518                                                 &dlc, &ctrl,
519                                                 &frame, &frame_size);
520
521         g_assert(nread == (int)(sizeof(advanced_input) - total - 1));
522         g_assert(frame_size == sizeof(advanced_output));
523         g_assert(memcmp(advanced_output, frame, frame_size) == 0);
524
525         total += nread;
526
527         nread = gsm0710_advanced_extract_frame(advanced_input + total,
528                                                 sizeof(advanced_input) - total,
529                                                 &dlc, &ctrl,
530                                                 &frame, &frame_size);
531         g_assert(nread == 0);
532
533         total = 0;
534
535         nread = gsm0710_advanced_extract_frame(advanced_input2 + total,
536                                                 sizeof(advanced_input2) - total,
537                                                 &dlc, &ctrl,
538                                                 &frame, &frame_size);
539
540         g_assert(nread == advanced_garbage_size + advanced_frame_size + 1);
541         g_assert(frame_size == sizeof(advanced_output));
542         g_assert(memcmp(advanced_output, frame, frame_size) == 0);
543
544         total += nread;
545
546         nread = gsm0710_advanced_extract_frame(advanced_input2 + total,
547                                                 sizeof(advanced_input2) - total,
548                                                 &dlc, &ctrl,
549                                                 &frame, &frame_size);
550
551         g_assert(frame_size == sizeof(advanced_output));
552         g_assert(memcmp(advanced_output, frame, frame_size) == 0);
553
554         total += nread;
555
556         g_assert(total == sizeof(advanced_input2) - 1);
557 }
558
559 int main(int argc, char **argv)
560 {
561         g_test_init(&argc, &argv, NULL);
562
563         g_test_add_func("/testmux/fill_basic", test_fill_basic);
564         g_test_add_func("/testmux/fill_advanced", test_fill_advanced);
565         g_test_add_func("/testmux/extract_basic", test_extract_basic);
566         g_test_add_func("/testmux/extract_advanced", test_extract_advanced);
567         g_test_add_func("/testmux/basic", test_basic);
568
569         return g_test_run();
570 }