[kdbus] KDBUS_ITEM_PAYLOAD_OFF items are (once again) relative to msg header
[platform/upstream/glib.git] / gio / tests / proxy-test.c
1 /* GLib testing framework examples and tests
2  *
3  * Copyright 2012 Red Hat, Inc.
4  *
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.
9  *
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.
14  *
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/>.
17  */
18
19 #include <string.h>
20
21 #define GLIB_VERSION_MIN_REQUIRED GLIB_VERSION_2_34
22 #include <gio/gio.h>
23
24 /* Overview:
25  *
26  * We have an echo server, two proxy servers, two GProxy
27  * implementations, and two GProxyResolver implementations.
28  *
29  * The echo server runs at @server.server_addr (on
30  * @server.server_port).
31  *
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.
37  *
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).
42  *
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 ].
47  */
48
49 typedef struct {
50   gchar *proxy_command;
51   gchar *supported_protocol;
52
53   GSocket *server;
54   GThread *thread;
55   GCancellable *cancellable;
56   gchar *uri;
57   gushort port;
58
59   GSocket *client_sock, *server_sock;
60   GMainLoop *loop;
61
62   GError *last_error;
63 } ProxyData;
64
65 static ProxyData proxy_a, proxy_b;
66
67 typedef struct {
68   GSocket *server;
69   GThread *server_thread;
70   GCancellable *cancellable;
71   GSocketAddress *server_addr;
72   gushort server_port;
73 } ServerData;
74
75 static ServerData server;
76
77 static gchar **last_proxies;
78
79 static GSocketClient *client;
80
81
82 /**************************************/
83 /* Test GProxyResolver implementation */
84 /**************************************/
85
86 typedef struct {
87   GObject parent_instance;
88 } GTestProxyResolver;
89
90 typedef struct {
91   GObjectClass parent_class;
92 } GTestProxyResolverClass;
93
94 static void g_test_proxy_resolver_iface_init (GProxyResolverInterface *iface);
95
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",
104                                                          0))
105
106 static void
107 g_test_proxy_resolver_init (GTestProxyResolver *resolver)
108 {
109 }
110
111 static gboolean
112 g_test_proxy_resolver_is_supported (GProxyResolver *resolver)
113 {
114   return TRUE;
115 }
116
117 static gchar **
118 g_test_proxy_resolver_lookup (GProxyResolver  *resolver,
119                               const gchar     *uri,
120                               GCancellable    *cancellable,
121                               GError         **error)
122 {
123   gchar **proxies;
124
125   g_assert (last_proxies == NULL);
126
127   if (g_cancellable_set_error_if_cancelled (cancellable, error))
128     return NULL;
129
130   proxies = g_new (gchar *, 3);
131
132   if (!strncmp (uri, "simple://", 4))
133     {
134       proxies[0] = g_strdup ("direct://");
135       proxies[1] = NULL;
136     }
137   else
138     {
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.
143        */
144       proxies[0] = g_strdup (proxy_a.uri);
145       proxies[1] = g_strdup (proxy_b.uri);
146       proxies[2] = NULL;
147     }
148
149   last_proxies = g_strdupv (proxies);
150
151   return proxies;
152 }
153
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)
160 {
161   GError *error = NULL;
162   GTask *task;
163   gchar **proxies;
164
165   proxies = g_proxy_resolver_lookup (resolver, uri, cancellable, &error);
166
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);
172
173   g_object_unref (task);
174 }
175
176 static gchar **
177 g_test_proxy_resolver_lookup_finish (GProxyResolver     *resolver,
178                                      GAsyncResult       *result,
179                                      GError            **error)
180 {
181   return g_task_propagate_pointer (G_TASK (result), error);
182 }
183
184 static void
185 g_test_proxy_resolver_class_init (GTestProxyResolverClass *resolver_class)
186 {
187 }
188
189 static void
190 g_test_proxy_resolver_iface_init (GProxyResolverInterface *iface)
191 {
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;
196 }
197
198 /****************************/
199 /* Alternate GProxyResolver */
200 /****************************/
201
202 typedef GTestProxyResolver GTestAltProxyResolver;
203 typedef GTestProxyResolverClass GTestAltProxyResolverClass;
204
205 static void g_test_alt_proxy_resolver_iface_init (GProxyResolverInterface *iface);
206
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);
212                          )
213
214 static void
215 g_test_alt_proxy_resolver_init (GTestProxyResolver *resolver)
216 {
217 }
218
219 static gchar **
220 g_test_alt_proxy_resolver_lookup (GProxyResolver  *resolver,
221                                   const gchar     *uri,
222                                   GCancellable    *cancellable,
223                                   GError         **error)
224 {
225   gchar **proxies;
226
227   proxies = g_new (gchar *, 2);
228
229   proxies[0] = g_strdup (proxy_a.uri);
230   proxies[1] = NULL;
231
232   last_proxies = g_strdupv (proxies);
233
234   return proxies;
235 }
236
237 static void
238 g_test_alt_proxy_resolver_class_init (GTestProxyResolverClass *resolver_class)
239 {
240 }
241
242 static void
243 g_test_alt_proxy_resolver_iface_init (GProxyResolverInterface *iface)
244 {
245   iface->lookup = g_test_alt_proxy_resolver_lookup;
246 }
247
248
249 /****************************************/
250 /* Test proxy implementation base class */
251 /****************************************/
252
253 typedef struct {
254   GObject parent;
255
256   ProxyData *proxy_data;
257 } GProxyBase;
258
259 typedef struct {
260   GObjectClass parent_class;
261 } GProxyBaseClass;
262
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)
266
267 static void
268 g_proxy_base_init (GProxyBase *proxy)
269 {
270 }
271
272 static GIOStream *
273 g_proxy_base_connect (GProxy            *proxy,
274                       GIOStream         *io_stream,
275                       GProxyAddress     *proxy_address,
276                       GCancellable      *cancellable,
277                       GError           **error)
278 {
279   ProxyData *data = ((GProxyBase *) proxy)->proxy_data;
280   const gchar *protocol;
281   GOutputStream *ostream;
282   GInputStream *istream;
283   gchar response;
284
285   g_assert_no_error (data->last_error);
286
287   protocol = g_proxy_address_get_destination_protocol (proxy_address);
288   if (strcmp (protocol, data->supported_protocol) != 0)
289     {
290       g_set_error_literal (&data->last_error,
291                            G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
292                            "Unsupported protocol");
293       goto fail;
294     }
295
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;
300
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;
305
306   if (response != g_ascii_toupper (*data->proxy_command))
307     {
308       g_set_error_literal (&data->last_error,
309                            G_IO_ERROR, G_IO_ERROR_FAILED,
310                            "Failed");
311       goto fail;
312     }
313
314   return g_object_ref (io_stream);
315
316  fail:
317   g_propagate_error (error, g_error_copy (data->last_error));
318   return NULL;
319 }
320
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)
328 {
329   GError *error = NULL;
330   GTask *task;
331   GIOStream *proxy_io_stream;
332
333   task = g_task_new (proxy, NULL, callback, user_data);
334
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);
342 }
343
344 static GIOStream *
345 g_proxy_base_connect_finish (GProxy        *proxy,
346                              GAsyncResult  *result,
347                              GError       **error)
348 {
349   return g_task_propagate_pointer (G_TASK (result), error);
350 }
351
352 static void
353 g_proxy_base_class_init (GProxyBaseClass *class)
354 {
355 }
356
357
358 /********************************************/
359 /* Test proxy implementation #1 ("Proxy A") */
360 /********************************************/
361
362 typedef GProxyBase GProxyA;
363 typedef GProxyBaseClass GProxyAClass;
364
365 static void g_proxy_a_iface_init (GProxyInterface *proxy_iface);
366
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",
375                                                          0))
376
377 static void
378 g_proxy_a_init (GProxyA *proxy)
379 {
380   ((GProxyBase *) proxy)->proxy_data = &proxy_a;
381 }
382
383 static gboolean
384 g_proxy_a_supports_hostname (GProxy *proxy)
385 {
386   return FALSE;
387 }
388
389 static void
390 g_proxy_a_class_init (GProxyAClass *class)
391 {
392 }
393
394 static void
395 g_proxy_a_iface_init (GProxyInterface *proxy_iface)
396 {
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;
401 }
402
403 /********************************************/
404 /* Test proxy implementation #2 ("Proxy B") */
405 /********************************************/
406
407 typedef GProxyBase GProxyB;
408 typedef GProxyBaseClass GProxyBClass;
409
410 static void g_proxy_b_iface_init (GProxyInterface *proxy_iface);
411
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",
420                                                          0))
421
422 static void
423 g_proxy_b_init (GProxyB *proxy)
424 {
425   ((GProxyBase *) proxy)->proxy_data = &proxy_b;
426 }
427
428 static gboolean
429 g_proxy_b_supports_hostname (GProxy *proxy)
430 {
431   return TRUE;
432 }
433
434 static void
435 g_proxy_b_class_init (GProxyBClass *class)
436 {
437 }
438
439 static void
440 g_proxy_b_iface_init (GProxyInterface *proxy_iface)
441 {
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;
446 }
447
448
449 /***********************************/
450 /* The proxy server implementation */
451 /***********************************/
452
453 static gboolean
454 proxy_bytes (GSocket      *socket,
455              GIOCondition  condition,
456              gpointer      user_data)
457 {
458   ProxyData *proxy = user_data;
459   gssize nread, nwrote, total;
460   gchar buffer[8];
461   GSocket *out_socket;
462   GError *error = NULL;
463
464   nread = g_socket_receive_with_blocking (socket, buffer, sizeof (buffer),
465                                           TRUE, NULL, &error);
466   if (nread == -1)
467     {
468       g_assert_error (error, G_IO_ERROR, G_IO_ERROR_CLOSED);
469       return FALSE;
470     }
471   else
472     g_assert_no_error (error);
473
474   if (nread == 0)
475     {
476       g_main_loop_quit (proxy->loop);
477       return FALSE;
478     }
479
480   if (socket == proxy->client_sock)
481     out_socket = proxy->server_sock;
482   else
483     out_socket = proxy->client_sock;
484
485   for (total = 0; total < nread; total += nwrote)
486     {
487       nwrote = g_socket_send_with_blocking (out_socket,
488                                             buffer + total, nread - total,
489                                             TRUE, NULL, &error);
490       g_assert_no_error (error);
491     }
492
493   return TRUE;
494 }
495
496 static gpointer
497 proxy_thread (gpointer user_data)
498 {
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;
505
506   context = g_main_context_new ();
507   proxy->loop = g_main_loop_new (context, FALSE);
508
509   while (TRUE)
510     {
511       proxy->client_sock = g_socket_accept (proxy->server, proxy->cancellable, &error);
512       if (!proxy->client_sock)
513         {
514           g_assert_error (error, G_IO_ERROR, G_IO_ERROR_CANCELLED);
515           g_error_free (error);
516           break;
517         }
518       else
519         g_assert_no_error (error);
520
521       nread = g_socket_receive (proxy->client_sock, command, 1, NULL, &error);
522       g_assert_no_error (error);
523
524       if (nread == 0)
525         {
526           g_clear_object (&proxy->client_sock);
527           continue;
528         }
529
530       g_assert_cmpint (nread, ==, 1);
531       g_assert_cmpstr (command, ==, proxy->proxy_command);
532
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);
537
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);
545
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);
549
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);
553
554       g_main_loop_run (proxy->loop);
555
556       g_socket_close (proxy->client_sock, &error);
557       g_assert_no_error (error);
558       g_clear_object (&proxy->client_sock);
559
560       g_socket_close (proxy->server_sock, &error);
561       g_assert_no_error (error);
562       g_clear_object (&proxy->server_sock);
563
564       g_source_destroy (read_source);
565       g_source_unref (read_source);
566       g_source_destroy (write_source);
567       g_source_unref (write_source);
568     }
569
570   g_main_loop_unref (proxy->loop);
571   g_main_context_unref (context);
572
573   g_object_unref (proxy->server);
574   g_object_unref (proxy->cancellable);
575
576   g_free (proxy->proxy_command);
577   g_free (proxy->supported_protocol);
578   g_free (proxy->uri);
579
580   return NULL;
581 }
582
583 static void
584 create_proxy (ProxyData    *proxy,
585               gchar         proxy_protocol,
586               const gchar  *destination_protocol,
587               GCancellable *cancellable)
588 {
589   GError *error = NULL;
590   GSocketAddress *addr;
591   GInetAddress *iaddr;
592
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);
596
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);
602
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);
606
607   g_socket_bind (proxy->server, addr, TRUE, &error);
608   g_assert_no_error (error);
609   g_object_unref (addr);
610
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);
617
618   g_socket_listen (proxy->server, &error);
619   g_assert_no_error (error);
620
621   proxy->thread = g_thread_new ("proxy", proxy_thread, proxy);
622 }
623
624
625
626 /**************************/
627 /* The actual echo server */
628 /**************************/
629
630 static gpointer
631 echo_server_thread (gpointer user_data)
632 {
633   ServerData *data = user_data;
634   GSocket *sock;
635   GError *error = NULL;
636   gssize nread, nwrote;
637   gchar buf[128];
638
639   while (TRUE)
640     {
641       sock = g_socket_accept (data->server, data->cancellable, &error);
642       if (!sock)
643         {
644           g_assert_error (error, G_IO_ERROR, G_IO_ERROR_CANCELLED);
645           g_error_free (error);
646           break;
647         }
648       else
649         g_assert_no_error (error);
650
651       while (TRUE)
652         {
653           nread = g_socket_receive (sock, buf, sizeof (buf), NULL, &error);
654           g_assert_no_error (error);
655           g_assert_cmpint (nread, >=, 0);
656
657           if (nread == 0)
658             break;
659
660           nwrote = g_socket_send (sock, buf, nread, NULL, &error);
661           g_assert_no_error (error);
662           g_assert_cmpint (nwrote, ==, nread);
663         }
664
665       g_socket_close (sock, &error);
666       g_assert_no_error (error);
667       g_object_unref (sock);
668     }
669
670   g_object_unref (data->server);
671   g_object_unref (data->server_addr);
672   g_object_unref (data->cancellable);
673
674   return NULL;
675 }
676
677 static void
678 create_server (ServerData *data, GCancellable *cancellable)
679 {
680   GError *error = NULL;
681   GSocketAddress *addr;
682   GInetAddress *iaddr;
683
684   data->cancellable = g_object_ref (cancellable);
685
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);
691
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);
696
697   g_socket_bind (data->server, addr, TRUE, &error);
698   g_assert_no_error (error);
699   g_object_unref (addr);
700
701   data->server_addr = g_socket_get_local_address (data->server, &error);
702   g_assert_no_error (error);
703
704   data->server_port = g_inet_socket_address_get_port (G_INET_SOCKET_ADDRESS (data->server_addr));
705
706   g_socket_listen (data->server, &error);
707   g_assert_no_error (error);
708
709   data->server_thread = g_thread_new ("server", echo_server_thread, data);
710 }
711
712
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 /******************************************************************/
717
718 typedef GResolver GFakeResolver;
719 typedef GResolverClass GFakeResolverClass;
720
721 static GType g_fake_resolver_get_type (void);
722 G_DEFINE_TYPE (GFakeResolver, g_fake_resolver, G_TYPE_RESOLVER)
723
724 static void
725 g_fake_resolver_init (GFakeResolver *gtr)
726 {
727 }
728
729 static GList *
730 g_fake_resolver_lookup_by_name (GResolver     *resolver,
731                                 const gchar   *hostname,
732                                 GCancellable  *cancellable,
733                                 GError       **error)
734 {
735   if (!strcmp (hostname, "example.com"))
736     return g_list_prepend (NULL, g_inet_address_new_from_string ("127.0.0.1"));
737   else
738     {
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;
745     }
746 }
747
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)
754 {
755   GTask *task;
756
757   task = g_task_new (resolver, cancellable, callback, user_data);
758
759   if (!strcmp (hostname, "example.com"))
760     {
761       GList *result;
762
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);
765     }
766   else
767     {
768       g_task_return_new_error (task,
769                                G_RESOLVER_ERROR, G_RESOLVER_ERROR_NOT_FOUND,
770                                "Not found");
771     }
772   g_object_unref (task);
773 }
774
775 static GList *
776 g_fake_resolver_lookup_by_name_finish (GResolver            *resolver,
777                                        GAsyncResult         *result,
778                                        GError              **error)
779 {
780   return g_task_propagate_pointer (G_TASK (result), error);
781 }
782
783 static void
784 g_fake_resolver_class_init (GFakeResolverClass *fake_class)
785 {
786   GResolverClass *resolver_class = G_RESOLVER_CLASS (fake_class);
787
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;
791 }
792
793
794
795 /****************************************/
796 /* We made it! Now for the actual test! */
797 /****************************************/
798
799 static void
800 setup_test (gpointer fixture,
801             gconstpointer user_data)
802 {
803 }
804
805 static void
806 teardown_test (gpointer fixture,
807                gconstpointer user_data)
808 {
809   if (last_proxies)
810     {
811       g_strfreev (last_proxies);
812       last_proxies = NULL;
813     }
814   g_clear_error (&proxy_a.last_error);
815   g_clear_error (&proxy_b.last_error);
816 }
817
818
819 static const gchar *testbuf = "0123456789abcdef";
820
821 static void
822 do_echo_test (GSocketConnection *conn)
823 {
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;
831
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));
836
837   for (total = 0; total < nwrote; total += nread)
838     {
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);
844     }
845
846   buf[total] = '\0';
847   g_assert_cmpstr (buf, ==, testbuf);
848 }
849
850 static void
851 async_got_conn (GObject      *source,
852                 GAsyncResult *result,
853                 gpointer      user_data)
854 {
855   GSocketConnection **conn = user_data;
856   GError *error = NULL;
857
858   *conn = g_socket_client_connect_finish (G_SOCKET_CLIENT (source),
859                                           result, &error);
860   g_assert_no_error (error);
861 }
862
863 static void
864 async_got_error (GObject      *source,
865                  GAsyncResult *result,
866                  gpointer      user_data)
867 {
868   GError **error = user_data;
869
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);
874 }
875
876
877 static void
878 assert_direct (GSocketConnection *conn)
879 {
880   GSocketAddress *addr;
881   GError *error = NULL;
882
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);
887
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);
892
893   addr = g_socket_connection_get_local_address (conn, &error);
894   g_assert_no_error (error);
895   g_object_unref (addr);
896
897   g_assert (g_socket_connection_is_connected (conn));
898 }
899
900 static void
901 test_direct_sync (gpointer fixture,
902                   gconstpointer user_data)
903 {
904   GSocketConnection *conn;
905   gchar *uri;
906   GError *error = NULL;
907
908   /* The simple:// URI should not require any proxy. */
909
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);
914
915   assert_direct (conn);
916   do_echo_test (conn);
917   g_object_unref (conn);
918 }
919
920 static void
921 test_direct_async (gpointer fixture,
922                    gconstpointer user_data)
923 {
924   GSocketConnection *conn;
925   gchar *uri;
926
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);
935
936   assert_direct (conn);
937   do_echo_test (conn);
938   g_object_unref (conn);
939 }
940
941 static void
942 assert_single (GSocketConnection *conn)
943 {
944   GSocketAddress *addr;
945   const gchar *proxy_uri;
946   gushort proxy_port;
947   GError *error = NULL;
948
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);
954
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);
962
963   g_object_unref (addr);
964 }
965
966 static void
967 test_single_sync (gpointer fixture,
968                   gconstpointer user_data)
969 {
970   GSocketConnection *conn;
971   GError *error = NULL;
972   gchar *uri;
973
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);
979
980   assert_single (conn);
981
982   do_echo_test (conn);
983   g_object_unref (conn);
984 }
985
986 static void
987 test_single_async (gpointer fixture,
988                    gconstpointer user_data)
989 {
990   GSocketConnection *conn;
991   gchar *uri;
992
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);
1001
1002   assert_single (conn);
1003   do_echo_test (conn);
1004   g_object_unref (conn);
1005 }
1006
1007 static void
1008 assert_multiple (GSocketConnection *conn)
1009 {
1010   GSocketAddress *addr;
1011   const gchar *proxy_uri;
1012   gushort proxy_port;
1013   GError *error = NULL;
1014
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);
1020
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);
1028
1029   g_object_unref (addr);
1030 }
1031
1032 static void
1033 test_multiple_sync (gpointer fixture,
1034                     gconstpointer user_data)
1035 {
1036   GSocketConnection *conn;
1037   GError *error = NULL;
1038   gchar *uri;
1039
1040   /* The beta:// URI should be proxied via Proxy B, after failing
1041    * via Proxy A.
1042    */
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);
1047
1048   assert_multiple (conn);
1049   do_echo_test (conn);
1050   g_object_unref (conn);
1051 }
1052
1053 static void
1054 test_multiple_async (gpointer fixture,
1055                      gconstpointer user_data)
1056 {
1057   GSocketConnection *conn;
1058   gchar *uri;
1059
1060   /* The beta:// URI should be proxied via Proxy B, after failing
1061    * via Proxy A.
1062    */
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);
1070
1071   assert_multiple (conn);
1072   do_echo_test (conn);
1073   g_object_unref (conn);
1074 }
1075
1076 static void
1077 test_dns (gpointer fixture,
1078           gconstpointer user_data)
1079 {
1080   GSocketConnection *conn;
1081   GError *error = NULL;
1082   gchar *uri;
1083
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
1087    */
1088
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);
1094
1095   g_assert_no_error (proxy_a.last_error);
1096   g_assert_no_error (proxy_b.last_error);
1097   teardown_test (NULL, NULL);
1098
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);
1106
1107   g_assert_no_error (proxy_a.last_error);
1108   g_assert_no_error (proxy_b.last_error);
1109   teardown_test (NULL, NULL);
1110
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.
1116    */
1117   g_assert_error (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED);
1118   g_clear_error (&error);
1119
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);
1123
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);
1131
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);
1135
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);
1140
1141   g_assert_no_error (proxy_a.last_error);
1142   g_assert_no_error (proxy_b.last_error);
1143
1144   do_echo_test (conn);
1145   g_clear_object (&conn);
1146   teardown_test (NULL, NULL);
1147
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);
1153
1154   g_assert_no_error (proxy_a.last_error);
1155   g_assert_no_error (proxy_b.last_error);
1156
1157   do_echo_test (conn);
1158   g_clear_object (&conn);
1159   teardown_test (NULL, NULL);
1160 }
1161
1162 static void
1163 assert_override (GSocketConnection *conn)
1164 {
1165   g_assert_cmpint (g_strv_length (last_proxies), ==, 1);
1166   g_assert_cmpstr (last_proxies[0], ==, proxy_a.uri);
1167
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);
1172 }
1173
1174 static void
1175 test_override (gpointer fixture,
1176                gconstpointer user_data)
1177 {
1178   GProxyResolver *alt_resolver;
1179   GSocketConnection *conn;
1180   GError *error = NULL;
1181   gchar *uri;
1182
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);
1187
1188   /* Alt proxy resolver always returns Proxy A, so alpha:// should
1189    * succeed, and simple:// and beta:// should fail.
1190    */
1191
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);
1199
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);
1209
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);
1218
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);
1229
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);
1237
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);
1247
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);
1252 }
1253
1254 static void
1255 assert_destination_port (GSocketAddressEnumerator *etor,
1256                          guint16                   port)
1257 {
1258   GSocketAddress *addr;
1259   GProxyAddress *paddr;
1260   GError *error = NULL;
1261
1262   while ((addr = g_socket_address_enumerator_next (etor, NULL, &error)))
1263     {
1264       g_assert_no_error (error);
1265
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);
1270     }
1271   g_assert_no_error (error);
1272 }
1273
1274 static void
1275 test_proxy_enumerator_ports (void)
1276 {
1277   GSocketAddressEnumerator *etor;
1278
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);
1284
1285   /* Have to call this to clear last_proxies so the next call to
1286    * g_test_proxy_resolver_lookup() won't assert.
1287    */
1288   teardown_test (NULL, NULL);
1289
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);
1295
1296   teardown_test (NULL, NULL);
1297
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);
1304
1305   teardown_test (NULL, NULL);
1306
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);
1313
1314   teardown_test (NULL, NULL);
1315 }
1316
1317 int
1318 main (int   argc,
1319       char *argv[])
1320 {
1321   GResolver *fake_resolver;
1322   GCancellable *cancellable;
1323   gint result;
1324
1325   g_test_init (&argc, &argv, NULL);
1326
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.
1331    */
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);
1337
1338   fake_resolver = g_object_new (g_fake_resolver_get_type (), NULL);
1339   g_resolver_set_default (fake_resolver);
1340
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);
1345
1346   client = g_socket_client_new ();
1347   g_assert_cmpint (g_socket_client_get_enable_proxy (client), ==, TRUE);
1348
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);
1358
1359   result = g_test_run();
1360
1361   g_object_unref (client);
1362
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);
1367
1368   g_object_unref (cancellable);
1369
1370   return result;
1371 }
1372