(root)/
glib-2.79.0/
gio/
tests/
converter-stream.c
       1  /* GLib testing framework examples and tests
       2   * Copyright (C) 2009 Red Hat, Inc.
       3   * Authors: Alexander Larsson <alexl@redhat.com>
       4   *
       5   * SPDX-License-Identifier: LicenseRef-old-glib-tests
       6   *
       7   * This work is provided "as is"; redistribution and modification
       8   * in whole or in part, in any medium, physical or electronic is
       9   * permitted without restriction.
      10   *
      11   * This work 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.
      14   *
      15   * In no event shall the authors or contributors be liable for any
      16   * direct, indirect, incidental, special, exemplary, or consequential
      17   * damages (including, but not limited to, procurement of substitute
      18   * goods or services; loss of use, data, or profits; or business
      19   * interruption) however caused and on any theory of liability, whether
      20   * in contract, strict liability, or tort (including negligence or
      21   * otherwise) arising in any way out of the use of this software, even
      22   * if advised of the possibility of such damage.
      23   */
      24  
      25  #include <glib/glib.h>
      26  #include <gio/gio.h>
      27  #include <stdlib.h>
      28  #include <string.h>
      29  
      30  #define G_TYPE_EXPANDER_CONVERTER         (g_expander_converter_get_type ())
      31  #define G_EXPANDER_CONVERTER(o)           (G_TYPE_CHECK_INSTANCE_CAST ((o), G_TYPE_EXPANDER_CONVERTER, GExpanderConverter))
      32  #define G_EXPANDER_CONVERTER_CLASS(k)     (G_TYPE_CHECK_CLASS_CAST((k), G_TYPE_EXPANDER_CONVERTER, GExpanderConverterClass))
      33  #define G_IS_EXPANDER_CONVERTER(o)        (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_TYPE_EXPANDER_CONVERTER))
      34  #define G_IS_EXPANDER_CONVERTER_CLASS(k)  (G_TYPE_CHECK_CLASS_TYPE ((k), G_TYPE_EXPANDER_CONVERTER))
      35  #define G_EXPANDER_CONVERTER_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), G_TYPE_EXPANDER_CONVERTER, GExpanderConverterClass))
      36  
      37  typedef struct _GExpanderConverter       GExpanderConverter;
      38  typedef struct _GExpanderConverterClass  GExpanderConverterClass;
      39  
      40  struct _GExpanderConverterClass
      41  {
      42    GObjectClass parent_class;
      43  };
      44  
      45  GType       g_expander_converter_get_type (void) G_GNUC_CONST;
      46  GConverter *g_expander_converter_new      (void);
      47  
      48  
      49  
      50  static void g_expander_converter_iface_init          (GConverterIface *iface);
      51  
      52  struct _GExpanderConverter
      53  {
      54    GObject parent_instance;
      55  };
      56  
      57  G_DEFINE_TYPE_WITH_CODE (GExpanderConverter, g_expander_converter, G_TYPE_OBJECT,
      58  			 G_IMPLEMENT_INTERFACE (G_TYPE_CONVERTER,
      59  						g_expander_converter_iface_init))
      60  
      61  static void
      62  g_expander_converter_class_init (GExpanderConverterClass *klass)
      63  {
      64  }
      65  
      66  static void
      67  g_expander_converter_init (GExpanderConverter *local)
      68  {
      69  }
      70  
      71  GConverter *
      72  g_expander_converter_new (void)
      73  {
      74    GConverter *conv;
      75  
      76    conv = g_object_new (G_TYPE_EXPANDER_CONVERTER, NULL);
      77  
      78    return conv;
      79  }
      80  
      81  static void
      82  g_expander_converter_reset (GConverter *converter)
      83  {
      84  }
      85  
      86  static GConverterResult
      87  g_expander_converter_convert (GConverter *converter,
      88  			      const void *inbuf,
      89  			      gsize       inbuf_size,
      90  			      void       *outbuf,
      91  			      gsize       outbuf_size,
      92  			      GConverterFlags flags,
      93  			      gsize      *bytes_read,
      94  			      gsize      *bytes_written,
      95  			      GError    **error)
      96  {
      97    const guint8 *in, *in_end;
      98    guint8 v, *out;
      99    gsize i;
     100    gsize block_size;
     101  
     102    in = inbuf;
     103    out = outbuf;
     104    in_end = in + inbuf_size;
     105  
     106    while (in < in_end)
     107      {
     108        v = *in;
     109  
     110        if (v == 0)
     111  	block_size = 10;
     112        else
     113  	block_size = v * 1000;
     114  
     115        if (outbuf_size < block_size)
     116  	{
     117  	  if (*bytes_read > 0)
     118  	    return G_CONVERTER_CONVERTED;
     119  
     120  	  g_set_error_literal (error, G_IO_ERROR,
     121  			       G_IO_ERROR_NO_SPACE,
     122  			       "No space in dest");
     123  	  return G_CONVERTER_ERROR;
     124  	}
     125  
     126        in++;
     127        *bytes_read += 1;
     128        *bytes_written += block_size;
     129        outbuf_size -= block_size;
     130        for (i = 0; i < block_size; i++)
     131  	*out++ = v;
     132      }
     133  
     134    if (in == in_end && (flags & G_CONVERTER_INPUT_AT_END))
     135      return G_CONVERTER_FINISHED;
     136    return G_CONVERTER_CONVERTED;
     137  }
     138  
     139  static void
     140  g_expander_converter_iface_init (GConverterIface *iface)
     141  {
     142    iface->convert = g_expander_converter_convert;
     143    iface->reset = g_expander_converter_reset;
     144  }
     145  
     146  #define G_TYPE_COMPRESSOR_CONVERTER         (g_compressor_converter_get_type ())
     147  #define G_COMPRESSOR_CONVERTER(o)           (G_TYPE_CHECK_INSTANCE_CAST ((o), G_TYPE_COMPRESSOR_CONVERTER, GCompressorConverter))
     148  #define G_COMPRESSOR_CONVERTER_CLASS(k)     (G_TYPE_CHECK_CLASS_CAST((k), G_TYPE_COMPRESSOR_CONVERTER, GCompressorConverterClass))
     149  #define G_IS_COMPRESSOR_CONVERTER(o)        (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_TYPE_COMPRESSOR_CONVERTER))
     150  #define G_IS_COMPRESSOR_CONVERTER_CLASS(k)  (G_TYPE_CHECK_CLASS_TYPE ((k), G_TYPE_COMPRESSOR_CONVERTER))
     151  #define G_COMPRESSOR_CONVERTER_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), G_TYPE_COMPRESSOR_CONVERTER, GCompressorConverterClass))
     152  
     153  typedef struct _GCompressorConverter       GCompressorConverter;
     154  typedef struct _GCompressorConverterClass  GCompressorConverterClass;
     155  
     156  struct _GCompressorConverterClass
     157  {
     158    GObjectClass parent_class;
     159  };
     160  
     161  GType       g_compressor_converter_get_type (void) G_GNUC_CONST;
     162  GConverter *g_compressor_converter_new      (void);
     163  
     164  
     165  
     166  static void g_compressor_converter_iface_init          (GConverterIface *iface);
     167  
     168  struct _GCompressorConverter
     169  {
     170    GObject parent_instance;
     171  };
     172  
     173  G_DEFINE_TYPE_WITH_CODE (GCompressorConverter, g_compressor_converter, G_TYPE_OBJECT,
     174  			 G_IMPLEMENT_INTERFACE (G_TYPE_CONVERTER,
     175  						g_compressor_converter_iface_init))
     176  
     177  static void
     178  g_compressor_converter_class_init (GCompressorConverterClass *klass)
     179  {
     180  }
     181  
     182  static void
     183  g_compressor_converter_init (GCompressorConverter *local)
     184  {
     185  }
     186  
     187  GConverter *
     188  g_compressor_converter_new (void)
     189  {
     190    GConverter *conv;
     191  
     192    conv = g_object_new (G_TYPE_COMPRESSOR_CONVERTER, NULL);
     193  
     194    return conv;
     195  }
     196  
     197  static void
     198  g_compressor_converter_reset (GConverter *converter)
     199  {
     200  }
     201  
     202  static GConverterResult
     203  g_compressor_converter_convert (GConverter *converter,
     204  				const void *inbuf,
     205  				gsize       inbuf_size,
     206  				void       *outbuf,
     207  				gsize       outbuf_size,
     208  				GConverterFlags flags,
     209  				gsize      *bytes_read,
     210  				gsize      *bytes_written,
     211  				GError    **error)
     212  {
     213    const guint8 *in, *in_end;
     214    guint8 v, *out;
     215    gsize i;
     216    gsize block_size;
     217  
     218    in = inbuf;
     219    out = outbuf;
     220    in_end = in + inbuf_size;
     221  
     222    while (in < in_end)
     223      {
     224        v = *in;
     225  
     226        if (v == 0)
     227  	{
     228  	  block_size = 0;
     229  	  while (in+block_size < in_end && *(in+block_size) == 0)
     230  	    block_size ++;
     231  	}
     232        else
     233  	block_size = v * 1000;
     234  
     235        /* Not enough data */
     236        if ((gsize) (in_end - in) < block_size)
     237  	{
     238  	  if (*bytes_read > 0)
     239  	    break;
     240  	  g_set_error_literal (error, G_IO_ERROR,
     241  			       G_IO_ERROR_PARTIAL_INPUT,
     242  			       "Need more data");
     243  	  return G_CONVERTER_ERROR;
     244  	}
     245  
     246        for (i = 0; i < block_size; i++)
     247  	{
     248  	  if (*(in + i) != v)
     249  	    {
     250  	      if (*bytes_read > 0)
     251  		break;
     252  	      g_set_error_literal (error, G_IO_ERROR,
     253  				   G_IO_ERROR_INVALID_DATA,
     254  				   "invalid data");
     255  	      return G_CONVERTER_ERROR;
     256  	    }
     257  	}
     258  
     259        if (v == 0 && (gsize) (in_end - in) == block_size && (flags & G_CONVERTER_INPUT_AT_END) == 0)
     260  	{
     261  	  if (*bytes_read > 0)
     262  	    break;
     263  	  g_set_error_literal (error, G_IO_ERROR,
     264  			       G_IO_ERROR_PARTIAL_INPUT,
     265  			       "Need more data");
     266  	  return G_CONVERTER_ERROR;
     267  	}
     268  
     269        in += block_size;
     270        *out++ = v;
     271        *bytes_read += block_size;
     272        *bytes_written += 1;
     273      }
     274  
     275    if (in == in_end && (flags & G_CONVERTER_INPUT_AT_END))
     276      return G_CONVERTER_FINISHED;
     277    return G_CONVERTER_CONVERTED;
     278  }
     279  
     280  static void
     281  g_compressor_converter_iface_init (GConverterIface *iface)
     282  {
     283    iface->convert = g_compressor_converter_convert;
     284    iface->reset = g_compressor_converter_reset;
     285  }
     286  
     287  guint8 unexpanded_data[] = { 0,1,3,4,5,6,7,3,12,0,0};
     288  
     289  static void
     290  test_expander (void)
     291  {
     292    guint8 *converted1, *converted2, *ptr;
     293    gsize n_read, n_written;
     294    gsize total_read;
     295    gssize res;
     296    GConverterResult cres;
     297    GInputStream *mem, *cstream;
     298    GOutputStream *mem_out, *cstream_out;
     299    GConverter *expander;
     300    GConverter *converter;
     301    GError *error;
     302    gsize i;
     303  
     304    expander = g_expander_converter_new ();
     305  
     306    converted1 = g_malloc (100*1000); /* Large enough */
     307    converted2 = g_malloc (100*1000); /* Large enough */
     308  
     309    cres = g_converter_convert (expander,
     310  			      unexpanded_data, sizeof(unexpanded_data),
     311  			      converted1, 100*1000,
     312  			      G_CONVERTER_INPUT_AT_END,
     313  			      &n_read, &n_written, NULL);
     314  
     315    g_assert_cmpint (cres, ==, G_CONVERTER_FINISHED);
     316    g_assert_cmpuint (n_read, ==, 11);
     317    g_assert_cmpuint (n_written, ==, 41030);
     318  
     319    g_converter_reset (expander);
     320  
     321    mem = g_memory_input_stream_new_from_data (unexpanded_data,
     322  					     sizeof (unexpanded_data),
     323  					     NULL);
     324    cstream = g_converter_input_stream_new (mem, expander);
     325    g_assert_true (g_converter_input_stream_get_converter (G_CONVERTER_INPUT_STREAM (cstream)) == expander);
     326    g_object_get (cstream, "converter", &converter, NULL);
     327    g_assert_true (converter == expander);
     328    g_object_unref (converter);
     329    g_object_unref (mem);
     330  
     331    total_read = 0;
     332    ptr = converted2;
     333    while (TRUE)
     334      {
     335        error = NULL;
     336        res = g_input_stream_read (cstream,
     337  				 ptr, 1,
     338  				 NULL, &error);
     339        g_assert_cmpint (res, !=, -1);
     340        if (res == 0)
     341  	break;
     342        ptr += res;
     343        total_read += res;
     344      }
     345  
     346    g_assert_cmpmem (converted1, n_written, converted2, total_read);
     347  
     348    g_converter_reset (expander);
     349  
     350    mem_out = g_memory_output_stream_new (NULL, 0, g_realloc, g_free);
     351    cstream_out = g_converter_output_stream_new (mem_out, expander);
     352    g_assert_true (g_converter_output_stream_get_converter (G_CONVERTER_OUTPUT_STREAM (cstream_out)) == expander);
     353    g_object_get (cstream_out, "converter", &converter, NULL);
     354    g_assert_true (converter == expander);
     355    g_object_unref (converter);
     356    g_object_unref (mem_out);
     357  
     358    for (i = 0; i < sizeof(unexpanded_data); i++)
     359      {
     360        error = NULL;
     361        res = g_output_stream_write (cstream_out,
     362  				   unexpanded_data + i, 1,
     363  				   NULL, &error);
     364        g_assert_cmpint (res, !=, -1);
     365        if (res == 0)
     366  	{
     367  	  g_assert_cmpuint (i, ==, sizeof(unexpanded_data) -1);
     368  	  break;
     369  	}
     370        g_assert_cmpint (res, ==, 1);
     371      }
     372  
     373    g_output_stream_close (cstream_out, NULL, NULL);
     374  
     375    g_assert_cmpmem (g_memory_output_stream_get_data (G_MEMORY_OUTPUT_STREAM (mem_out)),
     376                     g_memory_output_stream_get_data_size (G_MEMORY_OUTPUT_STREAM (mem_out)),
     377                     converted1, n_written);
     378  
     379    g_free (converted1);
     380    g_free (converted2);
     381    g_object_unref (cstream);
     382    g_object_unref (cstream_out);
     383    g_object_unref (expander);
     384  }
     385  
     386  static void
     387  test_compressor (void)
     388  {
     389    guint8 *converted, *expanded, *ptr;
     390    gsize n_read, expanded_size;
     391    gsize total_read;
     392    gssize res;
     393    GConverterResult cres;
     394    GInputStream *mem, *cstream;
     395    GOutputStream *mem_out, *cstream_out;
     396    GConverter *expander, *compressor;
     397    GError *error;
     398    gsize i;
     399  
     400    expander = g_expander_converter_new ();
     401    expanded = g_malloc (100*1000); /* Large enough */
     402    cres = g_converter_convert (expander,
     403  			      unexpanded_data, sizeof(unexpanded_data),
     404  			      expanded, 100*1000,
     405  			      G_CONVERTER_INPUT_AT_END,
     406  			      &n_read, &expanded_size, NULL);
     407    g_assert_cmpint (cres, ==, G_CONVERTER_FINISHED);
     408    g_assert_cmpuint (n_read, ==, 11);
     409    g_assert_cmpuint (expanded_size, ==, 41030);
     410  
     411    compressor = g_compressor_converter_new ();
     412  
     413    converted = g_malloc (100*1000); /* Large enough */
     414  
     415    mem = g_memory_input_stream_new_from_data (expanded,
     416  					     expanded_size,
     417  					     NULL);
     418    cstream = g_converter_input_stream_new (mem, compressor);
     419    g_object_unref (mem);
     420  
     421    total_read = 0;
     422    ptr = converted;
     423    while (TRUE)
     424      {
     425        error = NULL;
     426        res = g_input_stream_read (cstream,
     427  				 ptr, 1,
     428  				 NULL, &error);
     429        g_assert_cmpint (res, !=, -1);
     430        if (res == 0)
     431  	break;
     432        ptr += res;
     433        total_read += res;
     434      }
     435  
     436    /* "n_read - 1" because last 2 zeros are combined */
     437    g_assert_cmpmem (unexpanded_data, n_read - 1, converted, total_read);
     438  
     439    g_object_unref (cstream);
     440  
     441    g_converter_reset (compressor);
     442  
     443    mem_out = g_memory_output_stream_new (NULL, 0, g_realloc, g_free);
     444    cstream_out = g_converter_output_stream_new (mem_out, compressor);
     445    g_object_unref (mem_out);
     446  
     447    for (i = 0; i < expanded_size; i++)
     448      {
     449        error = NULL;
     450        res = g_output_stream_write (cstream_out,
     451  				   expanded + i, 1,
     452  				   NULL, &error);
     453        g_assert_cmpint (res, !=, -1);
     454        if (res == 0)
     455  	{
     456  	  g_assert_cmpuint (i, ==, expanded_size -1);
     457  	  break;
     458  	}
     459        g_assert_cmpint (res, ==, 1);
     460      }
     461  
     462    g_output_stream_close (cstream_out, NULL, NULL);
     463  
     464    /* "n_read - 1" because last 2 zeros are combined */
     465    g_assert_cmpmem (g_memory_output_stream_get_data (G_MEMORY_OUTPUT_STREAM (mem_out)),
     466                     g_memory_output_stream_get_data_size (G_MEMORY_OUTPUT_STREAM (mem_out)),
     467                     unexpanded_data,
     468                     n_read - 1);
     469  
     470    g_object_unref (cstream_out);
     471  
     472    g_converter_reset (compressor);
     473  
     474    memset (expanded, 5, 5*1000*2);
     475  
     476    mem = g_memory_input_stream_new_from_data (expanded,
     477  					     5*1000,
     478  					     NULL);
     479    cstream = g_converter_input_stream_new (mem, compressor);
     480    g_object_unref (mem);
     481  
     482    total_read = 0;
     483    ptr = converted;
     484    while (TRUE)
     485      {
     486        error = NULL;
     487        res = g_input_stream_read (cstream,
     488  				 ptr, 1,
     489  				 NULL, &error);
     490        g_assert_cmpint (res, !=, -1);
     491        if (res == 0)
     492  	break;
     493        ptr += res;
     494        total_read += res;
     495      }
     496  
     497    g_assert_cmpuint (total_read, ==, 1);
     498    g_assert_cmpuint (*converted, ==, 5);
     499  
     500    g_object_unref (cstream);
     501  
     502    mem = g_memory_input_stream_new_from_data (expanded,
     503  					     5*1000 * 2,
     504  					     NULL);
     505    cstream = g_converter_input_stream_new (mem, compressor);
     506    g_object_unref (mem);
     507  
     508    total_read = 0;
     509    ptr = converted;
     510    while (TRUE)
     511      {
     512        error = NULL;
     513        res = g_input_stream_read (cstream,
     514  				 ptr, 1,
     515  				 NULL, &error);
     516        g_assert_cmpint (res, !=, -1);
     517        if (res == 0)
     518  	break;
     519        ptr += res;
     520        total_read += res;
     521      }
     522  
     523    g_assert_cmpuint (total_read, ==, 2);
     524    g_assert_cmpuint (converted[0], ==, 5);
     525    g_assert_cmpuint (converted[1], ==, 5);
     526  
     527    g_object_unref (cstream);
     528  
     529    g_converter_reset (compressor);
     530  
     531    mem = g_memory_input_stream_new_from_data (expanded,
     532  					     5*1000 * 2 - 1,
     533  					     NULL);
     534    cstream = g_converter_input_stream_new (mem, compressor);
     535    g_object_unref (mem);
     536  
     537    total_read = 0;
     538    ptr = converted;
     539    while (TRUE)
     540      {
     541        error = NULL;
     542        res = g_input_stream_read (cstream,
     543  				 ptr, 1,
     544  				 NULL, &error);
     545        if (res == -1)
     546  	{
     547  	  g_assert_error (error, G_IO_ERROR, G_IO_ERROR_PARTIAL_INPUT);
     548            g_error_free (error);
     549  	  break;
     550  	}
     551  
     552        g_assert_cmpint (res, !=, 0);
     553        ptr += res;
     554        total_read += res;
     555      }
     556  
     557    g_assert_cmpuint (total_read, ==, 1);
     558    g_assert_cmpuint (converted[0], ==, 5);
     559  
     560    g_object_unref (cstream);
     561  
     562    g_free (expanded);
     563    g_free (converted);
     564    g_object_unref (expander);
     565    g_object_unref (compressor);
     566  }
     567  
     568  #define LEFTOVER_SHORT_READ_SIZE 512
     569  
     570  #define G_TYPE_LEFTOVER_CONVERTER         (g_leftover_converter_get_type ())
     571  #define G_LEFTOVER_CONVERTER(o)           (G_TYPE_CHECK_INSTANCE_CAST ((o), G_TYPE_LEFTOVER_CONVERTER, GLeftoverConverter))
     572  #define G_LEFTOVER_CONVERTER_CLASS(k)     (G_TYPE_CHECK_CLASS_CAST((k), G_TYPE_LEFTOVER_CONVERTER, GLeftoverConverterClass))
     573  #define G_IS_LEFTOVER_CONVERTER(o)        (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_TYPE_LEFTOVER_CONVERTER))
     574  #define G_IS_LEFTOVER_CONVERTER_CLASS(k)  (G_TYPE_CHECK_CLASS_TYPE ((k), G_TYPE_LEFTOVER_CONVERTER))
     575  #define G_LEFTOVER_CONVERTER_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), G_TYPE_LEFTOVER_CONVERTER, GLeftoverConverterClass))
     576  
     577  typedef struct _GLeftoverConverter       GLeftoverConverter;
     578  typedef struct _GLeftoverConverterClass  GLeftoverConverterClass;
     579  
     580  struct _GLeftoverConverterClass
     581  {
     582    GObjectClass parent_class;
     583  };
     584  
     585  GType       g_leftover_converter_get_type (void) G_GNUC_CONST;
     586  GConverter *g_leftover_converter_new      (void);
     587  
     588  
     589  
     590  static void g_leftover_converter_iface_init          (GConverterIface *iface);
     591  
     592  struct _GLeftoverConverter
     593  {
     594    GObject parent_instance;
     595  };
     596  
     597  G_DEFINE_TYPE_WITH_CODE (GLeftoverConverter, g_leftover_converter, G_TYPE_OBJECT,
     598  			 G_IMPLEMENT_INTERFACE (G_TYPE_CONVERTER,
     599  						g_leftover_converter_iface_init))
     600  
     601  static void
     602  g_leftover_converter_class_init (GLeftoverConverterClass *klass)
     603  {
     604  }
     605  
     606  static void
     607  g_leftover_converter_init (GLeftoverConverter *local)
     608  {
     609  }
     610  
     611  GConverter *
     612  g_leftover_converter_new (void)
     613  {
     614    GConverter *conv;
     615  
     616    conv = g_object_new (G_TYPE_LEFTOVER_CONVERTER, NULL);
     617  
     618    return conv;
     619  }
     620  
     621  static void
     622  g_leftover_converter_reset (GConverter *converter)
     623  {
     624  }
     625  
     626  static GConverterResult
     627  g_leftover_converter_convert (GConverter *converter,
     628  			      const void *inbuf,
     629  			      gsize       inbuf_size,
     630  			      void       *outbuf,
     631  			      gsize       outbuf_size,
     632  			      GConverterFlags flags,
     633  			      gsize      *bytes_read,
     634  			      gsize      *bytes_written,
     635  			      GError    **error)
     636  {
     637    if (outbuf_size == LEFTOVER_SHORT_READ_SIZE)
     638      {
     639        g_set_error_literal (error,
     640  			   G_IO_ERROR,
     641  			   G_IO_ERROR_PARTIAL_INPUT,
     642  			   "partial input");
     643        return G_CONVERTER_ERROR;
     644      }
     645  
     646    if (inbuf_size < 100)
     647      *bytes_read = *bytes_written = MIN (inbuf_size, outbuf_size);
     648    else
     649      *bytes_read = *bytes_written = MIN (inbuf_size - 10, outbuf_size);
     650    memcpy (outbuf, inbuf, *bytes_written);
     651  
     652    if (*bytes_read == inbuf_size && (flags & G_CONVERTER_INPUT_AT_END))
     653      return G_CONVERTER_FINISHED;
     654    return G_CONVERTER_CONVERTED;
     655  }
     656  
     657  static void
     658  g_leftover_converter_iface_init (GConverterIface *iface)
     659  {
     660    iface->convert = g_leftover_converter_convert;
     661    iface->reset = g_leftover_converter_reset;
     662  }
     663  
     664  #define LEFTOVER_BUFSIZE 8192
     665  #define INTERNAL_BUFSIZE 4096
     666  
     667  static void
     668  test_converter_leftover (void)
     669  {
     670    gchar *orig, *converted;
     671    gsize total_read;
     672    gssize res;
     673    goffset offset;
     674    GInputStream *mem, *cstream;
     675    GConverter *converter;
     676    GError *error;
     677    int i;
     678  
     679    converter = g_leftover_converter_new ();
     680  
     681    orig = g_malloc (LEFTOVER_BUFSIZE);
     682    converted = g_malloc (LEFTOVER_BUFSIZE);
     683    for (i = 0; i < LEFTOVER_BUFSIZE; i++)
     684      orig[i] = i % 64 + 32;
     685  
     686    mem = g_memory_input_stream_new_from_data (orig, LEFTOVER_BUFSIZE, NULL);
     687    cstream = g_converter_input_stream_new (mem, G_CONVERTER (converter));
     688    g_object_unref (mem);
     689  
     690    total_read = 0;
     691  
     692    error = NULL;
     693    res = g_input_stream_read (cstream,
     694  			     converted, LEFTOVER_SHORT_READ_SIZE,
     695  			     NULL, &error);
     696    g_assert_cmpint (res, ==, LEFTOVER_SHORT_READ_SIZE);
     697    total_read += res;
     698  
     699    offset = g_seekable_tell (G_SEEKABLE (mem));
     700    g_assert_cmpint (offset, >, LEFTOVER_SHORT_READ_SIZE);
     701    g_assert_cmpint (offset, <, LEFTOVER_BUFSIZE);
     702  
     703    /* At this point, @cstream has both a non-empty input_buffer
     704     * and a non-empty converted_buffer, which is the case
     705     * we want to test.
     706     */
     707  
     708    while (TRUE)
     709      {
     710        error = NULL;
     711        res = g_input_stream_read (cstream,
     712  				 converted + total_read,
     713  				 LEFTOVER_BUFSIZE - total_read,
     714  				 NULL, &error);
     715        g_assert_cmpint (res, >=, 0);
     716        if (res == 0)
     717  	break;
     718        total_read += res;
     719    }
     720  
     721    g_assert_cmpmem (orig, LEFTOVER_BUFSIZE, converted, total_read);
     722  
     723    g_object_unref (cstream);
     724    g_free (orig);
     725    g_free (converted);
     726    g_object_unref (converter);
     727  }
     728  
     729  #define DATA_LENGTH 1000000
     730  
     731  typedef struct {
     732    const gchar *path;
     733    GZlibCompressorFormat format;
     734    gint level;
     735  } CompressorTest;
     736  
     737  static void
     738  test_roundtrip (gconstpointer data)
     739  {
     740    const CompressorTest *test = data;
     741    GError *error = NULL;
     742    guint32 *data0, *data1;
     743    gsize data1_size;
     744    gint i;
     745    GInputStream *istream0, *istream1, *cistream1;
     746    GOutputStream *ostream1, *ostream2, *costream1;
     747    GConverter *compressor, *decompressor;
     748    GZlibCompressorFormat fmt;
     749    gint lvl;
     750    GFileInfo *info;
     751    GFileInfo *info2;
     752  
     753    g_test_bug ("https://bugzilla.gnome.org/show_bug.cgi?id=619945");
     754  
     755    data0 = g_malloc (DATA_LENGTH * sizeof (guint32));
     756    for (i = 0; i < DATA_LENGTH; i++)
     757      data0[i] = g_random_int ();
     758  
     759    istream0 = g_memory_input_stream_new_from_data (data0,
     760      DATA_LENGTH * sizeof (guint32), NULL);
     761  
     762    ostream1 = g_memory_output_stream_new (NULL, 0, g_realloc, g_free);
     763    compressor = G_CONVERTER (g_zlib_compressor_new (test->format, test->level));
     764    info = g_file_info_new ();
     765    g_file_info_set_name (info, "foo");
     766    g_object_set (compressor, "file-info", info, NULL);
     767    info2 = g_zlib_compressor_get_file_info (G_ZLIB_COMPRESSOR (compressor));
     768    g_assert_true (info == info2);
     769    g_object_unref (info);
     770    costream1 = g_converter_output_stream_new (ostream1, compressor);
     771    g_assert_true (g_converter_output_stream_get_converter (G_CONVERTER_OUTPUT_STREAM (costream1)) == compressor);
     772  
     773    g_output_stream_splice (costream1, istream0, 0, NULL, &error);
     774    g_assert_no_error (error);
     775  
     776    g_object_unref (costream1);
     777  
     778    g_converter_reset (compressor);
     779    g_object_get (compressor, "format", &fmt, "level", &lvl, NULL);
     780    g_assert_cmpint (fmt, ==, test->format);
     781    g_assert_cmpint (lvl, ==, test->level);
     782    g_object_unref (compressor);
     783    data1 = g_memory_output_stream_steal_data (G_MEMORY_OUTPUT_STREAM (ostream1));
     784    data1_size = g_memory_output_stream_get_data_size (
     785      G_MEMORY_OUTPUT_STREAM (ostream1));
     786    g_object_unref (ostream1);
     787    g_object_unref (istream0);
     788  
     789    istream1 = g_memory_input_stream_new_from_data (data1, data1_size, g_free);
     790    decompressor = G_CONVERTER (g_zlib_decompressor_new (test->format));
     791    cistream1 = g_converter_input_stream_new (istream1, decompressor);
     792  
     793    ostream2 = g_memory_output_stream_new (NULL, 0, g_realloc, g_free);
     794  
     795    g_output_stream_splice (ostream2, cistream1, 0, NULL, &error);
     796    g_assert_no_error (error);
     797  
     798    g_assert_cmpmem (data0, DATA_LENGTH * sizeof (guint32),
     799                     g_memory_output_stream_get_data (G_MEMORY_OUTPUT_STREAM (ostream2)),
     800                     g_memory_output_stream_get_data_size (G_MEMORY_OUTPUT_STREAM (ostream2)));
     801    g_object_unref (istream1);
     802    g_converter_reset (decompressor);
     803    g_object_get (decompressor, "format", &fmt, NULL);
     804    g_assert_cmpint (fmt, ==, test->format);
     805    g_object_unref (decompressor);
     806    g_object_unref (cistream1);
     807    g_object_unref (ostream2);
     808    g_free (data0);
     809  }
     810  
     811  typedef struct {
     812    const gchar *path;
     813    const gchar *charset_in;
     814    const gchar *text_in;
     815    const gchar *charset_out;
     816    const gchar *text_out;
     817    gint n_fallbacks;
     818  } CharsetTest;
     819  
     820  static void
     821  test_charset (gconstpointer data)
     822  {
     823    const CharsetTest *test = data;
     824    GInputStream *in, *in2;
     825    GConverter *conv;
     826    gchar *buffer;
     827    gsize count;
     828    gsize bytes_read;
     829    GError *error;
     830    gboolean fallback;
     831  
     832    conv = (GConverter *)g_charset_converter_new (test->charset_out, test->charset_in, NULL);
     833    g_object_get (conv, "use-fallback", &fallback, NULL);
     834    g_assert_false (fallback);
     835  
     836    in = g_memory_input_stream_new_from_data (test->text_in, -1, NULL);
     837    in2 = g_converter_input_stream_new (in, conv);
     838  
     839    count = 2 * strlen (test->text_out);
     840    buffer = g_malloc0 (count);
     841    error = NULL;
     842    g_input_stream_read_all (in2, buffer, count, &bytes_read, NULL, &error);
     843    if (test->n_fallbacks == 0)
     844      {
     845        g_assert_no_error (error);
     846        g_assert_cmpint (bytes_read, ==, strlen (test->text_out));
     847        g_assert_cmpstr (buffer, ==, test->text_out);
     848      }
     849    else
     850      {
     851        g_assert_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_DATA);
     852        g_error_free (error);
     853      }
     854  
     855    g_free (buffer);
     856    g_object_unref (in2);
     857    g_object_unref (in);
     858  
     859    if (test->n_fallbacks == 0)
     860      {
     861         g_object_unref (conv);
     862         return;
     863      }
     864  
     865    g_converter_reset (conv);
     866  
     867    g_assert_false (g_charset_converter_get_use_fallback (G_CHARSET_CONVERTER (conv)));
     868    g_charset_converter_set_use_fallback (G_CHARSET_CONVERTER (conv), TRUE);
     869  
     870    in = g_memory_input_stream_new_from_data (test->text_in, -1, NULL);
     871    in2 = g_converter_input_stream_new (in, conv);
     872  
     873    count = 2 * strlen (test->text_out);
     874    buffer = g_malloc0 (count);
     875    error = NULL;
     876    g_input_stream_read_all (in2, buffer, count, &bytes_read, NULL, &error);
     877    g_assert_no_error (error);
     878    g_assert_cmpstr (buffer, ==, test->text_out);
     879    g_assert_cmpint (bytes_read, ==, strlen (test->text_out));
     880    g_assert_cmpint (test->n_fallbacks, ==, g_charset_converter_get_num_fallbacks (G_CHARSET_CONVERTER (conv)));
     881  
     882    g_free (buffer);
     883    g_object_unref (in2);
     884    g_object_unref (in);
     885  
     886    g_object_unref (conv);
     887  }
     888  
     889  
     890  static void
     891  client_connected (GObject      *source,
     892  		  GAsyncResult *result,
     893  		  gpointer      user_data)
     894  {
     895    GSocketClient *client = G_SOCKET_CLIENT (source);
     896    GSocketConnection **conn = user_data;
     897    GError *error = NULL;
     898  
     899    *conn = g_socket_client_connect_finish (client, result, &error);
     900    g_assert_no_error (error);
     901  }
     902  
     903  static void
     904  server_connected (GObject      *source,
     905  		  GAsyncResult *result,
     906  		  gpointer      user_data)
     907  {
     908    GSocketListener *listener = G_SOCKET_LISTENER (source);
     909    GSocketConnection **conn = user_data;
     910    GError *error = NULL;
     911  
     912    *conn = g_socket_listener_accept_finish (listener, result, NULL, &error);
     913    g_assert_no_error (error);
     914  }
     915  
     916  static void
     917  make_socketpair (GIOStream **left,
     918  		 GIOStream **right)
     919  {
     920    GInetAddress *iaddr;
     921    GSocketAddress *saddr, *effective_address;
     922    GSocketListener *listener;
     923    GSocketClient *client;
     924    GError *error = NULL;
     925    GSocketConnection *client_conn = NULL, *server_conn = NULL;
     926  
     927    iaddr = g_inet_address_new_loopback (G_SOCKET_FAMILY_IPV4);
     928    saddr = g_inet_socket_address_new (iaddr, 0);
     929    g_object_unref (iaddr);
     930  
     931    listener = g_socket_listener_new ();
     932    g_socket_listener_add_address (listener, saddr,
     933  				 G_SOCKET_TYPE_STREAM,
     934  				 G_SOCKET_PROTOCOL_TCP,
     935  				 NULL,
     936  				 &effective_address,
     937  				 &error);
     938    g_assert_no_error (error);
     939    g_object_unref (saddr);
     940  
     941    client = g_socket_client_new ();
     942  
     943    g_socket_client_connect_async (client,
     944  				 G_SOCKET_CONNECTABLE (effective_address),
     945  				 NULL, client_connected, &client_conn);
     946    g_socket_listener_accept_async (listener, NULL,
     947  				  server_connected, &server_conn);
     948  
     949    while (!client_conn || !server_conn)
     950      g_main_context_iteration (NULL, TRUE);
     951  
     952    g_object_unref (client);
     953    g_object_unref (listener);
     954    g_object_unref (effective_address);
     955  
     956    *left = G_IO_STREAM (client_conn);
     957    *right = G_IO_STREAM (server_conn);
     958  }
     959  
     960  static void
     961  test_converter_pollable (void)
     962  {
     963    GIOStream *left, *right;
     964    guint8 *converted, *inptr;
     965    guint8 *expanded, *outptr, *expanded_end;
     966    gsize n_read, expanded_size;
     967    gsize total_read;
     968    gssize res;
     969    gboolean is_readable;
     970    GConverterResult cres;
     971    GInputStream *cstream;
     972    GPollableInputStream *pollable_in;
     973    GOutputStream *socket_out, *mem_out, *cstream_out;
     974    GPollableOutputStream *pollable_out;
     975    GConverter *expander, *compressor;
     976    GError *error;
     977    gsize i;
     978  
     979    expander = g_expander_converter_new ();
     980    expanded = g_malloc (100*1000); /* Large enough */
     981    cres = g_converter_convert (expander,
     982  			      unexpanded_data, sizeof(unexpanded_data),
     983  			      expanded, 100*1000,
     984  			      G_CONVERTER_INPUT_AT_END,
     985  			      &n_read, &expanded_size, NULL);
     986    g_assert_cmpint (cres, ==, G_CONVERTER_FINISHED);
     987    g_assert_cmpuint (n_read, ==, 11);
     988    g_assert_cmpuint (expanded_size, ==, 41030);
     989    expanded_end = expanded + expanded_size;
     990  
     991    make_socketpair (&left, &right);
     992  
     993    compressor = g_compressor_converter_new ();
     994  
     995    converted = g_malloc (100*1000); /* Large enough */
     996  
     997    cstream = g_converter_input_stream_new (g_io_stream_get_input_stream (left),
     998  					  compressor);
     999    pollable_in = G_POLLABLE_INPUT_STREAM (cstream);
    1000    g_assert_true (g_pollable_input_stream_can_poll (pollable_in));
    1001  
    1002    socket_out = g_io_stream_get_output_stream (right);
    1003  
    1004    total_read = 0;
    1005    outptr = expanded;
    1006    inptr = converted;
    1007    while (TRUE)
    1008      {
    1009        error = NULL;
    1010  
    1011        if (outptr < expanded_end)
    1012  	{
    1013  	   res = g_output_stream_write (socket_out,
    1014  				       outptr,
    1015  				       MIN (1000, (expanded_end - outptr)),
    1016  				       NULL, &error);
    1017  	  g_assert_cmpint (res, >, 0);
    1018  	  outptr += res;
    1019  	}
    1020        else if (socket_out)
    1021  	{
    1022  	  g_output_stream_close (socket_out, NULL, NULL);
    1023  	  g_object_unref (right);
    1024  	  socket_out = NULL;
    1025  	}
    1026  
    1027        /* Wait a few ticks to check for the pipe to propagate the
    1028         * write. We can’t wait on a GSource as that might affect the stream under
    1029         * test, so just poll. */
    1030        while (!g_pollable_input_stream_is_readable (pollable_in))
    1031          g_usleep (80L);
    1032  
    1033        is_readable = g_pollable_input_stream_is_readable (pollable_in);
    1034        res = g_pollable_input_stream_read_nonblocking (pollable_in,
    1035  						      inptr, 1,
    1036  						      NULL, &error);
    1037  
    1038        /* is_readable can be a false positive, but not a false negative */
    1039        if (!is_readable)
    1040  	g_assert_cmpint (res, ==, -1);
    1041  
    1042        /* Even after closing the write end, we can get WOULD_BLOCK (particularly
    1043         * on FreeBSD), so we can’t make any assertions based on `!socket_out`.
    1044         * This is because the FIN packets may still be in the out buffer of one
    1045         * half of the socket pair, while the in buffer of the other half has some
    1046         * data, but not enough for a full block for the converter to consume. */
    1047  
    1048        if (res == -1)
    1049  	{
    1050  	  g_assert_error (error, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK);
    1051  	  g_error_free (error);
    1052  
    1053  	  continue;
    1054  	}
    1055  
    1056        if (res == 0)
    1057  	break;
    1058        inptr += res;
    1059        total_read += res;
    1060      }
    1061  
    1062    /* "n_read - 1" because last 2 zeros are combined */
    1063    g_assert_cmpmem (unexpanded_data, n_read - 1, converted, total_read);
    1064  
    1065    g_object_unref (cstream);
    1066    g_object_unref (left);
    1067  
    1068    g_converter_reset (compressor);
    1069  
    1070    /* This doesn't actually test the behavior on
    1071     * G_IO_ERROR_WOULD_BLOCK; to do that we'd need to implement a
    1072     * custom GOutputStream that we could control blocking on.
    1073     */
    1074  
    1075    mem_out = g_memory_output_stream_new (NULL, 0, g_realloc, g_free);
    1076    cstream_out = g_converter_output_stream_new (mem_out, compressor);
    1077    g_object_unref (mem_out);
    1078    pollable_out = G_POLLABLE_OUTPUT_STREAM (cstream_out);
    1079    g_assert_true (g_pollable_output_stream_can_poll (pollable_out));
    1080    g_assert_true (g_pollable_output_stream_is_writable (pollable_out));
    1081  
    1082    for (i = 0; i < expanded_size; i++)
    1083      {
    1084        error = NULL;
    1085        res = g_pollable_output_stream_write_nonblocking (pollable_out,
    1086  							expanded + i, 1,
    1087  							NULL, &error);
    1088        g_assert_cmpint (res, !=, -1);
    1089        if (res == 0)
    1090  	{
    1091  	  g_assert_cmpuint (i, ==, expanded_size -1);
    1092  	  break;
    1093  	}
    1094        g_assert_cmpint (res, ==, 1);
    1095      }
    1096  
    1097    g_output_stream_close (cstream_out, NULL, NULL);
    1098  
    1099    /* "n_read - 1" because last 2 zeros are combined */
    1100    g_assert_cmpmem (g_memory_output_stream_get_data (G_MEMORY_OUTPUT_STREAM (mem_out)),
    1101                     g_memory_output_stream_get_data_size (G_MEMORY_OUTPUT_STREAM (mem_out)),
    1102                     unexpanded_data,
    1103                     n_read - 1);
    1104  
    1105    g_object_unref (cstream_out);
    1106  
    1107    g_free (expanded);
    1108    g_free (converted);
    1109    g_object_unref (expander);
    1110    g_object_unref (compressor);
    1111  }
    1112  
    1113  static void
    1114  test_truncation (gconstpointer data)
    1115  {
    1116    const CompressorTest *test = data;
    1117    GError *error = NULL;
    1118    guint32 *data0, *data1;
    1119    gsize data1_size;
    1120    gint i;
    1121    GInputStream *istream0, *istream1, *cistream1;
    1122    GOutputStream *ostream1, *ostream2, *costream1;
    1123    GConverter *compressor, *decompressor;
    1124  
    1125    data0 = g_malloc (DATA_LENGTH * sizeof (guint32));
    1126    for (i = 0; i < DATA_LENGTH; i++)
    1127      data0[i] = g_random_int ();
    1128  
    1129    istream0 = g_memory_input_stream_new_from_data (data0,
    1130      DATA_LENGTH * sizeof (guint32), NULL);
    1131  
    1132    ostream1 = g_memory_output_stream_new (NULL, 0, g_realloc, g_free);
    1133    compressor = G_CONVERTER (g_zlib_compressor_new (test->format, -1));
    1134    costream1 = g_converter_output_stream_new (ostream1, compressor);
    1135    g_assert_true (g_converter_output_stream_get_converter (G_CONVERTER_OUTPUT_STREAM (costream1)) == compressor);
    1136  
    1137    g_output_stream_splice (costream1, istream0, 0, NULL, &error);
    1138    g_assert_no_error (error);
    1139  
    1140    g_object_unref (costream1);
    1141    g_object_unref (compressor);
    1142  
    1143    data1 = g_memory_output_stream_steal_data (G_MEMORY_OUTPUT_STREAM (ostream1));
    1144    data1_size = g_memory_output_stream_get_data_size (
    1145      G_MEMORY_OUTPUT_STREAM (ostream1));
    1146    g_object_unref (ostream1);
    1147    g_object_unref (istream0);
    1148  
    1149    /* truncate */
    1150    data1_size /= 2;
    1151  
    1152    istream1 = g_memory_input_stream_new_from_data (data1, data1_size, g_free);
    1153    decompressor = G_CONVERTER (g_zlib_decompressor_new (test->format));
    1154    cistream1 = g_converter_input_stream_new (istream1, decompressor);
    1155  
    1156    ostream2 = g_memory_output_stream_new (NULL, 0, g_realloc, g_free);
    1157  
    1158    g_output_stream_splice (ostream2, cistream1, 0, NULL, &error);
    1159    g_assert_error (error, G_IO_ERROR, G_IO_ERROR_PARTIAL_INPUT);
    1160    g_error_free (error);
    1161  
    1162    g_object_unref (istream1);
    1163    g_object_unref (decompressor);
    1164    g_object_unref (cistream1);
    1165    g_object_unref (ostream2);
    1166    g_free (data0);
    1167  }
    1168  
    1169  static void
    1170  test_converter_basics (void)
    1171  {
    1172    GConverter *converter;
    1173    GError *error = NULL;
    1174    gchar *to;
    1175    gchar *from;
    1176  
    1177    converter = (GConverter *)g_charset_converter_new ("utf-8", "latin1", &error);
    1178    g_assert_no_error (error);
    1179    g_object_get (converter,
    1180                  "to-charset", &to,
    1181                  "from-charset", &from,
    1182                  NULL);
    1183  
    1184    g_assert_cmpstr (to, ==, "utf-8");
    1185    g_assert_cmpstr (from, ==, "latin1");
    1186  
    1187    g_free (to);
    1188    g_free (from);
    1189    g_object_unref (converter);
    1190  }
    1191  
    1192  int
    1193  main (int   argc,
    1194        char *argv[])
    1195  {
    1196    CompressorTest compressor_tests[] = {
    1197      { "/converter-output-stream/roundtrip/zlib-0", G_ZLIB_COMPRESSOR_FORMAT_ZLIB, 0 },
    1198      { "/converter-output-stream/roundtrip/zlib-9", G_ZLIB_COMPRESSOR_FORMAT_ZLIB, 9 },
    1199      { "/converter-output-stream/roundtrip/gzip-0", G_ZLIB_COMPRESSOR_FORMAT_GZIP, 0 },
    1200      { "/converter-output-stream/roundtrip/gzip-9", G_ZLIB_COMPRESSOR_FORMAT_GZIP, 9 },
    1201      { "/converter-output-stream/roundtrip/raw-0", G_ZLIB_COMPRESSOR_FORMAT_RAW, 0 },
    1202      { "/converter-output-stream/roundtrip/raw-9", G_ZLIB_COMPRESSOR_FORMAT_RAW, 9 },
    1203    };
    1204    CompressorTest truncation_tests[] = {
    1205      { "/converter-input-stream/truncation/zlib", G_ZLIB_COMPRESSOR_FORMAT_ZLIB, 0 },
    1206      { "/converter-input-stream/truncation/gzip", G_ZLIB_COMPRESSOR_FORMAT_GZIP, 0 },
    1207      { "/converter-input-stream/truncation/raw", G_ZLIB_COMPRESSOR_FORMAT_RAW, 0 },
    1208    };
    1209    CharsetTest charset_tests[] = {
    1210      { "/converter-input-stream/charset/utf8->latin1", "UTF-8", "\303\205rr Sant\303\251", "ISO-8859-1", "\305rr Sant\351", 0 },
    1211      { "/converter-input-stream/charset/latin1->utf8", "ISO-8859-1", "\305rr Sant\351", "UTF-8", "\303\205rr Sant\303\251", 0 },
    1212      { "/converter-input-stream/charset/fallbacks", "UTF-8", "Some characters just don't fit into latin1: πא", "ISO-8859-1", "Some characters just don't fit into latin1: \\CF\\80\\D7\\90", 4 },
    1213    };
    1214  
    1215    gsize i;
    1216  
    1217    g_test_init (&argc, &argv, NULL);
    1218  
    1219    g_test_add_func ("/converter/basics", test_converter_basics);
    1220    g_test_add_func ("/converter-input-stream/expander", test_expander);
    1221    g_test_add_func ("/converter-input-stream/compressor", test_compressor);
    1222  
    1223    for (i = 0; i < G_N_ELEMENTS (compressor_tests); i++)
    1224      g_test_add_data_func (compressor_tests[i].path, &compressor_tests[i], test_roundtrip);
    1225  
    1226    for (i = 0; i < G_N_ELEMENTS (truncation_tests); i++)
    1227      g_test_add_data_func (truncation_tests[i].path, &truncation_tests[i], test_truncation);
    1228  
    1229    for (i = 0; i < G_N_ELEMENTS (charset_tests); i++)
    1230      g_test_add_data_func (charset_tests[i].path, &charset_tests[i], test_charset);
    1231  
    1232    g_test_add_func ("/converter-stream/pollable", test_converter_pollable);
    1233    g_test_add_func ("/converter-stream/leftover", test_converter_leftover);
    1234  
    1235    return g_test_run();
    1236  }