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