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