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