Imported Upstream version 0.1.17
[platform/upstream/libnice.git] / tests / test-bsd.c
1 /*
2  * This file is part of the Nice GLib ICE library.
3  *
4  * (C) 2006, 2007, 2014 Collabora Ltd.
5  *  Contact: Dafydd Harries
6  * (C) 2006, 2007 Nokia Corporation. All rights reserved.
7  *  Contact: Kai Vehmanen
8  *
9  * The contents of this file are subject to the Mozilla Public License Version
10  * 1.1 (the "License"); you may not use this file except in compliance with
11  * the License. You may obtain a copy of the License at
12  * http://www.mozilla.org/MPL/
13  *
14  * Software distributed under the License is distributed on an "AS IS" basis,
15  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
16  * for the specific language governing rights and limitations under the
17  * License.
18  *
19  * The Original Code is the Nice GLib ICE library.
20  *
21  * The Initial Developers of the Original Code are Collabora Ltd and Nokia
22  * Corporation. All Rights Reserved.
23  *
24  * Contributors:
25  *   Dafydd Harries, Collabora Ltd.
26  *   Philip Withnall, Collabora Ltd.
27  *
28  * Alternatively, the contents of this file may be used under the terms of the
29  * the GNU Lesser General Public License Version 2.1 (the "LGPL"), in which
30  * case the provisions of LGPL are applicable instead of those above. If you
31  * wish to allow use of your version of this file only under the terms of the
32  * LGPL and not to allow others to use your version of this file under the
33  * MPL, indicate your decision by deleting the provisions above and replace
34  * them with the notice and other provisions required by the LGPL. If you do
35  * not delete the provisions above, a recipient may use your version of this
36  * file under either the MPL or the LGPL.
37  */
38 #ifdef HAVE_CONFIG_H
39 # include "config.h"
40 #endif
41
42 #include <string.h>
43
44 #include "socket.h"
45
46 static gssize
47 socket_recv (NiceSocket *sock, NiceAddress *addr, gsize buf_len, gchar *buf)
48 {
49   GInputVector local_buf = { buf, buf_len };
50   NiceInputMessage local_message = { &local_buf, 1, addr, 0 };
51   gint ret;
52
53   ret = nice_socket_recv_messages (sock, &local_message, 1);
54   if (ret <= 0)
55     return ret;
56
57   return local_buf.size;
58 }
59
60 static void
61 test_socket_initial_properties (void)
62 {
63   NiceSocket *sock;
64
65   sock = nice_udp_bsd_socket_new (NULL);
66   g_assert (sock != NULL);
67
68   // not bound to a particular interface
69   g_assert_cmpint (sock->addr.s.ip4.sin_addr.s_addr, ==, 0);
70   // is bound to a particular port
71   g_assert_cmpuint (nice_address_get_port (&sock->addr), !=, 0);
72
73   nice_socket_free (sock);
74 }
75
76 static void
77 test_socket_address_properties (void)
78 {
79   NiceSocket *sock;
80   NiceAddress tmp;
81
82   sock = nice_udp_bsd_socket_new (NULL);
83   g_assert (sock != NULL);
84
85   g_assert (nice_address_set_from_string (&tmp, "127.0.0.1"));
86   g_assert_cmpuint (nice_address_get_port (&sock->addr), !=, 0);
87   nice_address_set_port (&tmp, nice_address_get_port (&sock->addr));
88   g_assert_cmpuint (nice_address_get_port (&tmp), !=, 0);
89
90   nice_socket_free (sock);
91 }
92
93 static void
94 test_simple_send_recv (void)
95 {
96   NiceSocket *server;
97   NiceSocket *client;
98   NiceAddress tmp;
99   gchar buf[5];
100
101   server = nice_udp_bsd_socket_new (NULL);
102   g_assert (server != NULL);
103
104   client = nice_udp_bsd_socket_new (NULL);
105   g_assert (client != NULL);
106
107   g_assert (nice_address_set_from_string (&tmp, "127.0.0.1"));
108   nice_address_set_port (&tmp, nice_address_get_port (&server->addr));
109
110   /* Send and receive stuff. */
111   g_assert_cmpint (nice_socket_send (client, &tmp, 5, "hello"), ==, 5);
112
113   g_assert_cmpint (socket_recv (server, &tmp, 5, buf), ==, 5);
114   g_assert_cmpint (strncmp (buf, "hello", 5), ==, 0);
115
116   g_assert_cmpint (nice_socket_send (server, &tmp, 5, "uryyb"), ==, 5);
117
118   g_assert_cmpint (socket_recv (client, &tmp, 5, buf), ==, 5);
119   g_assert_cmpint (strncmp (buf, "uryyb", 5), ==, 0);
120
121   nice_socket_free (client);
122   nice_socket_free (server);
123 }
124
125 /* Check that sending and receiving to/from zero-length buffers returns
126  * immediately. */
127 static void
128 test_zero_send_recv (void)
129 {
130   NiceSocket *sock;
131   NiceAddress tmp;
132   gchar buf[5];
133   NiceOutputMessage local_out_message;
134   NiceInputMessage local_in_message;
135
136   sock = nice_udp_bsd_socket_new (NULL);
137   g_assert (sock != NULL);
138
139   g_assert (nice_address_set_from_string (&tmp, "127.0.0.1"));
140   g_assert_cmpuint (nice_address_get_port (&sock->addr), !=, 0);
141   nice_address_set_port (&tmp, nice_address_get_port (&sock->addr));
142   g_assert_cmpuint (nice_address_get_port (&tmp), !=, 0);
143
144   g_assert_cmpint (nice_socket_send (sock, &tmp, 0, "ignore-me"), ==, 0);
145   g_assert_cmpint (nice_socket_send (sock, &tmp, 0, NULL), ==, 0);
146
147   g_assert_cmpint (socket_recv (sock, &tmp, 0, buf), ==, 0);
148   g_assert_cmpint (socket_recv (sock, &tmp, 0, NULL), ==, 0);
149
150   /* And again with messages. */
151   g_assert_cmpint (nice_socket_send_messages (sock, &tmp,
152       &local_out_message, 0), ==, 0);
153   g_assert_cmpint (nice_socket_send_messages (sock, &tmp, NULL, 0), ==, 0);
154
155   g_assert_cmpint (nice_socket_recv_messages (sock,
156       &local_in_message, 0), ==, 0);
157   g_assert_cmpint (nice_socket_recv_messages (sock, NULL, 0), ==, 0);
158
159   nice_socket_free (sock);
160 }
161
162 /* Test receiving into multiple tiny buffers. */
163 static void
164 test_multi_buffer_recv (void)
165 {
166   NiceSocket *server;
167   NiceSocket *client;
168   NiceAddress tmp;
169   guint8 buf[20];
170   guint8 dummy_buf[9];
171
172   server = nice_udp_bsd_socket_new (NULL);
173   g_assert (server != NULL);
174
175   client = nice_udp_bsd_socket_new (NULL);
176   g_assert (client != NULL);
177
178   g_assert (nice_address_set_from_string (&tmp, "127.0.0.1"));
179   nice_address_set_port (&tmp, nice_address_get_port (&server->addr));
180
181   /* Send and receive stuff. */
182   {
183     GInputVector bufs[7] = {
184       { &buf[0], 1 },
185       { &buf[1], 4 },
186       { &buf[1], 0 },  /* should be unused (zero-length) */
187       { &buf[5], 1 },
188       { &buf[6], 5 },
189       { &buf[11], 9 },  /* should be unused (message fits in prior buffers) */
190       { &buf[11], 0 },  /* should be unused (zero-length) */
191     };
192     NiceInputMessage message = { bufs, G_N_ELEMENTS (bufs), NULL, 0 };
193
194     /* Initialise the buffers so we can try and catch out-of-bounds accesses. */
195     memset (buf, 0xaa, sizeof (buf));
196     memset (dummy_buf, 0xaa, sizeof (dummy_buf));
197
198     /* Send and receive. */
199     g_assert_cmpint (nice_socket_send (client, &tmp, 11, "hello-world"), ==, 11);
200     g_assert_cmpuint (nice_socket_recv_messages (server, &message, 1), ==, 1);
201     g_assert_cmpuint (message.length, ==, 11);
202
203     /* Check all of the things. The sizes should not have been modified. */
204     g_assert_cmpuint (bufs[0].size, ==, 1);
205     g_assert_cmpuint (bufs[1].size, ==, 4);
206     g_assert_cmpuint (bufs[2].size, ==, 0);
207     g_assert_cmpuint (bufs[3].size, ==, 1);
208     g_assert_cmpuint (bufs[4].size, ==, 5);
209     g_assert_cmpuint (bufs[5].size, ==, 9);
210     g_assert_cmpuint (bufs[6].size, ==, 0);
211
212     g_assert_cmpint (strncmp ((gchar *) buf, "hello-world", 11), ==, 0);
213     g_assert_cmpmem (buf + 11, 9, dummy_buf, 9);
214   }
215
216   nice_socket_free (client);
217   nice_socket_free (server);
218 }
219
220 /* Fill a buffer with deterministic but non-repeated data, so that transmission
221  * and reception corruption is more likely to be detected. */
222 static void
223 fill_send_buf (guint8 *buf, gsize buf_len, guint seed)
224 {
225   gsize i;
226
227   for (i = 0; i < buf_len; i++) {
228     buf[i] = '0' + (seed % 10);
229     seed++;
230   }
231 }
232
233 /* Test receiving multiple messages in a single call. */
234 static void
235 test_multi_message_recv (guint n_sends, guint n_receives,
236     guint n_bufs_per_message, gsize send_buf_size, gsize recv_buf_size,
237     guint expected_n_received_messages, guint expected_n_sent_messages)
238 {
239   NiceSocket *server;
240   NiceSocket *client;
241   NiceAddress tmp;
242
243   server = nice_udp_bsd_socket_new (NULL);
244   g_assert (server != NULL);
245
246   client = nice_udp_bsd_socket_new (NULL);
247   g_assert (client != NULL);
248
249   g_assert (nice_address_set_from_string (&tmp, "127.0.0.1"));
250   nice_address_set_port (&tmp, nice_address_get_port (&server->addr));
251
252   /* Send and receive stuff. */
253   {
254     GInputVector *recv_bufs;
255     NiceInputMessage *recv_messages;
256     GOutputVector *send_bufs;
257     NiceOutputMessage *send_messages;
258     guint i, j;
259     guint8 *_expected_recv_buf;
260     gsize expected_recv_buf_len;
261
262     /* Set up the send buffers. */
263     send_bufs = g_malloc0_n (n_sends * n_bufs_per_message,
264         sizeof (GOutputVector));
265     send_messages = g_malloc0_n (n_sends, sizeof (NiceOutputMessage));
266
267     for (i = 0; i < n_sends; i++) {
268       for (j = 0; j < n_bufs_per_message; j++) {
269         guint8 *buf = g_slice_alloc (send_buf_size);
270
271         send_bufs[i * n_bufs_per_message + j].buffer = buf;
272         send_bufs[i * n_bufs_per_message + j].size = send_buf_size;
273
274         /* Set up the buffer data. */
275         fill_send_buf (buf, send_buf_size, i);
276       }
277
278       send_messages[i].buffers = send_bufs + i * n_bufs_per_message;
279       send_messages[i].n_buffers = n_bufs_per_message;
280     }
281
282     /* Set up the receive buffers. Yay for dynamic tests! */
283     recv_bufs = g_malloc0_n (n_receives * n_bufs_per_message,
284         sizeof (GInputVector));
285     recv_messages = g_malloc0_n (n_receives, sizeof (NiceInputMessage));
286
287     for (i = 0; i < n_receives; i++) {
288       for (j = 0; j < n_bufs_per_message; j++) {
289         recv_bufs[i * n_bufs_per_message + j].buffer =
290             g_slice_alloc (recv_buf_size);
291         recv_bufs[i * n_bufs_per_message + j].size = recv_buf_size;
292
293         /* Initialise the buffer to try to catch out-of-bounds accesses. */
294         memset (recv_bufs[i * n_bufs_per_message + j].buffer, 0xaa,
295             recv_buf_size);
296       }
297
298       recv_messages[i].buffers = recv_bufs + i * n_bufs_per_message;
299       recv_messages[i].n_buffers = n_bufs_per_message;
300       recv_messages[i].from = NULL;
301       recv_messages[i].length = 0;
302     }
303
304     /* Send multiple packets. */
305     g_assert_cmpint (
306         nice_socket_send_messages (client, &tmp, send_messages, n_sends), ==,
307         expected_n_sent_messages);
308
309     /* Receive things. */
310     g_assert_cmpint (
311         nice_socket_recv_messages (server, recv_messages, n_receives), ==,
312         expected_n_received_messages);
313
314     /* Check all of the things. The sizes should not have been modified. */
315     expected_recv_buf_len = recv_buf_size * n_bufs_per_message;
316     _expected_recv_buf = g_slice_alloc (expected_recv_buf_len);
317
318     for (i = 0; i < expected_n_received_messages; i++) {
319       NiceInputMessage *message = &recv_messages[i];
320       guint8 *expected_recv_buf = _expected_recv_buf;
321       gsize expected_len;
322
323       expected_len = MIN (send_buf_size * n_bufs_per_message,
324           expected_recv_buf_len);
325       g_assert_cmpuint (message->length, ==, expected_len);
326
327       /* Build the expected buffer as a concatenation of the expected values of
328        * all receive buffers in the message. */
329       memset (expected_recv_buf, 0xaa, expected_recv_buf_len);
330       fill_send_buf (expected_recv_buf, expected_len, i);
331
332       for (j = 0; j < n_bufs_per_message; j++) {
333         g_assert_cmpuint (message->buffers[j].size, ==, recv_buf_size);
334         g_assert_cmpint (
335             memcmp (message->buffers[j].buffer, expected_recv_buf,
336                 recv_buf_size), ==, 0);
337
338         expected_recv_buf += recv_buf_size;
339       }
340     }
341
342     g_slice_free1 (expected_recv_buf_len, _expected_recv_buf);
343
344     for (i = 0; i < n_receives; i++) {
345       for (j = 0; j < n_bufs_per_message; j++) {
346         g_slice_free1 (recv_buf_size,
347                        recv_bufs[i * n_bufs_per_message + j].buffer);
348       }
349     }
350
351     for (i = 0; i < n_sends; i++) {
352       for (j = 0; j < n_bufs_per_message; j++) {
353         g_slice_free1 (send_buf_size,
354                        (gpointer) send_bufs[i * n_bufs_per_message + j].buffer);
355       }
356     }
357
358     g_free (recv_messages);
359     g_free (recv_bufs);
360     g_free (send_messages);
361     g_free (send_bufs);
362   }
363
364   nice_socket_free (client);
365   nice_socket_free (server);
366 }
367
368 int
369 main (void)
370 {
371   test_socket_initial_properties ();
372   test_socket_address_properties ();
373   test_simple_send_recv ();
374   test_zero_send_recv ();
375   test_multi_buffer_recv ();
376
377   /* Multi-message testing. Serious business. */
378   {
379     guint i;
380     struct {
381       guint n_sends;  /* messages */
382       guint expected_n_sent_messages;
383
384       guint n_receives;  /* messages */
385       guint expected_n_received_messages;
386
387       guint n_bufs_per_message;
388       gsize send_buf_size;
389       gsize recv_buf_size;
390     } test_cases[] = {
391       /* same number of sends and receives */
392       {   2,   2,   2,   2,   1, 100, 100 },  /* send 200B, receive 200B */
393       /* more sends than receives */
394       {   4,   4,   2,   2,   2, 100,  77 },  /* send 800B, receive 308B */
395       /* more receives than sends */
396       {   1,   1,   4,   1,   4,  10, 100 },  /* send 40B, receive 1600B */
397       /* small receive buffer (data loss) */
398       { 100, 100, 100, 100,   1, 100,  64 },  /* send 10000B, receive 6400B */
399       /* small receive buffers (data loss) */
400       {  50,  50,  50,  50,  10, 100,   8 },  /* send 50000B, receive 4000B */
401     };
402
403     for (i = 0; i < G_N_ELEMENTS (test_cases); i++) {
404       test_multi_message_recv (test_cases[i].n_sends, test_cases[i].n_receives,
405           test_cases[i].n_bufs_per_message, test_cases[i].send_buf_size,
406           test_cases[i].recv_buf_size,
407           test_cases[i].expected_n_received_messages,
408           test_cases[i].expected_n_sent_messages);
409     }
410   }
411
412   return 0;
413 }
414