5e0dfe42656ad324b8288bf56bef470e43b43ee8
[platform/upstream/glib.git] / gio / tests / stream-rw_all.c
1 /*
2  * Copyright © 2014 Canonical Limited
3  *
4  * This program is free software: you can redistribute it and/or modify
5  * it under the terms of the GNU Lesser General Public License as published
6  * by the Free Software Foundation; either version 2 of the licence or (at
7  * your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General
15  * Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
16  *
17  * Authors: Ryan Lortie <desrt@desrt.ca>
18  */
19
20 #include <gio/gio.h>
21 #include <string.h>
22
23 static gboolean expected_read_success;
24 static guint    expected_read;
25 static gboolean got_read_done;
26
27 static void
28 read_done (GObject      *source,
29            GAsyncResult *result,
30            gpointer      user_data)
31 {
32   gboolean success;
33   gsize read;
34
35   success = g_input_stream_read_all_finish (G_INPUT_STREAM (source), result, &read, NULL);
36   g_assert_cmpint (expected_read_success, ==, success);
37   g_assert_cmpint (expected_read, ==, read);
38   got_read_done = TRUE;
39 }
40
41 static void
42 wait_for_read (gboolean success,
43                gsize    read)
44 {
45   g_assert (!got_read_done);
46   expected_read_success = success;
47   expected_read = read;
48
49   while (!got_read_done)
50     g_main_context_iteration (NULL, TRUE);
51
52   got_read_done = FALSE;
53 }
54
55 static gboolean expected_write_success;
56 static guint    expected_written;
57 static gboolean got_write_done;
58
59 static void
60 write_done (GObject      *source,
61             GAsyncResult *result,
62             gpointer      user_data)
63 {
64   gboolean success;
65   gsize written;
66
67   success = g_output_stream_write_all_finish (G_OUTPUT_STREAM (source), result, &written, NULL);
68   g_assert_cmpint (expected_write_success, ==, success);
69   g_assert_cmpint (expected_written, ==, written);
70   got_write_done = TRUE;
71 }
72
73 static void
74 wait_for_write (gboolean success,
75                 gsize    written)
76 {
77   g_assert (!got_write_done);
78   expected_write_success = success;
79   expected_written = written;
80
81   while (!got_write_done)
82     g_main_context_iteration (NULL, TRUE);
83
84   got_write_done = FALSE;
85 }
86
87 static void
88 test_write_all_async_memory (void)
89 {
90   GOutputStream *ms;
91   gchar b[24];
92
93   ms = g_memory_output_stream_new (b, sizeof b, NULL, NULL);
94
95   g_output_stream_write_all_async (ms, "0123456789", 10, 0, NULL, write_done, NULL);
96   wait_for_write (TRUE, 10);
97
98   g_output_stream_write_all_async (ms, "0123456789", 10, 0, NULL, write_done, NULL);
99   wait_for_write (TRUE, 10);
100
101   /* this will trigger an out-of-space error, but we will see the
102    * partial write...
103    */
104   g_output_stream_write_all_async (ms, "0123456789", 10, 0, NULL, write_done, NULL);
105   wait_for_write (FALSE, 4);
106
107   /* and still an error, but no further bytes written */
108   g_output_stream_write_all_async (ms, "0123456789", 10, 0, NULL, write_done, NULL);
109   wait_for_write (FALSE, 0);
110
111   g_assert (!memcmp (b, "012345678901234567890123", 24));
112
113   g_object_unref (ms);
114 }
115
116 static void
117 test_read_all_async_memory (void)
118 {
119   GInputStream *ms;
120   gchar b[24] = "0123456789ABCDEFGHIJ!@#$";
121   gchar buf[10];
122
123   ms = g_memory_input_stream_new_from_data (b, sizeof b, NULL);
124
125   g_input_stream_read_all_async (ms, buf, 10, 0, NULL, read_done, NULL);
126   wait_for_read (TRUE, 10);
127   g_assert (!memcmp (buf, "0123456789", 10));
128
129   g_input_stream_read_all_async (ms, buf, 10, 0, NULL, read_done, NULL);
130   wait_for_read (TRUE, 10);
131   g_assert (!memcmp (buf, "ABCDEFGHIJ", 10));
132
133   /* partial read... */
134   g_input_stream_read_all_async (ms, buf, 10, 0, NULL, read_done, NULL);
135   wait_for_read (TRUE, 4);
136   g_assert (!memcmp (buf, "!@#$", 4));
137
138   /* EOF */
139   g_input_stream_read_all_async (ms, buf, 10, 0, NULL, read_done, NULL);
140   wait_for_read (TRUE, 0);
141
142   g_object_unref (ms);
143 }
144
145 #ifdef G_OS_UNIX
146 #include <errno.h>
147 #include <sys/types.h>
148 #include <sys/socket.h>
149 #include <gio/gunixinputstream.h>
150 #include <gio/gunixoutputstream.h>
151
152 static void
153 test_read_write_all_async_pipe (void)
154 {
155   GCancellable *cancellable;
156   GError *error = NULL;
157   GOutputStream *out;
158   GInputStream *in;
159   gsize in_flight;
160   gsize s;
161   gchar wbuf[100] = { 0, };
162   gchar rbuf[100];
163
164   {
165     gint sv[2];
166     gint s;
167
168     s = socketpair (AF_UNIX, SOCK_STREAM, 0, sv);
169     g_assert (s == 0);
170
171     out = g_unix_output_stream_new (sv[0], TRUE);
172     in = g_unix_input_stream_new (sv[1], TRUE);
173   }
174
175   /* Try to fill up the buffer */
176   in_flight = 0;
177   while (g_pollable_output_stream_is_writable (G_POLLABLE_OUTPUT_STREAM (out)))
178     {
179       s = g_output_stream_write (out, wbuf, sizeof wbuf, NULL, &error);
180       g_assert_no_error (error);
181       g_assert (s > 0);
182       in_flight += s;
183     }
184
185   /* Now start a blocking write_all; nothing should happen. */
186   cancellable = g_cancellable_new ();
187   g_output_stream_write_all_async (out, "0123456789", 10, 0, cancellable, write_done, NULL);
188   while (g_main_context_iteration (NULL, FALSE))
189     ;
190   g_assert (!got_write_done);
191
192   /* Cancel that to make sure it works */
193   g_cancellable_cancel (cancellable);
194   g_object_unref (cancellable);
195   wait_for_write (FALSE, 0);
196
197   /* Start it again */
198   g_output_stream_write_all_async (out, "0123456789", 10, 0, NULL, write_done, NULL);
199   while (g_main_context_iteration (NULL, FALSE))
200     ;
201   g_assert (!got_write_done);
202
203   /* Now drain as much as we originally put in the buffer to make it
204    * block -- this will unblock the writer.
205    */
206   while (in_flight)
207     {
208       s = g_input_stream_read (in, rbuf, MIN (sizeof wbuf, in_flight), NULL, &error);
209       g_assert_no_error (error);
210       g_assert (s > 0);
211       in_flight -= s;
212     }
213
214   /* That will have caused some writing to start happening.  Do a
215    * read_all as well, for more bytes than was written.
216    */
217   g_input_stream_read_all_async (in, rbuf, sizeof rbuf, 0, NULL, read_done, NULL);
218
219   /* The write is surely finished by now */
220   wait_for_write (TRUE, 10);
221   /* ...but the read will not yet be satisfied */
222   g_assert (!got_read_done);
223
224   /* Feed the read more than it asked for; this really should not block
225    * since the buffer is so small...
226    */
227   g_output_stream_write_all (out, wbuf, sizeof wbuf, 0, NULL, &error);
228   g_assert_no_error (error);
229
230   /* Read will have finished now */
231   wait_for_read (TRUE, sizeof rbuf);
232
233   /* Close the writer end to make an EOF condition */
234   g_output_stream_close (out, NULL, NULL);
235
236   /* ... and we should have exactly 10 extra bytes left in the buffer */
237   g_input_stream_read_all_async (in, rbuf, sizeof rbuf, 0, NULL, read_done, NULL);
238   wait_for_read (TRUE, 10);
239
240   g_object_unref (out);
241   g_object_unref (in);
242 }
243 #endif
244
245 int
246 main (int    argc,
247       char **argv)
248 {
249   g_test_init (&argc, &argv, NULL);
250
251   g_test_add_func ("/stream/read_all_async/memory", test_read_all_async_memory);
252   g_test_add_func ("/stream/write_all_async/memory", test_write_all_async_memory);
253 #ifdef G_OS_UNIX
254   g_test_add_func ("/stream/read_write_all_async/pipe", test_read_write_all_async_pipe);
255 #endif
256
257   return g_test_run();
258 }