|
Packit |
ae235b |
/*
|
|
Packit |
ae235b |
* Copyright © 2014 Canonical Limited
|
|
Packit |
ae235b |
*
|
|
Packit |
ae235b |
* This library is free software; you can redistribute it and/or
|
|
Packit |
ae235b |
* modify it under the terms of the GNU Lesser General Public
|
|
Packit |
ae235b |
* License as published by the Free Software Foundation; either
|
|
Packit |
ae235b |
* version 2.1 of the License, or (at your option) any later version.
|
|
Packit |
ae235b |
*
|
|
Packit |
ae235b |
* This library is distributed in the hope that it will be useful,
|
|
Packit |
ae235b |
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit |
ae235b |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
Packit |
ae235b |
* Lesser General Public License for more details.
|
|
Packit |
ae235b |
*
|
|
Packit |
ae235b |
* You should have received a copy of the GNU Lesser General
|
|
Packit |
ae235b |
* Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
|
Packit |
ae235b |
*
|
|
Packit |
ae235b |
* Authors: Ryan Lortie <desrt@desrt.ca>
|
|
Packit |
ae235b |
*/
|
|
Packit |
ae235b |
|
|
Packit |
ae235b |
#include <gio/gio.h>
|
|
Packit |
ae235b |
#include <string.h>
|
|
Packit |
ae235b |
|
|
Packit |
ae235b |
static gboolean expected_read_success;
|
|
Packit |
ae235b |
static guint expected_read;
|
|
Packit |
ae235b |
static gboolean got_read_done;
|
|
Packit |
ae235b |
|
|
Packit |
ae235b |
static void
|
|
Packit |
ae235b |
read_done (GObject *source,
|
|
Packit |
ae235b |
GAsyncResult *result,
|
|
Packit |
ae235b |
gpointer user_data)
|
|
Packit |
ae235b |
{
|
|
Packit |
ae235b |
gboolean success;
|
|
Packit |
ae235b |
gsize read;
|
|
Packit |
ae235b |
|
|
Packit |
ae235b |
success = g_input_stream_read_all_finish (G_INPUT_STREAM (source), result, &read, NULL);
|
|
Packit |
ae235b |
g_assert_cmpint (expected_read_success, ==, success);
|
|
Packit |
ae235b |
g_assert_cmpint (expected_read, ==, read);
|
|
Packit |
ae235b |
got_read_done = TRUE;
|
|
Packit |
ae235b |
}
|
|
Packit |
ae235b |
|
|
Packit |
ae235b |
static void
|
|
Packit |
ae235b |
wait_for_read (gboolean success,
|
|
Packit |
ae235b |
gsize read)
|
|
Packit |
ae235b |
{
|
|
Packit |
ae235b |
g_assert (!got_read_done);
|
|
Packit |
ae235b |
expected_read_success = success;
|
|
Packit |
ae235b |
expected_read = read;
|
|
Packit |
ae235b |
|
|
Packit |
ae235b |
while (!got_read_done)
|
|
Packit |
ae235b |
g_main_context_iteration (NULL, TRUE);
|
|
Packit |
ae235b |
|
|
Packit |
ae235b |
got_read_done = FALSE;
|
|
Packit |
ae235b |
}
|
|
Packit |
ae235b |
|
|
Packit |
ae235b |
static gboolean expected_write_success;
|
|
Packit |
ae235b |
static guint expected_written;
|
|
Packit |
ae235b |
static gboolean got_write_done;
|
|
Packit |
ae235b |
|
|
Packit |
ae235b |
static void
|
|
Packit |
ae235b |
write_done (GObject *source,
|
|
Packit |
ae235b |
GAsyncResult *result,
|
|
Packit |
ae235b |
gpointer user_data)
|
|
Packit |
ae235b |
{
|
|
Packit |
ae235b |
gboolean success;
|
|
Packit |
ae235b |
gsize written;
|
|
Packit |
ae235b |
|
|
Packit |
ae235b |
success = g_output_stream_write_all_finish (G_OUTPUT_STREAM (source), result, &written, NULL);
|
|
Packit |
ae235b |
g_assert_cmpint (expected_write_success, ==, success);
|
|
Packit |
ae235b |
g_assert_cmpint (expected_written, ==, written);
|
|
Packit |
ae235b |
got_write_done = TRUE;
|
|
Packit |
ae235b |
}
|
|
Packit |
ae235b |
|
|
Packit |
ae235b |
static void
|
|
Packit |
ae235b |
wait_for_write (gboolean success,
|
|
Packit |
ae235b |
gsize written)
|
|
Packit |
ae235b |
{
|
|
Packit |
ae235b |
g_assert (!got_write_done);
|
|
Packit |
ae235b |
expected_write_success = success;
|
|
Packit |
ae235b |
expected_written = written;
|
|
Packit |
ae235b |
|
|
Packit |
ae235b |
while (!got_write_done)
|
|
Packit |
ae235b |
g_main_context_iteration (NULL, TRUE);
|
|
Packit |
ae235b |
|
|
Packit |
ae235b |
got_write_done = FALSE;
|
|
Packit |
ae235b |
}
|
|
Packit |
ae235b |
|
|
Packit |
ae235b |
static void
|
|
Packit |
ae235b |
test_write_all_async_memory (void)
|
|
Packit |
ae235b |
{
|
|
Packit |
ae235b |
GOutputStream *ms;
|
|
Packit |
ae235b |
gchar b[24];
|
|
Packit |
ae235b |
|
|
Packit |
ae235b |
ms = g_memory_output_stream_new (b, sizeof b, NULL, NULL);
|
|
Packit |
ae235b |
|
|
Packit |
ae235b |
g_output_stream_write_all_async (ms, "0123456789", 10, 0, NULL, write_done, NULL);
|
|
Packit |
ae235b |
wait_for_write (TRUE, 10);
|
|
Packit |
ae235b |
|
|
Packit |
ae235b |
g_output_stream_write_all_async (ms, "0123456789", 10, 0, NULL, write_done, NULL);
|
|
Packit |
ae235b |
wait_for_write (TRUE, 10);
|
|
Packit |
ae235b |
|
|
Packit |
ae235b |
/* this will trigger an out-of-space error, but we will see the
|
|
Packit |
ae235b |
* partial write...
|
|
Packit |
ae235b |
*/
|
|
Packit |
ae235b |
g_output_stream_write_all_async (ms, "0123456789", 10, 0, NULL, write_done, NULL);
|
|
Packit |
ae235b |
wait_for_write (FALSE, 4);
|
|
Packit |
ae235b |
|
|
Packit |
ae235b |
/* and still an error, but no further bytes written */
|
|
Packit |
ae235b |
g_output_stream_write_all_async (ms, "0123456789", 10, 0, NULL, write_done, NULL);
|
|
Packit |
ae235b |
wait_for_write (FALSE, 0);
|
|
Packit |
ae235b |
|
|
Packit |
ae235b |
g_assert (!memcmp (b, "012345678901234567890123", 24));
|
|
Packit |
ae235b |
|
|
Packit |
ae235b |
g_object_unref (ms);
|
|
Packit |
ae235b |
}
|
|
Packit |
ae235b |
|
|
Packit |
ae235b |
static void
|
|
Packit |
ae235b |
test_read_all_async_memory (void)
|
|
Packit |
ae235b |
{
|
|
Packit |
ae235b |
GInputStream *ms;
|
|
Packit |
ae235b |
gchar b[24] = "0123456789ABCDEFGHIJ!@#$";
|
|
Packit |
ae235b |
gchar buf[10];
|
|
Packit |
ae235b |
|
|
Packit |
ae235b |
ms = g_memory_input_stream_new_from_data (b, sizeof b, NULL);
|
|
Packit |
ae235b |
|
|
Packit |
ae235b |
g_input_stream_read_all_async (ms, buf, 10, 0, NULL, read_done, NULL);
|
|
Packit |
ae235b |
wait_for_read (TRUE, 10);
|
|
Packit |
ae235b |
g_assert (!memcmp (buf, "0123456789", 10));
|
|
Packit |
ae235b |
|
|
Packit |
ae235b |
g_input_stream_read_all_async (ms, buf, 10, 0, NULL, read_done, NULL);
|
|
Packit |
ae235b |
wait_for_read (TRUE, 10);
|
|
Packit |
ae235b |
g_assert (!memcmp (buf, "ABCDEFGHIJ", 10));
|
|
Packit |
ae235b |
|
|
Packit |
ae235b |
/* partial read... */
|
|
Packit |
ae235b |
g_input_stream_read_all_async (ms, buf, 10, 0, NULL, read_done, NULL);
|
|
Packit |
ae235b |
wait_for_read (TRUE, 4);
|
|
Packit |
ae235b |
g_assert (!memcmp (buf, "!@#$", 4));
|
|
Packit |
ae235b |
|
|
Packit |
ae235b |
/* EOF */
|
|
Packit |
ae235b |
g_input_stream_read_all_async (ms, buf, 10, 0, NULL, read_done, NULL);
|
|
Packit |
ae235b |
wait_for_read (TRUE, 0);
|
|
Packit |
ae235b |
|
|
Packit |
ae235b |
g_object_unref (ms);
|
|
Packit |
ae235b |
}
|
|
Packit |
ae235b |
|
|
Packit |
ae235b |
#ifdef G_OS_UNIX
|
|
Packit |
ae235b |
#include <errno.h>
|
|
Packit |
ae235b |
#include <sys/types.h>
|
|
Packit |
ae235b |
#include <sys/socket.h>
|
|
Packit |
ae235b |
#include <gio/gunixinputstream.h>
|
|
Packit |
ae235b |
#include <gio/gunixoutputstream.h>
|
|
Packit |
ae235b |
|
|
Packit |
ae235b |
static void
|
|
Packit |
ae235b |
test_read_write_all_async_pipe (void)
|
|
Packit |
ae235b |
{
|
|
Packit |
ae235b |
GCancellable *cancellable;
|
|
Packit |
ae235b |
GError *error = NULL;
|
|
Packit |
ae235b |
GOutputStream *out;
|
|
Packit |
ae235b |
GInputStream *in;
|
|
Packit |
ae235b |
gsize in_flight;
|
|
Packit |
ae235b |
gsize s;
|
|
Packit |
ae235b |
gchar wbuf[100] = { 0, };
|
|
Packit |
ae235b |
gchar rbuf[100];
|
|
Packit |
ae235b |
|
|
Packit |
ae235b |
{
|
|
Packit |
ae235b |
gint sv[2];
|
|
Packit |
ae235b |
gint s;
|
|
Packit |
ae235b |
|
|
Packit |
ae235b |
s = socketpair (AF_UNIX, SOCK_STREAM, 0, sv);
|
|
Packit |
ae235b |
g_assert (s == 0);
|
|
Packit |
ae235b |
|
|
Packit |
ae235b |
out = g_unix_output_stream_new (sv[0], TRUE);
|
|
Packit |
ae235b |
in = g_unix_input_stream_new (sv[1], TRUE);
|
|
Packit |
ae235b |
}
|
|
Packit |
ae235b |
|
|
Packit |
ae235b |
/* Try to fill up the buffer */
|
|
Packit |
ae235b |
in_flight = 0;
|
|
Packit |
ae235b |
while (g_pollable_output_stream_is_writable (G_POLLABLE_OUTPUT_STREAM (out)))
|
|
Packit |
ae235b |
{
|
|
Packit |
ae235b |
s = g_output_stream_write (out, wbuf, sizeof wbuf, NULL, &error);
|
|
Packit |
ae235b |
g_assert_no_error (error);
|
|
Packit |
ae235b |
g_assert (s > 0);
|
|
Packit |
ae235b |
in_flight += s;
|
|
Packit |
ae235b |
}
|
|
Packit |
ae235b |
|
|
Packit |
ae235b |
/* Now start a blocking write_all; nothing should happen. */
|
|
Packit |
ae235b |
cancellable = g_cancellable_new ();
|
|
Packit |
ae235b |
g_output_stream_write_all_async (out, "0123456789", 10, 0, cancellable, write_done, NULL);
|
|
Packit |
ae235b |
while (g_main_context_iteration (NULL, FALSE))
|
|
Packit |
ae235b |
;
|
|
Packit |
ae235b |
g_assert (!got_write_done);
|
|
Packit |
ae235b |
|
|
Packit |
ae235b |
/* Cancel that to make sure it works */
|
|
Packit |
ae235b |
g_cancellable_cancel (cancellable);
|
|
Packit |
ae235b |
g_object_unref (cancellable);
|
|
Packit |
ae235b |
wait_for_write (FALSE, 0);
|
|
Packit |
ae235b |
|
|
Packit |
ae235b |
/* Start it again */
|
|
Packit |
ae235b |
g_output_stream_write_all_async (out, "0123456789", 10, 0, NULL, write_done, NULL);
|
|
Packit |
ae235b |
while (g_main_context_iteration (NULL, FALSE))
|
|
Packit |
ae235b |
;
|
|
Packit |
ae235b |
g_assert (!got_write_done);
|
|
Packit |
ae235b |
|
|
Packit |
ae235b |
/* Now drain as much as we originally put in the buffer to make it
|
|
Packit |
ae235b |
* block -- this will unblock the writer.
|
|
Packit |
ae235b |
*/
|
|
Packit |
ae235b |
while (in_flight)
|
|
Packit |
ae235b |
{
|
|
Packit |
ae235b |
s = g_input_stream_read (in, rbuf, MIN (sizeof wbuf, in_flight), NULL, &error);
|
|
Packit |
ae235b |
g_assert_no_error (error);
|
|
Packit |
ae235b |
g_assert (s > 0);
|
|
Packit |
ae235b |
in_flight -= s;
|
|
Packit |
ae235b |
}
|
|
Packit |
ae235b |
|
|
Packit |
ae235b |
/* That will have caused some writing to start happening. Do a
|
|
Packit |
ae235b |
* read_all as well, for more bytes than was written.
|
|
Packit |
ae235b |
*/
|
|
Packit |
ae235b |
g_input_stream_read_all_async (in, rbuf, sizeof rbuf, 0, NULL, read_done, NULL);
|
|
Packit |
ae235b |
|
|
Packit |
ae235b |
/* The write is surely finished by now */
|
|
Packit |
ae235b |
wait_for_write (TRUE, 10);
|
|
Packit |
ae235b |
/* ...but the read will not yet be satisfied */
|
|
Packit |
ae235b |
g_assert (!got_read_done);
|
|
Packit |
ae235b |
|
|
Packit |
ae235b |
/* Feed the read more than it asked for; this really should not block
|
|
Packit |
ae235b |
* since the buffer is so small...
|
|
Packit |
ae235b |
*/
|
|
Packit |
ae235b |
g_output_stream_write_all (out, wbuf, sizeof wbuf, 0, NULL, &error);
|
|
Packit |
ae235b |
g_assert_no_error (error);
|
|
Packit |
ae235b |
|
|
Packit |
ae235b |
/* Read will have finished now */
|
|
Packit |
ae235b |
wait_for_read (TRUE, sizeof rbuf);
|
|
Packit |
ae235b |
|
|
Packit |
ae235b |
/* Close the writer end to make an EOF condition */
|
|
Packit |
ae235b |
g_output_stream_close (out, NULL, NULL);
|
|
Packit |
ae235b |
|
|
Packit |
ae235b |
/* ... and we should have exactly 10 extra bytes left in the buffer */
|
|
Packit |
ae235b |
g_input_stream_read_all_async (in, rbuf, sizeof rbuf, 0, NULL, read_done, NULL);
|
|
Packit |
ae235b |
wait_for_read (TRUE, 10);
|
|
Packit |
ae235b |
|
|
Packit |
ae235b |
g_object_unref (out);
|
|
Packit |
ae235b |
g_object_unref (in);
|
|
Packit |
ae235b |
}
|
|
Packit |
ae235b |
#endif
|
|
Packit |
ae235b |
|
|
Packit |
ae235b |
int
|
|
Packit |
ae235b |
main (int argc,
|
|
Packit |
ae235b |
char **argv)
|
|
Packit |
ae235b |
{
|
|
Packit |
ae235b |
g_test_init (&argc, &argv, NULL);
|
|
Packit |
ae235b |
|
|
Packit |
ae235b |
g_test_add_func ("/stream/read_all_async/memory", test_read_all_async_memory);
|
|
Packit |
ae235b |
g_test_add_func ("/stream/write_all_async/memory", test_write_all_async_memory);
|
|
Packit |
ae235b |
#ifdef G_OS_UNIX
|
|
Packit |
ae235b |
g_test_add_func ("/stream/read_write_all_async/pipe", test_read_write_all_async_pipe);
|
|
Packit |
ae235b |
#endif
|
|
Packit |
ae235b |
|
|
Packit |
ae235b |
return g_test_run();
|
|
Packit |
ae235b |
}
|