Add some more cases to the app-id unit tests
[glib.git] / gio / tests / proxy-test.c
blob0cbe85c562001be2e037f024c600c224fa980221
1 /* GLib testing framework examples and tests
3 * Copyright 2012 Red Hat, Inc.
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General
16 * Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
19 #include <string.h>
21 #define GLIB_VERSION_MIN_REQUIRED GLIB_VERSION_2_34
22 #include <gio/gio.h>
24 /* Overview:
26 * We have an echo server, two proxy servers, two GProxy
27 * implementations, and two GProxyResolver implementations.
29 * The echo server runs at @server.server_addr (on
30 * @server.server_port).
32 * The two proxy servers, A and B, run on @proxy_a.port and
33 * @proxy_b.port, with @proxy_a.uri and @proxy_b.uri pointing to them.
34 * The "negotiation" with the two proxies is just sending the single
35 * letter "a" or "b" and receiving it back in uppercase; the proxy
36 * then connects to @server_addr.
38 * Proxy A supports "alpha://" URIs, and does not support hostname
39 * resolution, and Proxy B supports "beta://" URIs, and does support
40 * hostname resolution (but it just ignores the hostname and always
41 * connects to @server_addr anyway).
43 * The default GProxyResolver (GTestProxyResolver) looks at its URI
44 * and returns [ "direct://" ] for "simple://" URIs, and [
45 * proxy_a.uri, proxy_b.uri ] for other URIs. The other GProxyResolver
46 * (GTestAltProxyResolver) always returns [ proxy_a.uri ].
49 typedef struct {
50 gchar *proxy_command;
51 gchar *supported_protocol;
53 GSocket *server;
54 GThread *thread;
55 GCancellable *cancellable;
56 gchar *uri;
57 gushort port;
59 GSocket *client_sock, *server_sock;
60 GMainLoop *loop;
62 GError *last_error;
63 } ProxyData;
65 static ProxyData proxy_a, proxy_b;
67 typedef struct {
68 GSocket *server;
69 GThread *server_thread;
70 GCancellable *cancellable;
71 GSocketAddress *server_addr;
72 gushort server_port;
73 } ServerData;
75 static ServerData server;
77 static gchar **last_proxies;
79 static GSocketClient *client;
82 /**************************************/
83 /* Test GProxyResolver implementation */
84 /**************************************/
86 typedef struct {
87 GObject parent_instance;
88 } GTestProxyResolver;
90 typedef struct {
91 GObjectClass parent_class;
92 } GTestProxyResolverClass;
94 static void g_test_proxy_resolver_iface_init (GProxyResolverInterface *iface);
96 static GType _g_test_proxy_resolver_get_type (void);
97 #define g_test_proxy_resolver_get_type _g_test_proxy_resolver_get_type
98 G_DEFINE_TYPE_WITH_CODE (GTestProxyResolver, g_test_proxy_resolver, G_TYPE_OBJECT,
99 G_IMPLEMENT_INTERFACE (G_TYPE_PROXY_RESOLVER,
100 g_test_proxy_resolver_iface_init)
101 g_io_extension_point_implement (G_PROXY_RESOLVER_EXTENSION_POINT_NAME,
102 g_define_type_id,
103 "test",
106 static void
107 g_test_proxy_resolver_init (GTestProxyResolver *resolver)
111 static gboolean
112 g_test_proxy_resolver_is_supported (GProxyResolver *resolver)
114 return TRUE;
117 static gchar **
118 g_test_proxy_resolver_lookup (GProxyResolver *resolver,
119 const gchar *uri,
120 GCancellable *cancellable,
121 GError **error)
123 gchar **proxies;
125 g_assert (last_proxies == NULL);
127 if (g_cancellable_set_error_if_cancelled (cancellable, error))
128 return NULL;
130 proxies = g_new (gchar *, 3);
132 if (!strncmp (uri, "simple://", 4))
134 proxies[0] = g_strdup ("direct://");
135 proxies[1] = NULL;
137 else
139 /* Proxy A can only deal with "alpha://" URIs, not
140 * "beta://", but we always return both URIs
141 * anyway so we can test error handling when the first
142 * fails.
144 proxies[0] = g_strdup (proxy_a.uri);
145 proxies[1] = g_strdup (proxy_b.uri);
146 proxies[2] = NULL;
149 last_proxies = g_strdupv (proxies);
151 return proxies;
154 static void
155 g_test_proxy_resolver_lookup_async (GProxyResolver *resolver,
156 const gchar *uri,
157 GCancellable *cancellable,
158 GAsyncReadyCallback callback,
159 gpointer user_data)
161 GError *error = NULL;
162 GTask *task;
163 gchar **proxies;
165 proxies = g_proxy_resolver_lookup (resolver, uri, cancellable, &error);
167 task = g_task_new (resolver, NULL, callback, user_data);
168 if (proxies == NULL)
169 g_task_return_error (task, error);
170 else
171 g_task_return_pointer (task, proxies, (GDestroyNotify) g_strfreev);
173 g_object_unref (task);
176 static gchar **
177 g_test_proxy_resolver_lookup_finish (GProxyResolver *resolver,
178 GAsyncResult *result,
179 GError **error)
181 return g_task_propagate_pointer (G_TASK (result), error);
184 static void
185 g_test_proxy_resolver_class_init (GTestProxyResolverClass *resolver_class)
189 static void
190 g_test_proxy_resolver_iface_init (GProxyResolverInterface *iface)
192 iface->is_supported = g_test_proxy_resolver_is_supported;
193 iface->lookup = g_test_proxy_resolver_lookup;
194 iface->lookup_async = g_test_proxy_resolver_lookup_async;
195 iface->lookup_finish = g_test_proxy_resolver_lookup_finish;
198 /****************************/
199 /* Alternate GProxyResolver */
200 /****************************/
202 typedef GTestProxyResolver GTestAltProxyResolver;
203 typedef GTestProxyResolverClass GTestAltProxyResolverClass;
205 static void g_test_alt_proxy_resolver_iface_init (GProxyResolverInterface *iface);
207 static GType _g_test_alt_proxy_resolver_get_type (void);
208 #define g_test_alt_proxy_resolver_get_type _g_test_alt_proxy_resolver_get_type
209 G_DEFINE_TYPE_WITH_CODE (GTestAltProxyResolver, g_test_alt_proxy_resolver, g_test_proxy_resolver_get_type (),
210 G_IMPLEMENT_INTERFACE (G_TYPE_PROXY_RESOLVER,
211 g_test_alt_proxy_resolver_iface_init);
214 static void
215 g_test_alt_proxy_resolver_init (GTestProxyResolver *resolver)
219 static gchar **
220 g_test_alt_proxy_resolver_lookup (GProxyResolver *resolver,
221 const gchar *uri,
222 GCancellable *cancellable,
223 GError **error)
225 gchar **proxies;
227 proxies = g_new (gchar *, 2);
229 proxies[0] = g_strdup (proxy_a.uri);
230 proxies[1] = NULL;
232 last_proxies = g_strdupv (proxies);
234 return proxies;
237 static void
238 g_test_alt_proxy_resolver_class_init (GTestProxyResolverClass *resolver_class)
242 static void
243 g_test_alt_proxy_resolver_iface_init (GProxyResolverInterface *iface)
245 iface->lookup = g_test_alt_proxy_resolver_lookup;
249 /****************************************/
250 /* Test proxy implementation base class */
251 /****************************************/
253 typedef struct {
254 GObject parent;
256 ProxyData *proxy_data;
257 } GProxyBase;
259 typedef struct {
260 GObjectClass parent_class;
261 } GProxyBaseClass;
263 static GType _g_proxy_base_get_type (void);
264 #define g_proxy_base_get_type _g_proxy_base_get_type
265 G_DEFINE_ABSTRACT_TYPE (GProxyBase, g_proxy_base, G_TYPE_OBJECT)
267 static void
268 g_proxy_base_init (GProxyBase *proxy)
272 static GIOStream *
273 g_proxy_base_connect (GProxy *proxy,
274 GIOStream *io_stream,
275 GProxyAddress *proxy_address,
276 GCancellable *cancellable,
277 GError **error)
279 ProxyData *data = ((GProxyBase *) proxy)->proxy_data;
280 const gchar *protocol;
281 GOutputStream *ostream;
282 GInputStream *istream;
283 gchar response;
285 g_assert_no_error (data->last_error);
287 protocol = g_proxy_address_get_destination_protocol (proxy_address);
288 if (strcmp (protocol, data->supported_protocol) != 0)
290 g_set_error_literal (&data->last_error,
291 G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
292 "Unsupported protocol");
293 goto fail;
296 ostream = g_io_stream_get_output_stream (io_stream);
297 if (g_output_stream_write (ostream, data->proxy_command, 1, cancellable,
298 &data->last_error) != 1)
299 goto fail;
301 istream = g_io_stream_get_input_stream (io_stream);
302 if (g_input_stream_read (istream, &response, 1, cancellable,
303 &data->last_error) != 1)
304 goto fail;
306 if (response != g_ascii_toupper (*data->proxy_command))
308 g_set_error_literal (&data->last_error,
309 G_IO_ERROR, G_IO_ERROR_FAILED,
310 "Failed");
311 goto fail;
314 return g_object_ref (io_stream);
316 fail:
317 g_propagate_error (error, g_error_copy (data->last_error));
318 return NULL;
321 static void
322 g_proxy_base_connect_async (GProxy *proxy,
323 GIOStream *io_stream,
324 GProxyAddress *proxy_address,
325 GCancellable *cancellable,
326 GAsyncReadyCallback callback,
327 gpointer user_data)
329 GError *error = NULL;
330 GTask *task;
331 GIOStream *proxy_io_stream;
333 task = g_task_new (proxy, NULL, callback, user_data);
335 proxy_io_stream = g_proxy_connect (proxy, io_stream, proxy_address,
336 cancellable, &error);
337 if (proxy_io_stream)
338 g_task_return_pointer (task, proxy_io_stream, g_object_unref);
339 else
340 g_task_return_error (task, error);
341 g_object_unref (task);
344 static GIOStream *
345 g_proxy_base_connect_finish (GProxy *proxy,
346 GAsyncResult *result,
347 GError **error)
349 return g_task_propagate_pointer (G_TASK (result), error);
352 static void
353 g_proxy_base_class_init (GProxyBaseClass *class)
358 /********************************************/
359 /* Test proxy implementation #1 ("Proxy A") */
360 /********************************************/
362 typedef GProxyBase GProxyA;
363 typedef GProxyBaseClass GProxyAClass;
365 static void g_proxy_a_iface_init (GProxyInterface *proxy_iface);
367 static GType _g_proxy_a_get_type (void);
368 #define g_proxy_a_get_type _g_proxy_a_get_type
369 G_DEFINE_TYPE_WITH_CODE (GProxyA, g_proxy_a, g_proxy_base_get_type (),
370 G_IMPLEMENT_INTERFACE (G_TYPE_PROXY,
371 g_proxy_a_iface_init)
372 g_io_extension_point_implement (G_PROXY_EXTENSION_POINT_NAME,
373 g_define_type_id,
374 "proxy-a",
377 static void
378 g_proxy_a_init (GProxyA *proxy)
380 ((GProxyBase *) proxy)->proxy_data = &proxy_a;
383 static gboolean
384 g_proxy_a_supports_hostname (GProxy *proxy)
386 return FALSE;
389 static void
390 g_proxy_a_class_init (GProxyAClass *class)
394 static void
395 g_proxy_a_iface_init (GProxyInterface *proxy_iface)
397 proxy_iface->connect = g_proxy_base_connect;
398 proxy_iface->connect_async = g_proxy_base_connect_async;
399 proxy_iface->connect_finish = g_proxy_base_connect_finish;
400 proxy_iface->supports_hostname = g_proxy_a_supports_hostname;
403 /********************************************/
404 /* Test proxy implementation #2 ("Proxy B") */
405 /********************************************/
407 typedef GProxyBase GProxyB;
408 typedef GProxyBaseClass GProxyBClass;
410 static void g_proxy_b_iface_init (GProxyInterface *proxy_iface);
412 static GType _g_proxy_b_get_type (void);
413 #define g_proxy_b_get_type _g_proxy_b_get_type
414 G_DEFINE_TYPE_WITH_CODE (GProxyB, g_proxy_b, g_proxy_base_get_type (),
415 G_IMPLEMENT_INTERFACE (G_TYPE_PROXY,
416 g_proxy_b_iface_init)
417 g_io_extension_point_implement (G_PROXY_EXTENSION_POINT_NAME,
418 g_define_type_id,
419 "proxy-b",
422 static void
423 g_proxy_b_init (GProxyB *proxy)
425 ((GProxyBase *) proxy)->proxy_data = &proxy_b;
428 static gboolean
429 g_proxy_b_supports_hostname (GProxy *proxy)
431 return TRUE;
434 static void
435 g_proxy_b_class_init (GProxyBClass *class)
439 static void
440 g_proxy_b_iface_init (GProxyInterface *proxy_iface)
442 proxy_iface->connect = g_proxy_base_connect;
443 proxy_iface->connect_async = g_proxy_base_connect_async;
444 proxy_iface->connect_finish = g_proxy_base_connect_finish;
445 proxy_iface->supports_hostname = g_proxy_b_supports_hostname;
449 /***********************************/
450 /* The proxy server implementation */
451 /***********************************/
453 static gboolean
454 proxy_bytes (GSocket *socket,
455 GIOCondition condition,
456 gpointer user_data)
458 ProxyData *proxy = user_data;
459 gssize nread, nwrote, total;
460 gchar buffer[8];
461 GSocket *out_socket;
462 GError *error = NULL;
464 nread = g_socket_receive_with_blocking (socket, buffer, sizeof (buffer),
465 TRUE, NULL, &error);
466 if (nread == -1)
468 g_assert_error (error, G_IO_ERROR, G_IO_ERROR_CLOSED);
469 return FALSE;
471 else
472 g_assert_no_error (error);
474 if (nread == 0)
476 g_main_loop_quit (proxy->loop);
477 return FALSE;
480 if (socket == proxy->client_sock)
481 out_socket = proxy->server_sock;
482 else
483 out_socket = proxy->client_sock;
485 for (total = 0; total < nread; total += nwrote)
487 nwrote = g_socket_send_with_blocking (out_socket,
488 buffer + total, nread - total,
489 TRUE, NULL, &error);
490 g_assert_no_error (error);
493 return TRUE;
496 static gpointer
497 proxy_thread (gpointer user_data)
499 ProxyData *proxy = user_data;
500 GError *error = NULL;
501 gssize nread, nwrote;
502 gchar command[2] = { 0, 0 };
503 GMainContext *context;
504 GSource *read_source, *write_source;
506 context = g_main_context_new ();
507 proxy->loop = g_main_loop_new (context, FALSE);
509 while (TRUE)
511 proxy->client_sock = g_socket_accept (proxy->server, proxy->cancellable, &error);
512 if (!proxy->client_sock)
514 g_assert_error (error, G_IO_ERROR, G_IO_ERROR_CANCELLED);
515 g_error_free (error);
516 break;
518 else
519 g_assert_no_error (error);
521 nread = g_socket_receive (proxy->client_sock, command, 1, NULL, &error);
522 g_assert_no_error (error);
524 if (nread == 0)
526 g_clear_object (&proxy->client_sock);
527 continue;
530 g_assert_cmpint (nread, ==, 1);
531 g_assert_cmpstr (command, ==, proxy->proxy_command);
533 *command = g_ascii_toupper (*command);
534 nwrote = g_socket_send (proxy->client_sock, command, 1, NULL, &error);
535 g_assert_no_error (error);
536 g_assert_cmpint (nwrote, ==, 1);
538 proxy->server_sock = g_socket_new (G_SOCKET_FAMILY_IPV4,
539 G_SOCKET_TYPE_STREAM,
540 G_SOCKET_PROTOCOL_DEFAULT,
541 &error);
542 g_assert_no_error (error);
543 g_socket_connect (proxy->server_sock, server.server_addr, NULL, &error);
544 g_assert_no_error (error);
546 read_source = g_socket_create_source (proxy->client_sock, G_IO_IN, NULL);
547 g_source_set_callback (read_source, (GSourceFunc)proxy_bytes, proxy, NULL);
548 g_source_attach (read_source, context);
550 write_source = g_socket_create_source (proxy->server_sock, G_IO_IN, NULL);
551 g_source_set_callback (write_source, (GSourceFunc)proxy_bytes, proxy, NULL);
552 g_source_attach (write_source, context);
554 g_main_loop_run (proxy->loop);
556 g_socket_close (proxy->client_sock, &error);
557 g_assert_no_error (error);
558 g_clear_object (&proxy->client_sock);
560 g_socket_close (proxy->server_sock, &error);
561 g_assert_no_error (error);
562 g_clear_object (&proxy->server_sock);
564 g_source_destroy (read_source);
565 g_source_unref (read_source);
566 g_source_destroy (write_source);
567 g_source_unref (write_source);
570 g_main_loop_unref (proxy->loop);
571 g_main_context_unref (context);
573 g_object_unref (proxy->server);
574 g_object_unref (proxy->cancellable);
576 g_free (proxy->proxy_command);
577 g_free (proxy->supported_protocol);
578 g_free (proxy->uri);
580 return NULL;
583 static void
584 create_proxy (ProxyData *proxy,
585 gchar proxy_protocol,
586 const gchar *destination_protocol,
587 GCancellable *cancellable)
589 GError *error = NULL;
590 GSocketAddress *addr;
591 GInetAddress *iaddr;
593 proxy->proxy_command = g_strdup_printf ("%c", proxy_protocol);
594 proxy->supported_protocol = g_strdup (destination_protocol);
595 proxy->cancellable = g_object_ref (cancellable);
597 proxy->server = g_socket_new (G_SOCKET_FAMILY_IPV4,
598 G_SOCKET_TYPE_STREAM,
599 G_SOCKET_PROTOCOL_DEFAULT,
600 &error);
601 g_assert_no_error (error);
603 iaddr = g_inet_address_new_loopback (G_SOCKET_FAMILY_IPV4);
604 addr = g_inet_socket_address_new (iaddr, 0);
605 g_object_unref (iaddr);
607 g_socket_bind (proxy->server, addr, TRUE, &error);
608 g_assert_no_error (error);
609 g_object_unref (addr);
611 addr = g_socket_get_local_address (proxy->server, &error);
612 proxy->port = g_inet_socket_address_get_port (G_INET_SOCKET_ADDRESS (addr));
613 proxy->uri = g_strdup_printf ("proxy-%c://127.0.0.1:%u",
614 g_ascii_tolower (proxy_protocol),
615 proxy->port);
616 g_object_unref (addr);
618 g_socket_listen (proxy->server, &error);
619 g_assert_no_error (error);
621 proxy->thread = g_thread_new ("proxy", proxy_thread, proxy);
626 /**************************/
627 /* The actual echo server */
628 /**************************/
630 static gpointer
631 echo_server_thread (gpointer user_data)
633 ServerData *data = user_data;
634 GSocket *sock;
635 GError *error = NULL;
636 gssize nread, nwrote;
637 gchar buf[128];
639 while (TRUE)
641 sock = g_socket_accept (data->server, data->cancellable, &error);
642 if (!sock)
644 g_assert_error (error, G_IO_ERROR, G_IO_ERROR_CANCELLED);
645 g_error_free (error);
646 break;
648 else
649 g_assert_no_error (error);
651 while (TRUE)
653 nread = g_socket_receive (sock, buf, sizeof (buf), NULL, &error);
654 g_assert_no_error (error);
655 g_assert_cmpint (nread, >=, 0);
657 if (nread == 0)
658 break;
660 nwrote = g_socket_send (sock, buf, nread, NULL, &error);
661 g_assert_no_error (error);
662 g_assert_cmpint (nwrote, ==, nread);
665 g_socket_close (sock, &error);
666 g_assert_no_error (error);
667 g_object_unref (sock);
670 g_object_unref (data->server);
671 g_object_unref (data->server_addr);
672 g_object_unref (data->cancellable);
674 return NULL;
677 static void
678 create_server (ServerData *data, GCancellable *cancellable)
680 GError *error = NULL;
681 GSocketAddress *addr;
682 GInetAddress *iaddr;
684 data->cancellable = g_object_ref (cancellable);
686 data->server = g_socket_new (G_SOCKET_FAMILY_IPV4,
687 G_SOCKET_TYPE_STREAM,
688 G_SOCKET_PROTOCOL_DEFAULT,
689 &error);
690 g_assert_no_error (error);
692 g_socket_set_blocking (data->server, TRUE);
693 iaddr = g_inet_address_new_loopback (G_SOCKET_FAMILY_IPV4);
694 addr = g_inet_socket_address_new (iaddr, 0);
695 g_object_unref (iaddr);
697 g_socket_bind (data->server, addr, TRUE, &error);
698 g_assert_no_error (error);
699 g_object_unref (addr);
701 data->server_addr = g_socket_get_local_address (data->server, &error);
702 g_assert_no_error (error);
704 data->server_port = g_inet_socket_address_get_port (G_INET_SOCKET_ADDRESS (data->server_addr));
706 g_socket_listen (data->server, &error);
707 g_assert_no_error (error);
709 data->server_thread = g_thread_new ("server", echo_server_thread, data);
713 /******************************************************************/
714 /* Now a GResolver implementation, so the can't-resolve test will */
715 /* pass even if you have an evil DNS-faking ISP. */
716 /******************************************************************/
718 typedef GResolver GFakeResolver;
719 typedef GResolverClass GFakeResolverClass;
721 static GType g_fake_resolver_get_type (void);
722 G_DEFINE_TYPE (GFakeResolver, g_fake_resolver, G_TYPE_RESOLVER)
724 static void
725 g_fake_resolver_init (GFakeResolver *gtr)
729 static GList *
730 g_fake_resolver_lookup_by_name (GResolver *resolver,
731 const gchar *hostname,
732 GCancellable *cancellable,
733 GError **error)
735 if (!strcmp (hostname, "example.com"))
736 return g_list_prepend (NULL, g_inet_address_new_from_string ("127.0.0.1"));
737 else
739 /* Anything else is expected to fail. */
740 g_set_error (error,
741 G_RESOLVER_ERROR,
742 G_RESOLVER_ERROR_NOT_FOUND,
743 "Not found");
744 return NULL;
748 static void
749 g_fake_resolver_lookup_by_name_async (GResolver *resolver,
750 const gchar *hostname,
751 GCancellable *cancellable,
752 GAsyncReadyCallback callback,
753 gpointer user_data)
755 GTask *task;
757 task = g_task_new (resolver, cancellable, callback, user_data);
759 if (!strcmp (hostname, "example.com"))
761 GList *result;
763 result = g_list_prepend (NULL, g_inet_address_new_from_string ("127.0.0.1"));
764 g_task_return_pointer (task, result, (GDestroyNotify) g_resolver_free_addresses);
766 else
768 g_task_return_new_error (task,
769 G_RESOLVER_ERROR, G_RESOLVER_ERROR_NOT_FOUND,
770 "Not found");
772 g_object_unref (task);
775 static GList *
776 g_fake_resolver_lookup_by_name_finish (GResolver *resolver,
777 GAsyncResult *result,
778 GError **error)
780 return g_task_propagate_pointer (G_TASK (result), error);
783 static void
784 g_fake_resolver_class_init (GFakeResolverClass *fake_class)
786 GResolverClass *resolver_class = G_RESOLVER_CLASS (fake_class);
788 resolver_class->lookup_by_name = g_fake_resolver_lookup_by_name;
789 resolver_class->lookup_by_name_async = g_fake_resolver_lookup_by_name_async;
790 resolver_class->lookup_by_name_finish = g_fake_resolver_lookup_by_name_finish;
795 /****************************************/
796 /* We made it! Now for the actual test! */
797 /****************************************/
799 static void
800 setup_test (gpointer fixture,
801 gconstpointer user_data)
805 static void
806 teardown_test (gpointer fixture,
807 gconstpointer user_data)
809 if (last_proxies)
811 g_strfreev (last_proxies);
812 last_proxies = NULL;
814 g_clear_error (&proxy_a.last_error);
815 g_clear_error (&proxy_b.last_error);
819 static const gchar *testbuf = "0123456789abcdef";
821 static void
822 do_echo_test (GSocketConnection *conn)
824 GIOStream *iostream = G_IO_STREAM (conn);
825 GInputStream *istream = g_io_stream_get_input_stream (iostream);
826 GOutputStream *ostream = g_io_stream_get_output_stream (iostream);
827 gssize nread, total;
828 gsize nwrote;
829 gchar buf[128];
830 GError *error = NULL;
832 g_output_stream_write_all (ostream, testbuf, strlen (testbuf),
833 &nwrote, NULL, &error);
834 g_assert_no_error (error);
835 g_assert_cmpint (nwrote, ==, strlen (testbuf));
837 for (total = 0; total < nwrote; total += nread)
839 nread = g_input_stream_read (istream,
840 buf + total, sizeof (buf) - total,
841 NULL, &error);
842 g_assert_no_error (error);
843 g_assert_cmpint (nread, >, 0);
846 buf[total] = '\0';
847 g_assert_cmpstr (buf, ==, testbuf);
850 static void
851 async_got_conn (GObject *source,
852 GAsyncResult *result,
853 gpointer user_data)
855 GSocketConnection **conn = user_data;
856 GError *error = NULL;
858 *conn = g_socket_client_connect_finish (G_SOCKET_CLIENT (source),
859 result, &error);
860 g_assert_no_error (error);
863 static void
864 async_got_error (GObject *source,
865 GAsyncResult *result,
866 gpointer user_data)
868 GError **error = user_data;
870 g_assert (error != NULL && *error == NULL);
871 g_socket_client_connect_finish (G_SOCKET_CLIENT (source),
872 result, error);
873 g_assert (*error != NULL);
877 static void
878 assert_direct (GSocketConnection *conn)
880 GSocketAddress *addr;
881 GError *error = NULL;
883 g_assert_cmpint (g_strv_length (last_proxies), ==, 1);
884 g_assert_cmpstr (last_proxies[0], ==, "direct://");
885 g_assert_no_error (proxy_a.last_error);
886 g_assert_no_error (proxy_b.last_error);
888 addr = g_socket_connection_get_remote_address (conn, &error);
889 g_assert_no_error (error);
890 g_assert (addr != NULL && !G_IS_PROXY_ADDRESS (addr));
891 g_object_unref (addr);
893 addr = g_socket_connection_get_local_address (conn, &error);
894 g_assert_no_error (error);
895 g_object_unref (addr);
897 g_assert (g_socket_connection_is_connected (conn));
900 static void
901 test_direct_sync (gpointer fixture,
902 gconstpointer user_data)
904 GSocketConnection *conn;
905 gchar *uri;
906 GError *error = NULL;
908 /* The simple:// URI should not require any proxy. */
910 uri = g_strdup_printf ("simple://127.0.0.1:%u", server.server_port);
911 conn = g_socket_client_connect_to_uri (client, uri, 0, NULL, &error);
912 g_free (uri);
913 g_assert_no_error (error);
915 assert_direct (conn);
916 do_echo_test (conn);
917 g_object_unref (conn);
920 static void
921 test_direct_async (gpointer fixture,
922 gconstpointer user_data)
924 GSocketConnection *conn;
925 gchar *uri;
927 /* The simple:// URI should not require any proxy. */
928 uri = g_strdup_printf ("simple://127.0.0.1:%u", server.server_port);
929 conn = NULL;
930 g_socket_client_connect_to_uri_async (client, uri, 0, NULL,
931 async_got_conn, &conn);
932 g_free (uri);
933 while (conn == NULL)
934 g_main_context_iteration (NULL, TRUE);
936 assert_direct (conn);
937 do_echo_test (conn);
938 g_object_unref (conn);
941 static void
942 assert_single (GSocketConnection *conn)
944 GSocketAddress *addr;
945 const gchar *proxy_uri;
946 gushort proxy_port;
947 GError *error = NULL;
949 g_assert_cmpint (g_strv_length (last_proxies), ==, 2);
950 g_assert_cmpstr (last_proxies[0], ==, proxy_a.uri);
951 g_assert_cmpstr (last_proxies[1], ==, proxy_b.uri);
952 g_assert_no_error (proxy_a.last_error);
953 g_assert_no_error (proxy_b.last_error);
955 addr = g_socket_connection_get_remote_address (conn, &error);
956 g_assert_no_error (error);
957 g_assert (G_IS_PROXY_ADDRESS (addr));
958 proxy_uri = g_proxy_address_get_uri (G_PROXY_ADDRESS (addr));
959 g_assert_cmpstr (proxy_uri, ==, proxy_a.uri);
960 proxy_port = g_inet_socket_address_get_port (G_INET_SOCKET_ADDRESS (addr));
961 g_assert_cmpint (proxy_port, ==, proxy_a.port);
963 g_object_unref (addr);
966 static void
967 test_single_sync (gpointer fixture,
968 gconstpointer user_data)
970 GSocketConnection *conn;
971 GError *error = NULL;
972 gchar *uri;
974 /* The alpha:// URI should be proxied via Proxy A */
975 uri = g_strdup_printf ("alpha://127.0.0.1:%u", server.server_port);
976 conn = g_socket_client_connect_to_uri (client, uri, 0, NULL, &error);
977 g_free (uri);
978 g_assert_no_error (error);
980 assert_single (conn);
982 do_echo_test (conn);
983 g_object_unref (conn);
986 static void
987 test_single_async (gpointer fixture,
988 gconstpointer user_data)
990 GSocketConnection *conn;
991 gchar *uri;
993 /* The alpha:// URI should be proxied via Proxy A */
994 uri = g_strdup_printf ("alpha://127.0.0.1:%u", server.server_port);
995 conn = NULL;
996 g_socket_client_connect_to_uri_async (client, uri, 0, NULL,
997 async_got_conn, &conn);
998 g_free (uri);
999 while (conn == NULL)
1000 g_main_context_iteration (NULL, TRUE);
1002 assert_single (conn);
1003 do_echo_test (conn);
1004 g_object_unref (conn);
1007 static void
1008 assert_multiple (GSocketConnection *conn)
1010 GSocketAddress *addr;
1011 const gchar *proxy_uri;
1012 gushort proxy_port;
1013 GError *error = NULL;
1015 g_assert_cmpint (g_strv_length (last_proxies), ==, 2);
1016 g_assert_cmpstr (last_proxies[0], ==, proxy_a.uri);
1017 g_assert_cmpstr (last_proxies[1], ==, proxy_b.uri);
1018 g_assert_error (proxy_a.last_error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED);
1019 g_assert_no_error (proxy_b.last_error);
1021 addr = g_socket_connection_get_remote_address (conn, &error);
1022 g_assert_no_error (error);
1023 g_assert (G_IS_PROXY_ADDRESS (addr));
1024 proxy_uri = g_proxy_address_get_uri (G_PROXY_ADDRESS (addr));
1025 g_assert_cmpstr (proxy_uri, ==, proxy_b.uri);
1026 proxy_port = g_inet_socket_address_get_port (G_INET_SOCKET_ADDRESS (addr));
1027 g_assert_cmpint (proxy_port, ==, proxy_b.port);
1029 g_object_unref (addr);
1032 static void
1033 test_multiple_sync (gpointer fixture,
1034 gconstpointer user_data)
1036 GSocketConnection *conn;
1037 GError *error = NULL;
1038 gchar *uri;
1040 /* The beta:// URI should be proxied via Proxy B, after failing
1041 * via Proxy A.
1043 uri = g_strdup_printf ("beta://127.0.0.1:%u", server.server_port);
1044 conn = g_socket_client_connect_to_uri (client, uri, 0, NULL, &error);
1045 g_free (uri);
1046 g_assert_no_error (error);
1048 assert_multiple (conn);
1049 do_echo_test (conn);
1050 g_object_unref (conn);
1053 static void
1054 test_multiple_async (gpointer fixture,
1055 gconstpointer user_data)
1057 GSocketConnection *conn;
1058 gchar *uri;
1060 /* The beta:// URI should be proxied via Proxy B, after failing
1061 * via Proxy A.
1063 uri = g_strdup_printf ("beta://127.0.0.1:%u", server.server_port);
1064 conn = NULL;
1065 g_socket_client_connect_to_uri_async (client, uri, 0, NULL,
1066 async_got_conn, &conn);
1067 g_free (uri);
1068 while (conn == NULL)
1069 g_main_context_iteration (NULL, TRUE);
1071 assert_multiple (conn);
1072 do_echo_test (conn);
1073 g_object_unref (conn);
1076 static void
1077 test_dns (gpointer fixture,
1078 gconstpointer user_data)
1080 GSocketConnection *conn;
1081 GError *error = NULL;
1082 gchar *uri;
1084 /* The simple:// and alpha:// URIs should fail with a DNS error,
1085 * but the beta:// URI should succeed, because we pass it to
1086 * Proxy B without trying to resolve it first
1089 /* simple */
1090 uri = g_strdup_printf ("simple://no-such-host.xx:%u", server.server_port);
1091 conn = g_socket_client_connect_to_uri (client, uri, 0, NULL, &error);
1092 g_assert_error (error, G_RESOLVER_ERROR, G_RESOLVER_ERROR_NOT_FOUND);
1093 g_clear_error (&error);
1095 g_assert_no_error (proxy_a.last_error);
1096 g_assert_no_error (proxy_b.last_error);
1097 teardown_test (NULL, NULL);
1099 g_socket_client_connect_to_uri_async (client, uri, 0, NULL,
1100 async_got_error, &error);
1101 while (error == NULL)
1102 g_main_context_iteration (NULL, TRUE);
1103 g_assert_error (error, G_RESOLVER_ERROR, G_RESOLVER_ERROR_NOT_FOUND);
1104 g_clear_error (&error);
1105 g_free (uri);
1107 g_assert_no_error (proxy_a.last_error);
1108 g_assert_no_error (proxy_b.last_error);
1109 teardown_test (NULL, NULL);
1111 /* alpha */
1112 uri = g_strdup_printf ("alpha://no-such-host.xx:%u", server.server_port);
1113 conn = g_socket_client_connect_to_uri (client, uri, 0, NULL, &error);
1114 /* Since Proxy A fails, @client will try Proxy B too, which won't
1115 * load an alpha:// URI.
1117 g_assert_error (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED);
1118 g_clear_error (&error);
1120 g_assert_no_error (proxy_a.last_error);
1121 g_assert_error (proxy_b.last_error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED);
1122 teardown_test (NULL, NULL);
1124 g_socket_client_connect_to_uri_async (client, uri, 0, NULL,
1125 async_got_error, &error);
1126 while (error == NULL)
1127 g_main_context_iteration (NULL, TRUE);
1128 g_assert_error (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED);
1129 g_clear_error (&error);
1130 g_free (uri);
1132 g_assert_no_error (proxy_a.last_error);
1133 g_assert_error (proxy_b.last_error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED);
1134 teardown_test (NULL, NULL);
1136 /* beta */
1137 uri = g_strdup_printf ("beta://no-such-host.xx:%u", server.server_port);
1138 conn = g_socket_client_connect_to_uri (client, uri, 0, NULL, &error);
1139 g_assert_no_error (error);
1141 g_assert_no_error (proxy_a.last_error);
1142 g_assert_no_error (proxy_b.last_error);
1144 do_echo_test (conn);
1145 g_clear_object (&conn);
1146 teardown_test (NULL, NULL);
1148 g_socket_client_connect_to_uri_async (client, uri, 0, NULL,
1149 async_got_conn, &conn);
1150 while (conn == NULL)
1151 g_main_context_iteration (NULL, TRUE);
1152 g_free (uri);
1154 g_assert_no_error (proxy_a.last_error);
1155 g_assert_no_error (proxy_b.last_error);
1157 do_echo_test (conn);
1158 g_clear_object (&conn);
1159 teardown_test (NULL, NULL);
1162 static void
1163 assert_override (GSocketConnection *conn)
1165 g_assert_cmpint (g_strv_length (last_proxies), ==, 1);
1166 g_assert_cmpstr (last_proxies[0], ==, proxy_a.uri);
1168 if (conn)
1169 g_assert_no_error (proxy_a.last_error);
1170 else
1171 g_assert_error (proxy_a.last_error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED);
1174 static void
1175 test_override (gpointer fixture,
1176 gconstpointer user_data)
1178 GProxyResolver *alt_resolver;
1179 GSocketConnection *conn;
1180 GError *error = NULL;
1181 gchar *uri;
1183 g_assert (g_socket_client_get_proxy_resolver (client) == g_proxy_resolver_get_default ());
1184 alt_resolver = g_object_new (g_test_alt_proxy_resolver_get_type (), NULL);
1185 g_socket_client_set_proxy_resolver (client, alt_resolver);
1186 g_assert (g_socket_client_get_proxy_resolver (client) == alt_resolver);
1188 /* Alt proxy resolver always returns Proxy A, so alpha:// should
1189 * succeed, and simple:// and beta:// should fail.
1192 /* simple */
1193 uri = g_strdup_printf ("simple://127.0.0.1:%u", server.server_port);
1194 conn = g_socket_client_connect_to_uri (client, uri, 0, NULL, &error);
1195 g_assert_error (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED);
1196 g_clear_error (&error);
1197 assert_override (conn);
1198 teardown_test (NULL, NULL);
1200 g_socket_client_connect_to_uri_async (client, uri, 0, NULL,
1201 async_got_error, &error);
1202 while (error == NULL)
1203 g_main_context_iteration (NULL, TRUE);
1204 g_assert_error (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED);
1205 g_clear_error (&error);
1206 assert_override (conn);
1207 g_free (uri);
1208 teardown_test (NULL, NULL);
1210 /* alpha */
1211 uri = g_strdup_printf ("alpha://127.0.0.1:%u", server.server_port);
1212 conn = g_socket_client_connect_to_uri (client, uri, 0, NULL, &error);
1213 g_assert_no_error (error);
1214 assert_override (conn);
1215 do_echo_test (conn);
1216 g_clear_object (&conn);
1217 teardown_test (NULL, NULL);
1219 conn = NULL;
1220 g_socket_client_connect_to_uri_async (client, uri, 0, NULL,
1221 async_got_conn, &conn);
1222 while (conn == NULL)
1223 g_main_context_iteration (NULL, TRUE);
1224 assert_override (conn);
1225 do_echo_test (conn);
1226 g_clear_object (&conn);
1227 g_free (uri);
1228 teardown_test (NULL, NULL);
1230 /* beta */
1231 uri = g_strdup_printf ("beta://127.0.0.1:%u", server.server_port);
1232 conn = g_socket_client_connect_to_uri (client, uri, 0, NULL, &error);
1233 g_assert_error (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED);
1234 g_clear_error (&error);
1235 assert_override (conn);
1236 teardown_test (NULL, NULL);
1238 g_socket_client_connect_to_uri_async (client, uri, 0, NULL,
1239 async_got_error, &error);
1240 while (error == NULL)
1241 g_main_context_iteration (NULL, TRUE);
1242 g_assert_error (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED);
1243 g_clear_error (&error);
1244 assert_override (conn);
1245 g_free (uri);
1246 teardown_test (NULL, NULL);
1248 g_assert (g_socket_client_get_proxy_resolver (client) == alt_resolver);
1249 g_socket_client_set_proxy_resolver (client, NULL);
1250 g_assert (g_socket_client_get_proxy_resolver (client) == g_proxy_resolver_get_default ());
1251 g_object_unref (alt_resolver);
1254 static void
1255 assert_destination_port (GSocketAddressEnumerator *etor,
1256 guint16 port)
1258 GSocketAddress *addr;
1259 GProxyAddress *paddr;
1260 GError *error = NULL;
1262 while ((addr = g_socket_address_enumerator_next (etor, NULL, &error)))
1264 g_assert_no_error (error);
1266 g_assert (G_IS_PROXY_ADDRESS (addr));
1267 paddr = G_PROXY_ADDRESS (addr);
1268 g_assert_cmpint (g_proxy_address_get_destination_port (paddr), ==, port);
1269 g_object_unref (addr);
1271 g_assert_no_error (error);
1274 static void
1275 test_proxy_enumerator_ports (void)
1277 GSocketAddressEnumerator *etor;
1279 etor = g_object_new (G_TYPE_PROXY_ADDRESS_ENUMERATOR,
1280 "uri", "http://example.com/",
1281 NULL);
1282 assert_destination_port (etor, 0);
1283 g_object_unref (etor);
1285 /* Have to call this to clear last_proxies so the next call to
1286 * g_test_proxy_resolver_lookup() won't assert.
1288 teardown_test (NULL, NULL);
1290 etor = g_object_new (G_TYPE_PROXY_ADDRESS_ENUMERATOR,
1291 "uri", "http://example.com:8080/",
1292 NULL);
1293 assert_destination_port (etor, 8080);
1294 g_object_unref (etor);
1296 teardown_test (NULL, NULL);
1298 etor = g_object_new (G_TYPE_PROXY_ADDRESS_ENUMERATOR,
1299 "uri", "http://example.com/",
1300 "default-port", 80,
1301 NULL);
1302 assert_destination_port (etor, 80);
1303 g_object_unref (etor);
1305 teardown_test (NULL, NULL);
1307 etor = g_object_new (G_TYPE_PROXY_ADDRESS_ENUMERATOR,
1308 "uri", "http://example.com:8080/",
1309 "default-port", 80,
1310 NULL);
1311 assert_destination_port (etor, 8080);
1312 g_object_unref (etor);
1314 teardown_test (NULL, NULL);
1318 main (int argc,
1319 char *argv[])
1321 GResolver *fake_resolver;
1322 GCancellable *cancellable;
1323 gint result;
1325 g_test_init (&argc, &argv, NULL);
1327 /* Register stuff. The dummy g_proxy_get_default_for_protocol() call
1328 * is to force _g_io_modules_ensure_extension_points_registered() to
1329 * get called, so we can then register a proxy resolver extension
1330 * point.
1332 g_proxy_get_default_for_protocol ("foo");
1333 g_test_proxy_resolver_get_type ();
1334 g_proxy_a_get_type ();
1335 g_proxy_b_get_type ();
1336 g_setenv ("GIO_USE_PROXY_RESOLVER", "test", TRUE);
1338 fake_resolver = g_object_new (g_fake_resolver_get_type (), NULL);
1339 g_resolver_set_default (fake_resolver);
1341 cancellable = g_cancellable_new ();
1342 create_server (&server, cancellable);
1343 create_proxy (&proxy_a, 'a', "alpha", cancellable);
1344 create_proxy (&proxy_b, 'b', "beta", cancellable);
1346 client = g_socket_client_new ();
1347 g_assert_cmpint (g_socket_client_get_enable_proxy (client), ==, TRUE);
1349 g_test_add_vtable ("/proxy/direct_sync", 0, NULL, setup_test, test_direct_sync, teardown_test);
1350 g_test_add_vtable ("/proxy/direct_async", 0, NULL, setup_test, test_direct_async, teardown_test);
1351 g_test_add_vtable ("/proxy/single_sync", 0, NULL, setup_test, test_single_sync, teardown_test);
1352 g_test_add_vtable ("/proxy/single_async", 0, NULL, setup_test, test_single_async, teardown_test);
1353 g_test_add_vtable ("/proxy/multiple_sync", 0, NULL, setup_test, test_multiple_sync, teardown_test);
1354 g_test_add_vtable ("/proxy/multiple_async", 0, NULL, setup_test, test_multiple_async, teardown_test);
1355 g_test_add_vtable ("/proxy/dns", 0, NULL, setup_test, test_dns, teardown_test);
1356 g_test_add_vtable ("/proxy/override", 0, NULL, setup_test, test_override, teardown_test);
1357 g_test_add_func ("/proxy/enumerator-ports", test_proxy_enumerator_ports);
1359 result = g_test_run();
1361 g_object_unref (client);
1363 g_cancellable_cancel (cancellable);
1364 g_thread_join (proxy_a.thread);
1365 g_thread_join (proxy_b.thread);
1366 g_thread_join (server.server_thread);
1368 g_object_unref (cancellable);
1370 return result;