1 /* GNet GConn unit tests
2 * Copyright (C) 2007 Tim-Philipp Müller <tim centricular net>
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 */
18
19 #include "config.h"
20 #include "gnetcheck.h"
21
22 #ifdef HAVE_VALGRIND
23 #include <valgrind/valgrind.h>
24 #endif
25
26 #include <string.h>
27
28 static void
conn_fail_cb(GConn * conn,GConnEvent * event,gpointer data)29 conn_fail_cb (GConn * conn, GConnEvent * event, gpointer data)
30 {
31 GMainLoop *loop = (GMainLoop *) data;
32
33 /* the domain doesn't exist, it should give us an error */
34 fail_unless_equals_int (event->type, GNET_CONN_ERROR);
35
36 /* test that we can delete the connection in the callback */
37 gnet_conn_delete (conn);
38
39 g_main_loop_quit (loop);
40 }
41
42 static void
conn_cb(GConn * conn,GConnEvent * event,gpointer data)43 conn_cb (GConn * conn, GConnEvent * event, gpointer data)
44 {
45 GMainLoop *loop = (GMainLoop *) data;
46
47 switch (event->type) {
48 case GNET_CONN_CONNECT: {
49 const gchar req[] = "GET / HTTP/1.0\r\n"
50 "Accept: */*\r\nConnection: Close\r\n"
51 "\r\n";
52
53 g_print ("Connected.\n");
54 /* using _write_direct() here on purpose to test that code path too */
55 gnet_conn_write_direct (conn, g_strdup (req), strlen (req),
56 (GDestroyNotify) g_free);
57 break;
58 }
59 case GNET_CONN_WRITE:
60 g_print ("Sent request.\n");
61 gnet_conn_read (conn);
62 break;
63 case GNET_CONN_READ:
64 g_print (".");
65 /* write (1, event->buffer, event->length); */
66 gnet_conn_read (conn);
67 break;
68 case GNET_CONN_READABLE:
69 g_error ("READABLE event shouldn't have happened without explicit watch");
70 break;
71 case GNET_CONN_WRITABLE:
72 g_error ("WRITABLE event shouldn't have happened without explicit watch");
73 break;
74 case GNET_CONN_CLOSE:
75 g_print ("\nConnection closed by server.\n");
76 g_main_loop_quit (loop);
77 break;
78 case GNET_CONN_TIMEOUT:
79 g_print ("Timeout.\n");
80 g_main_loop_quit (loop);
81 break;
82 case GNET_CONN_ERROR:
83 g_print ("Connection error.\n");
84 g_main_loop_quit (loop);
85 break;
86 default:
87 g_error ("Unexpected event type %d", event->type);
88 break;
89 }
90 }
91
GNET_START_TEST(test_conn_new)92 GNET_START_TEST (test_conn_new)
93 {
94 GMainContext *ctx;
95 GMainLoop *loop;
96 GConn *conn;
97
98 ctx = g_main_context_new ();
99 loop = g_main_loop_new (ctx, FALSE);
100
101 conn = gnet_conn_new ("www.microsoft.com", 80, conn_cb, loop);
102 /* should always succeed, we're not doing any lookups or connecting yet */
103 fail_unless (conn != NULL);
104
105 gnet_conn_timeout (conn, 5 * 1000);
106 gnet_conn_set_main_context (conn, ctx);
107
108 fail_if (g_main_context_pending (ctx));
109
110 gnet_conn_connect (conn);
111
112 g_main_loop_run (loop);
113
114 gnet_conn_disconnect (conn);
115 gnet_conn_delete (conn);
116
117 fail_if (g_main_context_pending (NULL));
118 fail_if (g_main_context_pending (ctx));
119
120 /* test failure case too */
121 conn = gnet_conn_new ("does.not.exist", 80, conn_fail_cb, loop);
122 /* should always succeed, we're not doing any lookups or connecting yet */
123 fail_unless (conn != NULL);
124
125 gnet_conn_timeout (conn, 5 * 1000);
126 gnet_conn_set_main_context (conn, ctx);
127
128 fail_if (g_main_context_pending (ctx));
129
130 gnet_conn_connect (conn);
131
132 g_main_loop_run (loop);
133
134 /* we've deleted the connection in the callback */
135
136 g_main_context_unref (ctx);
137 g_main_loop_unref (loop);
138
139 #ifdef HAVE_VALGRIND
140 if (RUNNING_ON_VALGRIND) {
141 /* give DNS lookup thread a chance to finish, it's not stuck in a blocking
142 * operation, so a short sleep should be fine; valgrind will think the
143 * thread was leaked if we don't do this */
144 g_usleep (1 * G_USEC_PER_SEC);
145 }
146 #endif
147 }
148 GNET_END_TEST;
149
GNET_START_TEST(test_conn_new_inetaddr)150 GNET_START_TEST (test_conn_new_inetaddr)
151 {
152 GMainContext *ctx;
153 GMainLoop *loop;
154 GInetAddr *ia;
155 GConn *conn;
156
157 ia = gnet_inetaddr_new ("www.sun.com", 80);
158
159 /* it's not fatal if this doesn't work, it's not what we're testing here */
160 if (ia == NULL) {
161 g_print ("Failed to resolve www.sun.com, skipping test.\n");
162 return;
163 }
164
165 ctx = g_main_context_new ();
166 loop = g_main_loop_new (ctx, FALSE);
167
168 ASSERT_CRITICAL (fail_if (gnet_conn_new_inetaddr (NULL, conn_cb, loop)));
169
170 conn = gnet_conn_new_inetaddr (ia, conn_cb, loop);
171 gnet_inetaddr_unref (ia);
172
173 /* should always succeed, we're not connecting yet */
174 fail_unless (conn != NULL);
175
176 gnet_conn_timeout (conn, 5 * 1000);
177 gnet_conn_set_main_context (conn, ctx);
178
179 fail_if (g_main_context_pending (ctx));
180
181 gnet_conn_connect (conn);
182
183 g_main_loop_run (loop);
184
185 gnet_conn_disconnect (conn);
186 gnet_conn_delete (conn);
187
188 fail_if (g_main_context_pending (NULL));
189
190 g_main_context_unref (ctx);
191 g_main_loop_unref (loop);
192 }
193 GNET_END_TEST;
194
GNET_START_TEST(test_conn_new_socket)195 GNET_START_TEST (test_conn_new_socket)
196 {
197 GMainContext *ctx;
198 GMainLoop *loop;
199 GTcpSocket *socket;
200 GConn *conn;
201
202 socket = gnet_tcp_socket_connect ("www.oracle.com", 80);
203
204 /* it's not fatal if this doesn't work, it's not what we're testing here */
205 if (socket == NULL) {
206 g_print ("Failed to resolve+connect to www.oracole.com, skipping test.\n");
207 return;
208 }
209
210 ctx = g_main_context_new ();
211 loop = g_main_loop_new (ctx, FALSE);
212
213 ASSERT_CRITICAL (fail_if (gnet_conn_new_socket (NULL, conn_cb, loop)));
214
215 conn = gnet_conn_new_socket (socket, conn_cb, loop);
216
217 /* conn took ownership of the socket */
218 socket = NULL;
219
220 /* should always succeed */
221 fail_unless (conn != NULL);
222
223 gnet_conn_timeout (conn, 5 * 1000);
224 gnet_conn_set_main_context (conn, ctx);
225
226 fail_if (g_main_context_pending (ctx));
227
228 /* we're already connected, so do fake call to callback so request is sent */
229 {
230 GConnEvent event = { GNET_CONN_CONNECT, NULL, 0 };
231
232 conn_cb (conn, &event, loop);
233 }
234
235 g_main_loop_run (loop);
236
237 gnet_conn_disconnect (conn);
238 gnet_conn_delete (conn);
239
240 fail_if (g_main_context_pending (NULL));
241
242 g_main_context_unref (ctx);
243 g_main_loop_unref (loop);
244 }
245 GNET_END_TEST;
246
247 static Suite *
gnetconn_suite(void)248 gnetconn_suite (void)
249 {
250 Suite *s = suite_create ("GConn");
251 TCase *tc_chain = tcase_create ("conn");
252
253 tcase_set_timeout (tc_chain, 0);
254
255 suite_add_tcase (s, tc_chain);
256
257 #ifdef GNET_ENABLE_NETWORK_TESTS
258 tcase_add_test (tc_chain, test_conn_new);
259 tcase_add_test (tc_chain, test_conn_new_inetaddr);
260 tcase_add_test (tc_chain, test_conn_new_socket);
261 #endif
262
263 return s;
264 }
265
266 GNET_CHECK_MAIN (gnetconn);
267
268