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, write to the
17 * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
18 * Boston, MA 02111-1307, USA.
23 #define GLIB_VERSION_MIN_REQUIRED GLIB_VERSION_2_34
28 * We have an echo server, two proxy servers, two GProxy
29 * implementations, and a GProxyResolver implementation.
31 * The echo server runs at @server.server_addr (on
32 * @server.server_port).
34 * The two proxy servers, A and B, run on @proxy_a.port and
35 * @proxy_b.port, with @proxy_a.uri and @proxy_b.uri pointing to them.
36 * The "negotiation" with the two proxies is just sending the single
37 * letter "a" or "b" and receiving it back in uppercase; the proxy
38 * then connects to @server_addr.
40 * Proxy A supports "alpha://" URIs, and does not support hostname
41 * resolution, and Proxy B supports "beta://" URIs, and does support
42 * hostname resolution (but it just ignores the hostname and always
43 * connects to @server_addr anyway).
45 * The GProxyResolver (GTestProxyResolver) looks at its URI and
46 * returns [ "direct://" ] for "simple://" URIs, and [ proxy_a.uri,
47 * proxy_b.uri ] for other URIs.
52 gchar *supported_protocol;
56 GCancellable *cancellable;
60 GSocket *client_sock, *server_sock;
66 static ProxyData proxy_a, proxy_b;
70 GThread *server_thread;
71 GCancellable *cancellable;
72 GSocketAddress *server_addr;
76 static ServerData server;
78 static gchar **last_proxies;
80 static GSocketClient *client;
83 /**************************************/
84 /* Test GProxyResolver implementation */
85 /**************************************/
88 GObject parent_instance;
92 GObjectClass parent_class;
93 } GTestProxyResolverClass;
95 static void g_test_proxy_resolver_iface_init (GProxyResolverInterface *iface);
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,
107 g_test_proxy_resolver_init (GTestProxyResolver *resolver)
112 g_test_proxy_resolver_is_supported (GProxyResolver *resolver)
118 g_test_proxy_resolver_lookup (GProxyResolver *resolver,
120 GCancellable *cancellable,
125 g_assert (last_proxies == NULL);
127 if (g_cancellable_set_error_if_cancelled (cancellable, error))
130 proxies = g_new (gchar *, 3);
132 if (!strncmp (uri, "simple://", 4))
134 proxies[0] = g_strdup ("direct://");
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
144 proxies[0] = g_strdup (proxy_a.uri);
145 proxies[1] = g_strdup (proxy_b.uri);
149 last_proxies = g_strdupv (proxies);
155 g_test_proxy_resolver_lookup_async (GProxyResolver *resolver,
157 GCancellable *cancellable,
158 GAsyncReadyCallback callback,
161 GError *error = NULL;
162 GSimpleAsyncResult *simple;
165 proxies = g_test_proxy_resolver_lookup (resolver, uri, cancellable, &error);
167 simple = g_simple_async_result_new (G_OBJECT (resolver),
169 g_test_proxy_resolver_lookup_async);
172 g_simple_async_result_take_error (simple, error);
174 g_simple_async_result_set_op_res_gpointer (simple, proxies, (GDestroyNotify) g_strfreev);
176 g_simple_async_result_complete_in_idle (simple);
177 g_object_unref (simple);
181 g_test_proxy_resolver_lookup_finish (GProxyResolver *resolver,
182 GAsyncResult *result,
185 if (G_IS_SIMPLE_ASYNC_RESULT (result))
187 GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (result);
190 if (g_simple_async_result_propagate_error (simple, error))
193 proxies = g_simple_async_result_get_op_res_gpointer (simple);
194 return g_strdupv (proxies);
201 g_test_proxy_resolver_class_init (GTestProxyResolverClass *resolver_class)
206 g_test_proxy_resolver_iface_init (GProxyResolverInterface *iface)
208 iface->is_supported = g_test_proxy_resolver_is_supported;
209 iface->lookup = g_test_proxy_resolver_lookup;
210 iface->lookup_async = g_test_proxy_resolver_lookup_async;
211 iface->lookup_finish = g_test_proxy_resolver_lookup_finish;
215 /****************************************/
216 /* Test proxy implementation base class */
217 /****************************************/
222 ProxyData *proxy_data;
226 GObjectClass parent_class;
229 #define g_proxy_base_get_type _g_proxy_base_get_type
230 G_DEFINE_ABSTRACT_TYPE (GProxyBase, g_proxy_base, G_TYPE_OBJECT)
233 g_proxy_base_init (GProxyBase *proxy)
238 g_proxy_base_connect (GProxy *proxy,
239 GIOStream *io_stream,
240 GProxyAddress *proxy_address,
241 GCancellable *cancellable,
244 ProxyData *data = ((GProxyBase *) proxy)->proxy_data;
245 const gchar *protocol;
246 GOutputStream *ostream;
247 GInputStream *istream;
250 g_assert_no_error (data->last_error);
252 protocol = g_proxy_address_get_destination_protocol (proxy_address);
253 if (strcmp (protocol, data->supported_protocol) != 0)
255 g_set_error_literal (&data->last_error,
256 G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
257 "Unsupported protocol");
261 ostream = g_io_stream_get_output_stream (io_stream);
262 if (g_output_stream_write (ostream, data->proxy_command, 1, cancellable,
263 &data->last_error) != 1)
266 istream = g_io_stream_get_input_stream (io_stream);
267 if (g_input_stream_read (istream, &response, 1, cancellable,
268 &data->last_error) != 1)
271 if (response != g_ascii_toupper (*data->proxy_command))
273 g_set_error_literal (&data->last_error,
274 G_IO_ERROR, G_IO_ERROR_FAILED,
279 return g_object_ref (io_stream);
282 g_propagate_error (error, g_error_copy (data->last_error));
287 g_proxy_base_connect_async (GProxy *proxy,
288 GIOStream *io_stream,
289 GProxyAddress *proxy_address,
290 GCancellable *cancellable,
291 GAsyncReadyCallback callback,
294 GError *error = NULL;
295 GSimpleAsyncResult *simple;
296 GIOStream *proxy_io_stream;
298 simple = g_simple_async_result_new (G_OBJECT (proxy),
300 g_proxy_base_connect_async);
302 proxy_io_stream = g_proxy_connect (proxy, io_stream, proxy_address,
303 cancellable, &error);
306 g_simple_async_result_set_op_res_gpointer (simple, proxy_io_stream,
310 g_simple_async_result_take_error (simple, error);
311 g_simple_async_result_complete_in_idle (simple);
312 g_object_unref (simple);
316 g_proxy_base_connect_finish (GProxy *proxy,
317 GAsyncResult *result,
320 GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (result);
322 if (g_simple_async_result_propagate_error (simple, error))
325 return g_object_ref (g_simple_async_result_get_op_res_gpointer (simple));
329 g_proxy_base_class_init (GProxyBaseClass *class)
334 /********************************************/
335 /* Test proxy implementation #1 ("Proxy A") */
336 /********************************************/
338 typedef GProxyBase GProxyA;
339 typedef GProxyBaseClass GProxyAClass;
341 static void g_proxy_a_iface_init (GProxyInterface *proxy_iface);
343 #define g_proxy_a_get_type _g_proxy_a_get_type
344 G_DEFINE_TYPE_WITH_CODE (GProxyA, g_proxy_a, g_proxy_base_get_type (),
345 G_IMPLEMENT_INTERFACE (G_TYPE_PROXY,
346 g_proxy_a_iface_init)
347 g_io_extension_point_implement (G_PROXY_EXTENSION_POINT_NAME,
353 g_proxy_a_init (GProxyA *proxy)
355 ((GProxyBase *) proxy)->proxy_data = &proxy_a;
359 g_proxy_a_supports_hostname (GProxy *proxy)
365 g_proxy_a_class_init (GProxyAClass *class)
370 g_proxy_a_iface_init (GProxyInterface *proxy_iface)
372 proxy_iface->connect = g_proxy_base_connect;
373 proxy_iface->connect_async = g_proxy_base_connect_async;
374 proxy_iface->connect_finish = g_proxy_base_connect_finish;
375 proxy_iface->supports_hostname = g_proxy_a_supports_hostname;
378 /********************************************/
379 /* Test proxy implementation #2 ("Proxy B") */
380 /********************************************/
382 typedef GProxyBase GProxyB;
383 typedef GProxyBaseClass GProxyBClass;
385 static void g_proxy_b_iface_init (GProxyInterface *proxy_iface);
387 #define g_proxy_b_get_type _g_proxy_b_get_type
388 G_DEFINE_TYPE_WITH_CODE (GProxyB, g_proxy_b, g_proxy_base_get_type (),
389 G_IMPLEMENT_INTERFACE (G_TYPE_PROXY,
390 g_proxy_b_iface_init)
391 g_io_extension_point_implement (G_PROXY_EXTENSION_POINT_NAME,
397 g_proxy_b_init (GProxyB *proxy)
399 ((GProxyBase *) proxy)->proxy_data = &proxy_b;
403 g_proxy_b_supports_hostname (GProxy *proxy)
409 g_proxy_b_class_init (GProxyBClass *class)
414 g_proxy_b_iface_init (GProxyInterface *proxy_iface)
416 proxy_iface->connect = g_proxy_base_connect;
417 proxy_iface->connect_async = g_proxy_base_connect_async;
418 proxy_iface->connect_finish = g_proxy_base_connect_finish;
419 proxy_iface->supports_hostname = g_proxy_b_supports_hostname;
423 /***********************************/
424 /* The proxy server implementation */
425 /***********************************/
428 proxy_bytes (GSocket *socket,
429 GIOCondition condition,
432 ProxyData *proxy = user_data;
433 gssize nread, nwrote, total;
436 GError *error = NULL;
438 nread = g_socket_receive_with_blocking (socket, buffer, sizeof (buffer),
442 g_assert_error (error, G_IO_ERROR, G_IO_ERROR_CLOSED);
446 g_assert_no_error (error);
450 g_main_loop_quit (proxy->loop);
454 if (socket == proxy->client_sock)
455 out_socket = proxy->server_sock;
457 out_socket = proxy->client_sock;
459 for (total = 0; total < nread; total += nwrote)
461 nwrote = g_socket_send_with_blocking (out_socket,
462 buffer + total, nread - total,
464 g_assert_no_error (error);
471 proxy_thread (gpointer user_data)
473 ProxyData *proxy = user_data;
474 GError *error = NULL;
475 gssize nread, nwrote;
476 gchar command[2] = { 0, 0 };
477 GMainContext *context;
478 GSource *read_source, *write_source;
480 context = g_main_context_new ();
481 proxy->loop = g_main_loop_new (context, FALSE);
485 proxy->client_sock = g_socket_accept (proxy->server, proxy->cancellable, &error);
486 if (!proxy->client_sock)
488 g_assert_error (error, G_IO_ERROR, G_IO_ERROR_CANCELLED);
489 g_error_free (error);
493 g_assert_no_error (error);
495 nread = g_socket_receive (proxy->client_sock, command, 1, NULL, &error);
496 g_assert_no_error (error);
500 g_clear_object (&proxy->client_sock);
504 g_assert_cmpint (nread, ==, 1);
505 g_assert_cmpstr (command, ==, proxy->proxy_command);
507 *command = g_ascii_toupper (*command);
508 nwrote = g_socket_send (proxy->client_sock, command, 1, NULL, &error);
509 g_assert_no_error (error);
510 g_assert_cmpint (nwrote, ==, 1);
512 proxy->server_sock = g_socket_new (G_SOCKET_FAMILY_IPV4,
513 G_SOCKET_TYPE_STREAM,
514 G_SOCKET_PROTOCOL_DEFAULT,
516 g_assert_no_error (error);
517 g_socket_connect (proxy->server_sock, server.server_addr, NULL, &error);
518 g_assert_no_error (error);
520 read_source = g_socket_create_source (proxy->client_sock, G_IO_IN, NULL);
521 g_source_set_callback (read_source, (GSourceFunc)proxy_bytes, proxy, NULL);
522 g_source_attach (read_source, context);
524 write_source = g_socket_create_source (proxy->server_sock, G_IO_IN, NULL);
525 g_source_set_callback (write_source, (GSourceFunc)proxy_bytes, proxy, NULL);
526 g_source_attach (write_source, context);
528 g_main_loop_run (proxy->loop);
530 g_socket_close (proxy->client_sock, &error);
531 g_assert_no_error (error);
532 g_clear_object (&proxy->client_sock);
534 g_socket_close (proxy->server_sock, &error);
535 g_assert_no_error (error);
536 g_clear_object (&proxy->server_sock);
538 g_source_destroy (read_source);
539 g_source_unref (read_source);
540 g_source_destroy (write_source);
541 g_source_unref (write_source);
544 g_main_loop_unref (proxy->loop);
545 g_main_context_unref (context);
547 g_object_unref (proxy->server);
548 g_object_unref (proxy->cancellable);
550 g_free (proxy->proxy_command);
551 g_free (proxy->supported_protocol);
558 create_proxy (ProxyData *proxy,
559 gchar proxy_protocol,
560 const gchar *destination_protocol,
561 GCancellable *cancellable)
563 GError *error = NULL;
564 GSocketAddress *addr;
567 proxy->proxy_command = g_strdup_printf ("%c", proxy_protocol);
568 proxy->supported_protocol = g_strdup (destination_protocol);
569 proxy->cancellable = g_object_ref (cancellable);
571 proxy->server = g_socket_new (G_SOCKET_FAMILY_IPV4,
572 G_SOCKET_TYPE_STREAM,
573 G_SOCKET_PROTOCOL_DEFAULT,
575 g_assert_no_error (error);
577 iaddr = g_inet_address_new_loopback (G_SOCKET_FAMILY_IPV4);
578 addr = g_inet_socket_address_new (iaddr, 0);
579 g_object_unref (iaddr);
581 g_socket_bind (proxy->server, addr, TRUE, &error);
582 g_assert_no_error (error);
583 g_object_unref (addr);
585 addr = g_socket_get_local_address (proxy->server, &error);
586 proxy->port = g_inet_socket_address_get_port (G_INET_SOCKET_ADDRESS (addr));
587 proxy->uri = g_strdup_printf ("proxy-%c://127.0.0.1:%u",
588 g_ascii_tolower (proxy_protocol),
590 g_object_unref (addr);
592 g_socket_listen (proxy->server, &error);
593 g_assert_no_error (error);
595 proxy->thread = g_thread_new ("proxy", proxy_thread, proxy);
600 /**************************/
601 /* The actual echo server */
602 /**************************/
605 echo_server_thread (gpointer user_data)
607 ServerData *data = user_data;
609 GError *error = NULL;
610 gssize nread, nwrote;
615 sock = g_socket_accept (data->server, data->cancellable, &error);
618 g_assert_error (error, G_IO_ERROR, G_IO_ERROR_CANCELLED);
619 g_error_free (error);
623 g_assert_no_error (error);
627 nread = g_socket_receive (sock, buf, sizeof (buf), NULL, &error);
628 g_assert_no_error (error);
629 g_assert_cmpint (nread, >=, 0);
634 nwrote = g_socket_send (sock, buf, nread, NULL, &error);
635 g_assert_no_error (error);
636 g_assert_cmpint (nwrote, ==, nread);
639 g_socket_close (sock, &error);
640 g_assert_no_error (error);
641 g_object_unref (sock);
644 g_object_unref (data->server);
645 g_object_unref (data->server_addr);
646 g_object_unref (data->cancellable);
652 create_server (ServerData *data, GCancellable *cancellable)
654 GError *error = NULL;
655 GSocketAddress *addr;
658 data->cancellable = g_object_ref (cancellable);
660 data->server = g_socket_new (G_SOCKET_FAMILY_IPV4,
661 G_SOCKET_TYPE_STREAM,
662 G_SOCKET_PROTOCOL_DEFAULT,
664 g_assert_no_error (error);
666 g_socket_set_blocking (data->server, TRUE);
667 iaddr = g_inet_address_new_loopback (G_SOCKET_FAMILY_IPV4);
668 addr = g_inet_socket_address_new (iaddr, 0);
669 g_object_unref (iaddr);
671 g_socket_bind (data->server, addr, TRUE, &error);
672 g_assert_no_error (error);
673 g_object_unref (addr);
675 data->server_addr = g_socket_get_local_address (data->server, &error);
676 g_assert_no_error (error);
678 data->server_port = g_inet_socket_address_get_port (G_INET_SOCKET_ADDRESS (data->server_addr));
680 g_socket_listen (data->server, &error);
681 g_assert_no_error (error);
683 data->server_thread = g_thread_new ("server", echo_server_thread, data);
687 /******************************************************************/
688 /* Now a GResolver implementation, so the can't-resolve test will */
689 /* pass even if you have an evil DNS-faking ISP. */
690 /******************************************************************/
692 typedef GResolver GFakeResolver;
693 typedef GResolverClass GFakeResolverClass;
695 G_DEFINE_TYPE (GFakeResolver, g_fake_resolver, G_TYPE_RESOLVER)
698 g_fake_resolver_init (GFakeResolver *gtr)
703 g_fake_resolver_lookup_by_name (GResolver *resolver,
704 const gchar *hostname,
705 GCancellable *cancellable,
708 /* This is only ever called with lookups that are expected to
713 G_RESOLVER_ERROR_NOT_FOUND,
719 g_fake_resolver_lookup_by_name_async (GResolver *resolver,
720 const gchar *hostname,
721 GCancellable *cancellable,
722 GAsyncReadyCallback callback,
725 g_simple_async_report_error_in_idle (G_OBJECT (resolver),
728 G_RESOLVER_ERROR_NOT_FOUND,
733 g_fake_resolver_class_init (GFakeResolverClass *fake_class)
735 GResolverClass *resolver_class = G_RESOLVER_CLASS (fake_class);
737 resolver_class->lookup_by_name = g_fake_resolver_lookup_by_name;
738 resolver_class->lookup_by_name_async = g_fake_resolver_lookup_by_name_async;
743 /****************************************/
744 /* We made it! Now for the actual test! */
745 /****************************************/
748 setup_test (gpointer fixture,
749 gconstpointer user_data)
754 teardown_test (gpointer fixture,
755 gconstpointer user_data)
759 g_strfreev (last_proxies);
762 g_clear_error (&proxy_a.last_error);
763 g_clear_error (&proxy_b.last_error);
767 static const gchar *testbuf = "0123456789abcdef";
770 do_echo_test (GSocketConnection *conn)
772 GIOStream *iostream = G_IO_STREAM (conn);
773 GInputStream *istream = g_io_stream_get_input_stream (iostream);
774 GOutputStream *ostream = g_io_stream_get_output_stream (iostream);
778 GError *error = NULL;
780 g_output_stream_write_all (ostream, testbuf, strlen (testbuf),
781 &nwrote, NULL, &error);
782 g_assert_no_error (error);
783 g_assert_cmpint (nwrote, ==, strlen (testbuf));
785 for (total = 0; total < nwrote; total += nread)
787 nread = g_input_stream_read (istream,
788 buf + total, sizeof (buf) - total,
790 g_assert_no_error (error);
791 g_assert_cmpint (nread, >, 0);
795 g_assert_cmpstr (buf, ==, testbuf);
799 async_got_conn (GObject *source,
800 GAsyncResult *result,
803 GSocketConnection **conn = user_data;
804 GError *error = NULL;
806 *conn = g_socket_client_connect_finish (G_SOCKET_CLIENT (source),
808 g_assert_no_error (error);
812 async_got_error (GObject *source,
813 GAsyncResult *result,
816 GError **error = user_data;
818 g_assert (error != NULL && *error == NULL);
819 g_socket_client_connect_finish (G_SOCKET_CLIENT (source),
821 g_assert (*error != NULL);
826 assert_direct (GSocketConnection *conn)
828 GSocketAddress *addr;
829 GError *error = NULL;
831 g_assert_cmpint (g_strv_length (last_proxies), ==, 1);
832 g_assert_cmpstr (last_proxies[0], ==, "direct://");
833 g_assert_no_error (proxy_a.last_error);
834 g_assert_no_error (proxy_b.last_error);
836 addr = g_socket_connection_get_remote_address (conn, &error);
837 g_assert_no_error (error);
838 g_assert (!G_IS_PROXY_ADDRESS (addr));
839 g_object_unref (addr);
841 addr = g_socket_connection_get_local_address (conn, &error);
842 g_assert_no_error (error);
843 g_object_unref (addr);
845 g_assert (g_socket_connection_is_connected (conn));
849 test_direct_sync (gpointer fixture,
850 gconstpointer user_data)
852 GSocketConnection *conn;
854 GError *error = NULL;
856 /* The simple:// URI should not require any proxy. */
858 uri = g_strdup_printf ("simple://127.0.0.1:%u", server.server_port);
859 conn = g_socket_client_connect_to_uri (client, uri, 0, NULL, &error);
861 g_assert_no_error (error);
863 assert_direct (conn);
865 g_object_unref (conn);
869 test_direct_async (gpointer fixture,
870 gconstpointer user_data)
872 GSocketConnection *conn;
875 /* The simple:// URI should not require any proxy. */
876 uri = g_strdup_printf ("simple://127.0.0.1:%u", server.server_port);
878 g_socket_client_connect_to_uri_async (client, uri, 0, NULL,
879 async_got_conn, &conn);
882 g_main_context_iteration (NULL, TRUE);
884 assert_direct (conn);
886 g_object_unref (conn);
890 assert_single (GSocketConnection *conn)
892 GSocketAddress *addr;
893 const gchar *proxy_uri;
895 GError *error = NULL;
897 g_assert_cmpint (g_strv_length (last_proxies), ==, 2);
898 g_assert_cmpstr (last_proxies[0], ==, proxy_a.uri);
899 g_assert_cmpstr (last_proxies[1], ==, proxy_b.uri);
900 g_assert_no_error (proxy_a.last_error);
901 g_assert_no_error (proxy_b.last_error);
903 addr = g_socket_connection_get_remote_address (conn, &error);
904 g_assert_no_error (error);
905 g_assert (G_IS_PROXY_ADDRESS (addr));
906 proxy_uri = g_proxy_address_get_uri (G_PROXY_ADDRESS (addr));
907 g_assert_cmpstr (proxy_uri, ==, proxy_a.uri);
908 proxy_port = g_inet_socket_address_get_port (G_INET_SOCKET_ADDRESS (addr));
909 g_assert_cmpint (proxy_port, ==, proxy_a.port);
911 g_object_unref (addr);
915 test_single_sync (gpointer fixture,
916 gconstpointer user_data)
918 GSocketConnection *conn;
919 GError *error = NULL;
922 /* The alpha:// URI should be proxied via Proxy A */
923 uri = g_strdup_printf ("alpha://127.0.0.1:%u", server.server_port);
924 conn = g_socket_client_connect_to_uri (client, uri, 0, NULL, &error);
926 g_assert_no_error (error);
928 assert_single (conn);
931 g_object_unref (conn);
935 test_single_async (gpointer fixture,
936 gconstpointer user_data)
938 GSocketConnection *conn;
941 /* The alpha:// URI should be proxied via Proxy A */
942 uri = g_strdup_printf ("alpha://127.0.0.1:%u", server.server_port);
944 g_socket_client_connect_to_uri_async (client, uri, 0, NULL,
945 async_got_conn, &conn);
948 g_main_context_iteration (NULL, TRUE);
950 assert_single (conn);
952 g_object_unref (conn);
956 assert_multiple (GSocketConnection *conn)
958 GSocketAddress *addr;
959 const gchar *proxy_uri;
961 GError *error = NULL;
963 g_assert_cmpint (g_strv_length (last_proxies), ==, 2);
964 g_assert_cmpstr (last_proxies[0], ==, proxy_a.uri);
965 g_assert_cmpstr (last_proxies[1], ==, proxy_b.uri);
966 g_assert_error (proxy_a.last_error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED);
967 g_assert_no_error (proxy_b.last_error);
969 addr = g_socket_connection_get_remote_address (conn, &error);
970 g_assert_no_error (error);
971 g_assert (G_IS_PROXY_ADDRESS (addr));
972 proxy_uri = g_proxy_address_get_uri (G_PROXY_ADDRESS (addr));
973 g_assert_cmpstr (proxy_uri, ==, proxy_b.uri);
974 proxy_port = g_inet_socket_address_get_port (G_INET_SOCKET_ADDRESS (addr));
975 g_assert_cmpint (proxy_port, ==, proxy_b.port);
977 g_object_unref (addr);
981 test_multiple_sync (gpointer fixture,
982 gconstpointer user_data)
984 GSocketConnection *conn;
985 GError *error = NULL;
988 /* The beta:// URI should be proxied via Proxy B, after failing
991 uri = g_strdup_printf ("beta://127.0.0.1:%u", server.server_port);
992 conn = g_socket_client_connect_to_uri (client, uri, 0, NULL, &error);
994 g_assert_no_error (error);
996 assert_multiple (conn);
998 g_object_unref (conn);
1002 test_multiple_async (gpointer fixture,
1003 gconstpointer user_data)
1005 GSocketConnection *conn;
1008 /* The beta:// URI should be proxied via Proxy B, after failing
1011 uri = g_strdup_printf ("beta://127.0.0.1:%u", server.server_port);
1013 g_socket_client_connect_to_uri_async (client, uri, 0, NULL,
1014 async_got_conn, &conn);
1016 while (conn == NULL)
1017 g_main_context_iteration (NULL, TRUE);
1019 assert_multiple (conn);
1020 do_echo_test (conn);
1021 g_object_unref (conn);
1025 test_dns (gpointer fixture,
1026 gconstpointer user_data)
1028 GSocketConnection *conn;
1029 GError *error = NULL;
1032 /* The simple:// and alpha:// URIs should fail with a DNS error,
1033 * but the beta:// URI should succeed, because we pass it to
1034 * Proxy B without trying to resolve it first
1038 uri = g_strdup_printf ("simple://no-such-host.xx:%u", server.server_port);
1039 conn = g_socket_client_connect_to_uri (client, uri, 0, NULL, &error);
1040 g_assert_error (error, G_RESOLVER_ERROR, G_RESOLVER_ERROR_NOT_FOUND);
1041 g_clear_error (&error);
1043 g_assert_no_error (proxy_a.last_error);
1044 g_assert_no_error (proxy_b.last_error);
1045 teardown_test (NULL, NULL);
1047 g_socket_client_connect_to_uri_async (client, uri, 0, NULL,
1048 async_got_error, &error);
1049 while (error == NULL)
1050 g_main_context_iteration (NULL, TRUE);
1051 g_assert_error (error, G_RESOLVER_ERROR, G_RESOLVER_ERROR_NOT_FOUND);
1052 g_clear_error (&error);
1055 g_assert_no_error (proxy_a.last_error);
1056 g_assert_no_error (proxy_b.last_error);
1057 teardown_test (NULL, NULL);
1060 uri = g_strdup_printf ("alpha://no-such-host.xx:%u", server.server_port);
1061 conn = g_socket_client_connect_to_uri (client, uri, 0, NULL, &error);
1062 /* Since Proxy A fails, @client will try Proxy B too, which won't
1063 * load an alpha:// URI.
1065 g_assert_error (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED);
1066 g_clear_error (&error);
1068 g_assert_no_error (proxy_a.last_error);
1069 g_assert_error (proxy_b.last_error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED);
1070 teardown_test (NULL, NULL);
1072 g_socket_client_connect_to_uri_async (client, uri, 0, NULL,
1073 async_got_error, &error);
1074 while (error == NULL)
1075 g_main_context_iteration (NULL, TRUE);
1076 g_assert_error (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED);
1077 g_clear_error (&error);
1080 g_assert_no_error (proxy_a.last_error);
1081 g_assert_error (proxy_b.last_error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED);
1082 teardown_test (NULL, NULL);
1085 uri = g_strdup_printf ("beta://no-such-host.xx:%u", server.server_port);
1086 conn = g_socket_client_connect_to_uri (client, uri, 0, NULL, &error);
1087 g_assert_no_error (error);
1089 g_assert_no_error (proxy_a.last_error);
1090 g_assert_no_error (proxy_b.last_error);
1092 do_echo_test (conn);
1093 g_clear_object (&conn);
1094 teardown_test (NULL, NULL);
1096 g_socket_client_connect_to_uri_async (client, uri, 0, NULL,
1097 async_got_conn, &conn);
1098 while (conn == NULL)
1099 g_main_context_iteration (NULL, TRUE);
1102 g_assert_no_error (proxy_a.last_error);
1103 g_assert_no_error (proxy_b.last_error);
1105 do_echo_test (conn);
1106 g_clear_object (&conn);
1107 teardown_test (NULL, NULL);
1114 GResolver *fake_resolver;
1115 GCancellable *cancellable;
1119 g_test_init (&argc, &argv, NULL);
1121 /* Register stuff. The dummy g_proxy_get_default_for_protocol() call
1122 * is to force _g_io_modules_ensure_extension_points_registered() to
1123 * get called, so we can then register a proxy resolver extension
1126 g_proxy_get_default_for_protocol ("foo");
1127 g_test_proxy_resolver_get_type ();
1128 g_proxy_a_get_type ();
1129 g_proxy_b_get_type ();
1130 g_setenv ("GIO_USE_PROXY_RESOLVER", "test", TRUE);
1132 fake_resolver = g_object_new (g_fake_resolver_get_type (), NULL);
1133 g_resolver_set_default (fake_resolver);
1135 cancellable = g_cancellable_new ();
1136 create_server (&server, cancellable);
1137 create_proxy (&proxy_a, 'a', "alpha", cancellable);
1138 create_proxy (&proxy_b, 'b', "beta", cancellable);
1140 client = g_socket_client_new ();
1141 g_assert_cmpint (g_socket_client_get_enable_proxy (client), ==, TRUE);
1143 g_test_add_vtable ("/proxy/direct_sync", 0, NULL, setup_test, test_direct_sync, teardown_test);
1144 g_test_add_vtable ("/proxy/direct_async", 0, NULL, setup_test, test_direct_async, teardown_test);
1145 g_test_add_vtable ("/proxy/single_sync", 0, NULL, setup_test, test_single_sync, teardown_test);
1146 g_test_add_vtable ("/proxy/single_async", 0, NULL, setup_test, test_single_async, teardown_test);
1147 g_test_add_vtable ("/proxy/multiple_sync", 0, NULL, setup_test, test_multiple_sync, teardown_test);
1148 g_test_add_vtable ("/proxy/multiple_async", 0, NULL, setup_test, test_multiple_async, teardown_test);
1149 g_test_add_vtable ("/proxy/dns", 0, NULL, setup_test, test_dns, teardown_test);
1151 result = g_test_run();
1153 g_object_unref (client);
1155 g_cancellable_cancel (cancellable);
1156 g_thread_join (proxy_a.thread);
1157 g_thread_join (proxy_b.thread);
1158 g_thread_join (server.server_thread);
1160 g_object_unref (cancellable);