(root)/
glib-2.79.0/
gio/
tests/
async-splice-output-stream.c
       1  /* GLib testing framework examples and tests
       2   * Copyright (C) 2010-2012 Collabora Ltd.
       3   * Authors: Xavier Claessens <xclaesse@gmail.com>
       4   *          Mike Ruprecht <mike.ruprecht@collabora.co.uk>
       5   *
       6   * SPDX-License-Identifier: LicenseRef-old-glib-tests
       7   *
       8   * This work is provided "as is"; redistribution and modification
       9   * in whole or in part, in any medium, physical or electronic is
      10   * permitted without restriction.
      11   *
      12   * This work is distributed in the hope that it will be useful,
      13   * but WITHOUT ANY WARRANTY; without even the implied warranty of
      14   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
      15   *
      16   * In no event shall the authors or contributors be liable for any
      17   * direct, indirect, incidental, special, exemplary, or consequential
      18   * damages (including, but not limited to, procurement of substitute
      19   * goods or services; loss of use, data, or profits; or business
      20   * interruption) however caused and on any theory of liability, whether
      21   * in contract, strict liability, or tort (including negligence or
      22   * otherwise) arising in any way out of the use of this software, even
      23   * if advised of the possibility of such damage.
      24   */
      25  
      26  #include <glib/glib.h>
      27  #include <glib/gstdio.h>
      28  #include <gio/gio.h>
      29  #include <stdlib.h>
      30  #include <string.h>
      31  
      32  typedef enum
      33  {
      34    TEST_THREADED_NONE    = 0,
      35    TEST_THREADED_ISTREAM = 1,
      36    TEST_THREADED_OSTREAM = 2,
      37    TEST_CANCEL           = 4,
      38    TEST_THREADED_BOTH    = TEST_THREADED_ISTREAM | TEST_THREADED_OSTREAM,
      39  } TestThreadedFlags;
      40  
      41  typedef struct
      42  {
      43    GMainLoop *main_loop;
      44    const gchar *data;
      45    GInputStream *istream;
      46    GOutputStream *ostream;
      47    TestThreadedFlags flags;
      48    gchar *input_path;
      49    gchar *output_path;
      50  } TestCopyChunksData;
      51  
      52  static void
      53  test_copy_chunks_splice_cb (GObject      *source,
      54                              GAsyncResult *res,
      55                              gpointer      user_data)
      56  {
      57    TestCopyChunksData *data = user_data;
      58    gchar *received_data;
      59    GError *error = NULL;
      60    gssize bytes_spliced;
      61  
      62    bytes_spliced = g_output_stream_splice_finish (G_OUTPUT_STREAM (source),
      63                                                   res, &error);
      64  
      65    if (data->flags & TEST_CANCEL)
      66      {
      67        g_assert_error (error, G_IO_ERROR, G_IO_ERROR_CANCELLED);
      68        g_error_free (error);
      69        g_main_loop_quit (data->main_loop);
      70        return;
      71      }
      72  
      73    g_assert_no_error (error);
      74    g_assert_cmpint (bytes_spliced, ==, strlen (data->data));
      75  
      76    if (data->flags & TEST_THREADED_OSTREAM)
      77      {
      78        gsize length = 0;
      79  
      80        g_file_get_contents (data->output_path, &received_data,
      81                             &length, &error);
      82        g_assert_no_error (error);
      83        g_assert_cmpstr (received_data, ==, data->data);
      84        g_free (received_data);
      85      }
      86    else
      87      {
      88        received_data = g_memory_output_stream_get_data (G_MEMORY_OUTPUT_STREAM (data->ostream));
      89        g_assert_cmpstr (received_data, ==, data->data);
      90      }
      91  
      92    g_assert (g_input_stream_is_closed (data->istream));
      93    g_assert (g_output_stream_is_closed (data->ostream));
      94  
      95    if (data->flags & TEST_THREADED_ISTREAM)
      96      {
      97        g_unlink (data->input_path);
      98        g_free (data->input_path);
      99      }
     100  
     101    if (data->flags & TEST_THREADED_OSTREAM)
     102      {
     103        g_unlink (data->output_path);
     104        g_free (data->output_path);
     105      }
     106  
     107    g_main_loop_quit (data->main_loop);
     108  }
     109  
     110  static void
     111  test_copy_chunks_start (TestThreadedFlags flags)
     112  {
     113    TestCopyChunksData data;
     114    GError *error = NULL;
     115    GCancellable *cancellable = NULL;
     116  
     117    data.main_loop = g_main_loop_new (NULL, FALSE);
     118    data.data = "abcdefghijklmnopqrstuvwxyz";
     119    data.flags = flags;
     120  
     121    if (data.flags & TEST_CANCEL)
     122      {
     123        cancellable = g_cancellable_new ();
     124        g_cancellable_cancel (cancellable);
     125      }
     126  
     127    if (data.flags & TEST_THREADED_ISTREAM)
     128      {
     129        GFile *file;
     130        GFileIOStream *stream;
     131  
     132        file = g_file_new_tmp ("test-inputXXXXXX", &stream, &error);
     133        g_assert_no_error (error);
     134        g_object_unref (stream);
     135        data.input_path = g_file_get_path (file);
     136        g_file_set_contents (data.input_path,
     137                             data.data, strlen (data.data),
     138                             &error);
     139        g_assert_no_error (error);
     140        data.istream = G_INPUT_STREAM (g_file_read (file, NULL, &error));
     141        g_assert_no_error (error);
     142        g_object_unref (file);
     143      }
     144    else
     145      {
     146        data.istream = g_memory_input_stream_new_from_data (data.data, -1, NULL);
     147      }
     148  
     149    if (data.flags & TEST_THREADED_OSTREAM)
     150      {
     151        GFile *file;
     152        GFileIOStream *stream;
     153  
     154        file = g_file_new_tmp ("test-outputXXXXXX", &stream, &error);
     155        g_assert_no_error (error);
     156        g_object_unref (stream);
     157        data.output_path = g_file_get_path (file);
     158        data.ostream = G_OUTPUT_STREAM (g_file_replace (file, NULL, FALSE,
     159                                                        G_FILE_CREATE_NONE,
     160                                                        NULL, &error));
     161        g_assert_no_error (error);
     162        g_object_unref (file);
     163      }
     164    else
     165      {
     166        data.ostream = g_memory_output_stream_new (NULL, 0, g_realloc, g_free);
     167      }
     168  
     169    g_output_stream_splice_async (data.ostream, data.istream,
     170                                  G_OUTPUT_STREAM_SPLICE_CLOSE_SOURCE |
     171                                  G_OUTPUT_STREAM_SPLICE_CLOSE_TARGET,
     172                                  G_PRIORITY_DEFAULT, cancellable,
     173                                  test_copy_chunks_splice_cb, &data);
     174  
     175    /* We do not hold a ref in data struct, this is to make sure the operation
     176     * keeps the iostream objects alive until it finishes
     177     */
     178    g_object_unref (data.istream);
     179    g_object_unref (data.ostream);
     180    g_clear_object (&cancellable);
     181  
     182    g_main_loop_run (data.main_loop);
     183    g_main_loop_unref (data.main_loop);
     184  }
     185  
     186  static void
     187  test_copy_chunks (void)
     188  {
     189    test_copy_chunks_start (TEST_THREADED_NONE);
     190  }
     191  
     192  static void
     193  test_copy_chunks_threaded_input (void)
     194  {
     195    test_copy_chunks_start (TEST_THREADED_ISTREAM);
     196  }
     197  
     198  static void
     199  test_copy_chunks_threaded_output (void)
     200  {
     201    test_copy_chunks_start (TEST_THREADED_OSTREAM);
     202  }
     203  
     204  static void
     205  test_copy_chunks_threaded (void)
     206  {
     207    test_copy_chunks_start (TEST_THREADED_BOTH);
     208  }
     209  
     210  static void
     211  test_cancelled (void)
     212  {
     213    test_copy_chunks_start (TEST_THREADED_NONE | TEST_CANCEL);
     214  }
     215  
     216  int
     217  main (int   argc,
     218        char *argv[])
     219  {
     220    g_test_init (&argc, &argv, NULL);
     221  
     222    g_test_add_func ("/async-splice/copy-chunks", test_copy_chunks);
     223    g_test_add_func ("/async-splice/copy-chunks-threaded-input",
     224                     test_copy_chunks_threaded_input);
     225    g_test_add_func ("/async-splice/copy-chunks-threaded-output",
     226                     test_copy_chunks_threaded_output);
     227    g_test_add_func ("/async-splice/copy-chunks-threaded",
     228                     test_copy_chunks_threaded);
     229    g_test_add_func ("/async-splice/cancelled",
     230                     test_cancelled);
     231  
     232    return g_test_run();
     233  }