(root)/
glib-2.79.0/
glib/
tests/
io-channel.c
       1  /* GLib testing framework examples and tests
       2   *
       3   * Copyright © 2001 Hidetoshi Tajima
       4   * Copyright © 2001 Ron Steinke
       5   * Copyright © 2001 Owen Taylor
       6   * Copyright © 2002 Manish Singh
       7   * Copyright © 2011 Sjoerd Simons
       8   * Copyright © 2012 Simon McVittie
       9   * Copyright © 2013 Stef Walter
      10   * Copyright © 2005, 2006, 2008, 2012, 2013 Matthias Clasen
      11   * Copyright © 2020 Endless Mobile, Inc.
      12   *
      13   * SPDX-License-Identifier: LGPL-2.1-or-later
      14   *
      15   * This library is free software; you can redistribute it and/or
      16   * modify it under the terms of the GNU Lesser General Public
      17   * License as published by the Free Software Foundation; either
      18   * version 2.1 of the License, or (at your option) any later version.
      19   *
      20   * This library is distributed in the hope that it will be useful,
      21   * but WITHOUT ANY WARRANTY; without even the implied warranty of
      22   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      23   * Lesser General Public License for more details.
      24   *
      25   * You should have received a copy of the GNU Lesser General
      26   * Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
      27   *
      28   * Author: Philip Withnall <withnall@endlessm.com>
      29   */
      30  
      31  #include <glib.h>
      32  #include <glib/gstdio.h>
      33  
      34  static void
      35  test_small_writes (void)
      36  {
      37    GIOChannel *io;
      38    GIOStatus status = G_IO_STATUS_ERROR;
      39    guint bytes_remaining;
      40    gchar tmp;
      41    GError *local_error = NULL;
      42  
      43    io = g_io_channel_new_file ("iochannel-test-outfile", "w", &local_error);
      44    g_assert_no_error (local_error);
      45  
      46    g_io_channel_set_encoding (io, NULL, NULL);
      47    g_io_channel_set_buffer_size (io, 1022);
      48  
      49    bytes_remaining = 2 * g_io_channel_get_buffer_size (io);
      50    tmp = 0;
      51  
      52    while (bytes_remaining)
      53      {
      54        status = g_io_channel_write_chars (io, &tmp, 1, NULL, NULL);
      55        if (status == G_IO_STATUS_ERROR)
      56          break;
      57        if (status == G_IO_STATUS_NORMAL)
      58          bytes_remaining--;
      59      }
      60  
      61    g_assert_cmpint (status, ==, G_IO_STATUS_NORMAL);
      62  
      63    g_io_channel_unref (io);
      64    g_remove ("iochannel-test-outfile");
      65  }
      66  
      67  static void
      68  test_read_write (void)
      69  {
      70    GIOChannel *gio_r, *gio_w ;
      71    GError *local_error = NULL;
      72    GString *buffer;
      73    char *filename;
      74    gint rlength = 0;
      75    glong wlength = 0;
      76    gsize length_out;
      77    const gchar *encoding = "EUC-JP";
      78    GIOStatus status;
      79    const gsize buffer_size_bytes = 1024;
      80  
      81    filename = g_test_build_filename (G_TEST_DIST, "iochannel-test-infile", NULL);
      82  
      83    setbuf (stdout, NULL); /* For debugging */
      84  
      85    gio_r = g_io_channel_new_file (filename, "r", &local_error);
      86    g_assert_no_error (local_error);
      87  
      88    gio_w = g_io_channel_new_file ("iochannel-test-outfile", "w", &local_error);
      89    g_assert_no_error (local_error);
      90  
      91    g_io_channel_set_encoding (gio_r, encoding, &local_error);
      92    g_assert_no_error (local_error);
      93  
      94    g_io_channel_set_buffer_size (gio_r, buffer_size_bytes);
      95  
      96    status = g_io_channel_set_flags (gio_r, G_IO_FLAG_NONBLOCK, &local_error);
      97    if (status == G_IO_STATUS_ERROR)
      98      {
      99  #ifdef G_OS_WIN32
     100        g_test_message ("FIXME: not implemented on win32");
     101  #else
     102        /* Errors should not happen */
     103        g_assert_no_error (local_error);
     104  #endif
     105        g_clear_error (&local_error);
     106      }
     107    buffer = g_string_sized_new (buffer_size_bytes);
     108  
     109    while (TRUE)
     110      {
     111        do
     112          status = g_io_channel_read_line_string (gio_r, buffer, NULL, &local_error);
     113        while (status == G_IO_STATUS_AGAIN);
     114        if (status != G_IO_STATUS_NORMAL)
     115          break;
     116  
     117        rlength += buffer->len;
     118  
     119        do
     120          status = g_io_channel_write_chars (gio_w, buffer->str, buffer->len,
     121            &length_out, &local_error);
     122        while (status == G_IO_STATUS_AGAIN);
     123        if (status != G_IO_STATUS_NORMAL)
     124          break;
     125  
     126        wlength += length_out;
     127  
     128        /* Ensure the whole line was written */
     129        g_assert_cmpuint (length_out, ==, buffer->len);
     130  
     131        g_test_message ("%s", buffer->str);
     132        g_string_truncate (buffer, 0);
     133      }
     134  
     135    switch (status)
     136      {
     137        case G_IO_STATUS_EOF:
     138          break;
     139        case G_IO_STATUS_ERROR:
     140          /* Errors should not happen */
     141          g_assert_no_error (local_error);
     142          g_clear_error (&local_error);
     143          break;
     144        default:
     145          g_assert_not_reached ();
     146          break;
     147      }
     148  
     149    do
     150      status = g_io_channel_flush (gio_w, &local_error);
     151    while (status == G_IO_STATUS_AGAIN);
     152  
     153    if (status == G_IO_STATUS_ERROR)
     154      {
     155        /* Errors should not happen */
     156        g_assert_no_error (local_error);
     157        g_clear_error (&local_error);
     158      }
     159  
     160    g_test_message ("read %d bytes, wrote %ld bytes", rlength, wlength);
     161  
     162    g_io_channel_unref (gio_r);
     163    g_io_channel_unref (gio_w);
     164  
     165    test_small_writes ();
     166  
     167    g_free (filename);
     168    g_string_free (buffer, TRUE);
     169  }
     170  
     171  static void
     172  test_read_line_embedded_nuls (void)
     173  {
     174    const guint8 test_data[] = { 'H', 'i', '!', '\0', 'y', 'o', 'u', '\n', ':', ')', '\n' };
     175    gint fd;
     176    gchar *filename = NULL;
     177    GIOChannel *channel = NULL;
     178    GError *local_error = NULL;
     179    gchar *line = NULL;
     180    gsize line_length, terminator_pos;
     181    GIOStatus status;
     182  
     183    g_test_summary ("Test that reading a line containing embedded nuls works "
     184                    "when using non-standard line terminators.");
     185  
     186    /* Write out a temporary file. */
     187    fd = g_file_open_tmp ("glib-test-io-channel-XXXXXX", &filename, &local_error);
     188    g_assert_no_error (local_error);
     189    g_close (fd, NULL);
     190    fd = -1;
     191  
     192    g_file_set_contents (filename, (const gchar *) test_data, sizeof (test_data), &local_error);
     193    g_assert_no_error (local_error);
     194  
     195    /* Create the channel. */
     196    channel = g_io_channel_new_file (filename, "r", &local_error);
     197    g_assert_no_error (local_error);
     198  
     199    /* Only break on newline characters, not nuls.
     200     * Use length -1 here to exercise glib#2323; the case where length > 0
     201     * is covered in glib/tests/protocol.c. */
     202    g_io_channel_set_line_term (channel, "\n", -1);
     203    g_io_channel_set_encoding (channel, NULL, &local_error);
     204    g_assert_no_error (local_error);
     205  
     206    status = g_io_channel_read_line (channel, &line, &line_length,
     207                                     &terminator_pos, &local_error);
     208    g_assert_no_error (local_error);
     209    g_assert_cmpint (status, ==, G_IO_STATUS_NORMAL);
     210    g_assert_cmpuint (line_length, ==, 8);
     211    g_assert_cmpuint (terminator_pos, ==, 7);
     212    g_assert_cmpmem (line, line_length, test_data, 8);
     213  
     214    g_free (line);
     215    g_io_channel_unref (channel);
     216    g_free (filename);
     217  }
     218  
     219  int
     220  main (int   argc,
     221        char *argv[])
     222  {
     223    g_test_init (&argc, &argv, NULL);
     224  
     225    g_test_add_func ("/io-channel/read-write", test_read_write);
     226    g_test_add_func ("/io-channel/read-line/embedded-nuls", test_read_line_embedded_nuls);
     227  
     228    return g_test_run ();
     229  }