1 /* GLib testing framework examples and tests
2 * Copyright (C) 2009 Red Hat, Inc.
3 * Authors: Alexander Larsson <alexl@redhat.com>
5 * This work is provided "as is"; redistribution and modification
6 * in whole or in part, in any medium, physical or electronic is
7 * permitted without restriction.
9 * This work is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 * In no event shall the authors or contributors be liable for any
14 * direct, indirect, incidental, special, exemplary, or consequential
15 * damages (including, but not limited to, procurement of substitute
16 * goods or services; loss of use, data, or profits; or business
17 * interruption) however caused and on any theory of liability, whether
18 * in contract, strict liability, or tort (including negligence or
19 * otherwise) arising in any way out of the use of this software, even
20 * if advised of the possibility of such damage.
23 #include <glib/glib.h>
28 #define G_TYPE_EXPANDER_CONVERTER (g_expander_converter_get_type ())
29 #define G_EXPANDER_CONVERTER(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), G_TYPE_EXPANDER_CONVERTER, GExpanderConverter))
30 #define G_EXPANDER_CONVERTER_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), G_TYPE_EXPANDER_CONVERTER, GExpanderConverterClass))
31 #define G_IS_EXPANDER_CONVERTER(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_TYPE_EXPANDER_CONVERTER))
32 #define G_IS_EXPANDER_CONVERTER_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), G_TYPE_EXPANDER_CONVERTER))
33 #define G_EXPANDER_CONVERTER_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), G_TYPE_EXPANDER_CONVERTER, GExpanderConverterClass))
35 typedef struct _GExpanderConverter GExpanderConverter
;
36 typedef struct _GExpanderConverterClass GExpanderConverterClass
;
38 struct _GExpanderConverterClass
40 GObjectClass parent_class
;
43 GType
g_expander_converter_get_type (void) G_GNUC_CONST
;
44 GConverter
*g_expander_converter_new (void);
48 static void g_expander_converter_iface_init (GConverterIface
*iface
);
50 struct _GExpanderConverter
52 GObject parent_instance
;
55 G_DEFINE_TYPE_WITH_CODE (GExpanderConverter
, g_expander_converter
, G_TYPE_OBJECT
,
56 G_IMPLEMENT_INTERFACE (G_TYPE_CONVERTER
,
57 g_expander_converter_iface_init
))
60 g_expander_converter_class_init (GExpanderConverterClass
*klass
)
65 g_expander_converter_init (GExpanderConverter
*local
)
70 g_expander_converter_new (void)
74 conv
= g_object_new (G_TYPE_EXPANDER_CONVERTER
, NULL
);
80 g_expander_converter_reset (GConverter
*converter
)
84 static GConverterResult
85 g_expander_converter_convert (GConverter
*converter
,
90 GConverterFlags flags
,
95 const guint8
*in
, *in_end
;
102 in_end
= in
+ inbuf_size
;
111 block_size
= v
* 1000;
113 if (outbuf_size
< block_size
)
116 return G_CONVERTER_CONVERTED
;
118 g_set_error_literal (error
, G_IO_ERROR
,
121 return G_CONVERTER_ERROR
;
126 *bytes_written
+= block_size
;
127 outbuf_size
-= block_size
;
128 for (i
= 0; i
< block_size
; i
++)
132 if (in
== in_end
&& (flags
& G_CONVERTER_INPUT_AT_END
))
133 return G_CONVERTER_FINISHED
;
134 return G_CONVERTER_CONVERTED
;
138 g_expander_converter_iface_init (GConverterIface
*iface
)
140 iface
->convert
= g_expander_converter_convert
;
141 iface
->reset
= g_expander_converter_reset
;
144 #define G_TYPE_COMPRESSOR_CONVERTER (g_compressor_converter_get_type ())
145 #define G_COMPRESSOR_CONVERTER(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), G_TYPE_COMPRESSOR_CONVERTER, GCompressorConverter))
146 #define G_COMPRESSOR_CONVERTER_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), G_TYPE_COMPRESSOR_CONVERTER, GCompressorConverterClass))
147 #define G_IS_COMPRESSOR_CONVERTER(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_TYPE_COMPRESSOR_CONVERTER))
148 #define G_IS_COMPRESSOR_CONVERTER_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), G_TYPE_COMPRESSOR_CONVERTER))
149 #define G_COMPRESSOR_CONVERTER_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), G_TYPE_COMPRESSOR_CONVERTER, GCompressorConverterClass))
151 typedef struct _GCompressorConverter GCompressorConverter
;
152 typedef struct _GCompressorConverterClass GCompressorConverterClass
;
154 struct _GCompressorConverterClass
156 GObjectClass parent_class
;
159 GType
g_compressor_converter_get_type (void) G_GNUC_CONST
;
160 GConverter
*g_compressor_converter_new (void);
164 static void g_compressor_converter_iface_init (GConverterIface
*iface
);
166 struct _GCompressorConverter
168 GObject parent_instance
;
171 G_DEFINE_TYPE_WITH_CODE (GCompressorConverter
, g_compressor_converter
, G_TYPE_OBJECT
,
172 G_IMPLEMENT_INTERFACE (G_TYPE_CONVERTER
,
173 g_compressor_converter_iface_init
))
176 g_compressor_converter_class_init (GCompressorConverterClass
*klass
)
181 g_compressor_converter_init (GCompressorConverter
*local
)
186 g_compressor_converter_new (void)
190 conv
= g_object_new (G_TYPE_COMPRESSOR_CONVERTER
, NULL
);
196 g_compressor_converter_reset (GConverter
*converter
)
200 static GConverterResult
201 g_compressor_converter_convert (GConverter
*converter
,
206 GConverterFlags flags
,
208 gsize
*bytes_written
,
211 const guint8
*in
, *in_end
;
218 in_end
= in
+ inbuf_size
;
227 while (in
+block_size
< in_end
&& *(in
+block_size
) == 0)
231 block_size
= v
* 1000;
233 /* Not enough data */
234 if (in_end
- in
< block_size
)
238 g_set_error_literal (error
, G_IO_ERROR
,
239 G_IO_ERROR_PARTIAL_INPUT
,
241 return G_CONVERTER_ERROR
;
244 for (i
= 0; i
< block_size
; i
++)
250 g_set_error_literal (error
, G_IO_ERROR
,
251 G_IO_ERROR_INVALID_DATA
,
253 return G_CONVERTER_ERROR
;
257 if (v
== 0 && in_end
- in
== block_size
&& (flags
& G_CONVERTER_INPUT_AT_END
) == 0)
261 g_set_error_literal (error
, G_IO_ERROR
,
262 G_IO_ERROR_PARTIAL_INPUT
,
264 return G_CONVERTER_ERROR
;
269 *bytes_read
+= block_size
;
273 if (in
== in_end
&& (flags
& G_CONVERTER_INPUT_AT_END
))
274 return G_CONVERTER_FINISHED
;
275 return G_CONVERTER_CONVERTED
;
279 g_compressor_converter_iface_init (GConverterIface
*iface
)
281 iface
->convert
= g_compressor_converter_convert
;
282 iface
->reset
= g_compressor_converter_reset
;
285 guint8 unexpanded_data
[] = { 0,1,3,4,5,6,7,3,12,0,0};
290 guint8
*converted1
, *converted2
, *ptr
;
291 gsize n_read
, n_written
;
294 GConverterResult cres
;
295 GInputStream
*mem
, *cstream
;
296 GOutputStream
*mem_out
, *cstream_out
;
297 GConverter
*expander
;
298 GConverter
*converter
;
302 expander
= g_expander_converter_new ();
304 converted1
= g_malloc (100*1000); /* Large enough */
305 converted2
= g_malloc (100*1000); /* Large enough */
307 cres
= g_converter_convert (expander
,
308 unexpanded_data
, sizeof(unexpanded_data
),
309 converted1
, 100*1000,
310 G_CONVERTER_INPUT_AT_END
,
311 &n_read
, &n_written
, NULL
);
313 g_assert (cres
== G_CONVERTER_FINISHED
);
314 g_assert (n_read
== 11);
315 g_assert (n_written
== 41030);
317 g_converter_reset (expander
);
319 mem
= g_memory_input_stream_new_from_data (unexpanded_data
,
320 sizeof (unexpanded_data
),
322 cstream
= g_converter_input_stream_new (mem
, expander
);
323 g_assert (g_converter_input_stream_get_converter (G_CONVERTER_INPUT_STREAM (cstream
)) == expander
);
324 g_object_get (cstream
, "converter", &converter
, NULL
);
325 g_assert (converter
== expander
);
326 g_object_unref (converter
);
327 g_object_unref (mem
);
334 res
= g_input_stream_read (cstream
,
337 g_assert (res
!= -1);
344 g_assert_cmpmem (converted1
, n_written
, converted2
, total_read
);
346 g_converter_reset (expander
);
348 mem_out
= g_memory_output_stream_new (NULL
, 0, g_realloc
, g_free
);
349 cstream_out
= g_converter_output_stream_new (mem_out
, expander
);
350 g_assert (g_converter_output_stream_get_converter (G_CONVERTER_OUTPUT_STREAM (cstream_out
)) == expander
);
351 g_object_get (cstream_out
, "converter", &converter
, NULL
);
352 g_assert (converter
== expander
);
353 g_object_unref (converter
);
354 g_object_unref (mem_out
);
356 for (i
= 0; i
< sizeof(unexpanded_data
); i
++)
359 res
= g_output_stream_write (cstream_out
,
360 unexpanded_data
+ i
, 1,
362 g_assert (res
!= -1);
365 g_assert (i
== sizeof(unexpanded_data
) -1);
371 g_output_stream_close (cstream_out
, NULL
, NULL
);
373 g_assert_cmpmem (g_memory_output_stream_get_data (G_MEMORY_OUTPUT_STREAM (mem_out
)),
374 g_memory_output_stream_get_data_size (G_MEMORY_OUTPUT_STREAM (mem_out
)),
375 converted1
, n_written
);
379 g_object_unref (cstream
);
380 g_object_unref (cstream_out
);
381 g_object_unref (expander
);
385 test_compressor (void)
387 guint8
*converted
, *expanded
, *ptr
;
388 gsize n_read
, expanded_size
;
391 GConverterResult cres
;
392 GInputStream
*mem
, *cstream
;
393 GOutputStream
*mem_out
, *cstream_out
;
394 GConverter
*expander
, *compressor
;
398 expander
= g_expander_converter_new ();
399 expanded
= g_malloc (100*1000); /* Large enough */
400 cres
= g_converter_convert (expander
,
401 unexpanded_data
, sizeof(unexpanded_data
),
403 G_CONVERTER_INPUT_AT_END
,
404 &n_read
, &expanded_size
, NULL
);
405 g_assert (cres
== G_CONVERTER_FINISHED
);
406 g_assert (n_read
== 11);
407 g_assert (expanded_size
== 41030);
409 compressor
= g_compressor_converter_new ();
411 converted
= g_malloc (100*1000); /* Large enough */
413 mem
= g_memory_input_stream_new_from_data (expanded
,
416 cstream
= g_converter_input_stream_new (mem
, compressor
);
417 g_object_unref (mem
);
424 res
= g_input_stream_read (cstream
,
427 g_assert (res
!= -1);
434 /* "n_read - 1" because last 2 zeros are combined */
435 g_assert_cmpmem (unexpanded_data
, n_read
- 1, converted
, total_read
);
437 g_object_unref (cstream
);
439 g_converter_reset (compressor
);
441 mem_out
= g_memory_output_stream_new (NULL
, 0, g_realloc
, g_free
);
442 cstream_out
= g_converter_output_stream_new (mem_out
, compressor
);
443 g_object_unref (mem_out
);
445 for (i
= 0; i
< expanded_size
; i
++)
448 res
= g_output_stream_write (cstream_out
,
451 g_assert (res
!= -1);
454 g_assert (i
== expanded_size
-1);
460 g_output_stream_close (cstream_out
, NULL
, NULL
);
462 /* "n_read - 1" because last 2 zeros are combined */
463 g_assert_cmpmem (g_memory_output_stream_get_data (G_MEMORY_OUTPUT_STREAM (mem_out
)),
464 g_memory_output_stream_get_data_size (G_MEMORY_OUTPUT_STREAM (mem_out
)),
468 g_object_unref (cstream_out
);
470 g_converter_reset (compressor
);
472 memset (expanded
, 5, 5*1000*2);
474 mem
= g_memory_input_stream_new_from_data (expanded
,
477 cstream
= g_converter_input_stream_new (mem
, compressor
);
478 g_object_unref (mem
);
485 res
= g_input_stream_read (cstream
,
488 g_assert (res
!= -1);
495 g_assert (total_read
== 1);
496 g_assert (*converted
== 5);
498 g_object_unref (cstream
);
500 mem
= g_memory_input_stream_new_from_data (expanded
,
503 cstream
= g_converter_input_stream_new (mem
, compressor
);
504 g_object_unref (mem
);
511 res
= g_input_stream_read (cstream
,
514 g_assert (res
!= -1);
521 g_assert (total_read
== 2);
522 g_assert (converted
[0] == 5);
523 g_assert (converted
[1] == 5);
525 g_object_unref (cstream
);
527 g_converter_reset (compressor
);
529 mem
= g_memory_input_stream_new_from_data (expanded
,
532 cstream
= g_converter_input_stream_new (mem
, compressor
);
533 g_object_unref (mem
);
540 res
= g_input_stream_read (cstream
,
545 g_assert_error (error
, G_IO_ERROR
, G_IO_ERROR_PARTIAL_INPUT
);
546 g_error_free (error
);
555 g_assert (total_read
== 1);
556 g_assert (converted
[0] == 5);
558 g_object_unref (cstream
);
562 g_object_unref (expander
);
563 g_object_unref (compressor
);
566 #define LEFTOVER_SHORT_READ_SIZE 512
568 #define G_TYPE_LEFTOVER_CONVERTER (g_leftover_converter_get_type ())
569 #define G_LEFTOVER_CONVERTER(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), G_TYPE_LEFTOVER_CONVERTER, GLeftoverConverter))
570 #define G_LEFTOVER_CONVERTER_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), G_TYPE_LEFTOVER_CONVERTER, GLeftoverConverterClass))
571 #define G_IS_LEFTOVER_CONVERTER(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_TYPE_LEFTOVER_CONVERTER))
572 #define G_IS_LEFTOVER_CONVERTER_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), G_TYPE_LEFTOVER_CONVERTER))
573 #define G_LEFTOVER_CONVERTER_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), G_TYPE_LEFTOVER_CONVERTER, GLeftoverConverterClass))
575 typedef struct _GLeftoverConverter GLeftoverConverter
;
576 typedef struct _GLeftoverConverterClass GLeftoverConverterClass
;
578 struct _GLeftoverConverterClass
580 GObjectClass parent_class
;
583 GType
g_leftover_converter_get_type (void) G_GNUC_CONST
;
584 GConverter
*g_leftover_converter_new (void);
588 static void g_leftover_converter_iface_init (GConverterIface
*iface
);
590 struct _GLeftoverConverter
592 GObject parent_instance
;
595 G_DEFINE_TYPE_WITH_CODE (GLeftoverConverter
, g_leftover_converter
, G_TYPE_OBJECT
,
596 G_IMPLEMENT_INTERFACE (G_TYPE_CONVERTER
,
597 g_leftover_converter_iface_init
))
600 g_leftover_converter_class_init (GLeftoverConverterClass
*klass
)
605 g_leftover_converter_init (GLeftoverConverter
*local
)
610 g_leftover_converter_new (void)
614 conv
= g_object_new (G_TYPE_LEFTOVER_CONVERTER
, NULL
);
620 g_leftover_converter_reset (GConverter
*converter
)
624 static GConverterResult
625 g_leftover_converter_convert (GConverter
*converter
,
630 GConverterFlags flags
,
632 gsize
*bytes_written
,
635 if (outbuf_size
== LEFTOVER_SHORT_READ_SIZE
)
637 g_set_error_literal (error
,
639 G_IO_ERROR_PARTIAL_INPUT
,
641 return G_CONVERTER_ERROR
;
644 if (inbuf_size
< 100)
645 *bytes_read
= *bytes_written
= MIN (inbuf_size
, outbuf_size
);
647 *bytes_read
= *bytes_written
= MIN (inbuf_size
- 10, outbuf_size
);
648 memcpy (outbuf
, inbuf
, *bytes_written
);
650 if (*bytes_read
== inbuf_size
&& (flags
& G_CONVERTER_INPUT_AT_END
))
651 return G_CONVERTER_FINISHED
;
652 return G_CONVERTER_CONVERTED
;
656 g_leftover_converter_iface_init (GConverterIface
*iface
)
658 iface
->convert
= g_leftover_converter_convert
;
659 iface
->reset
= g_leftover_converter_reset
;
662 #define LEFTOVER_BUFSIZE 8192
663 #define INTERNAL_BUFSIZE 4096
666 test_converter_leftover (void)
668 gchar
*orig
, *converted
;
672 GInputStream
*mem
, *cstream
;
673 GConverter
*converter
;
677 converter
= g_leftover_converter_new ();
679 orig
= g_malloc (LEFTOVER_BUFSIZE
);
680 converted
= g_malloc (LEFTOVER_BUFSIZE
);
681 for (i
= 0; i
< LEFTOVER_BUFSIZE
; i
++)
682 orig
[i
] = i
% 64 + 32;
684 mem
= g_memory_input_stream_new_from_data (orig
, LEFTOVER_BUFSIZE
, NULL
);
685 cstream
= g_converter_input_stream_new (mem
, G_CONVERTER (converter
));
686 g_object_unref (mem
);
691 res
= g_input_stream_read (cstream
,
692 converted
, LEFTOVER_SHORT_READ_SIZE
,
694 g_assert_cmpint (res
, ==, LEFTOVER_SHORT_READ_SIZE
);
697 offset
= g_seekable_tell (G_SEEKABLE (mem
));
698 g_assert_cmpint (offset
, >, LEFTOVER_SHORT_READ_SIZE
);
699 g_assert_cmpint (offset
, <, LEFTOVER_BUFSIZE
);
701 /* At this point, @cstream has both a non-empty input_buffer
702 * and a non-empty converted_buffer, which is the case
709 res
= g_input_stream_read (cstream
,
710 converted
+ total_read
,
711 LEFTOVER_BUFSIZE
- total_read
,
719 g_assert_cmpmem (orig
, LEFTOVER_BUFSIZE
, converted
, total_read
);
721 g_object_unref (cstream
);
724 g_object_unref (converter
);
727 #define DATA_LENGTH 1000000
731 GZlibCompressorFormat format
;
736 test_roundtrip (gconstpointer data
)
738 const CompressorTest
*test
= data
;
739 GError
*error
= NULL
;
740 guint32
*data0
, *data1
;
743 GInputStream
*istream0
, *istream1
, *cistream1
;
744 GOutputStream
*ostream1
, *ostream2
, *costream1
;
745 GConverter
*compressor
, *decompressor
;
746 GZlibCompressorFormat fmt
;
751 g_test_bug ("619945");
753 data0
= g_malloc (DATA_LENGTH
* sizeof (guint32
));
754 for (i
= 0; i
< DATA_LENGTH
; i
++)
755 data0
[i
] = g_random_int ();
757 istream0
= g_memory_input_stream_new_from_data (data0
,
758 DATA_LENGTH
* sizeof (guint32
), NULL
);
760 ostream1
= g_memory_output_stream_new (NULL
, 0, g_realloc
, g_free
);
761 compressor
= G_CONVERTER (g_zlib_compressor_new (test
->format
, test
->level
));
762 info
= g_file_info_new ();
763 g_file_info_set_name (info
, "foo");
764 g_object_set (compressor
, "file-info", info
, NULL
);
765 info2
= g_zlib_compressor_get_file_info (G_ZLIB_COMPRESSOR (compressor
));
766 g_assert (info
== info2
);
767 g_object_unref (info
);
768 costream1
= g_converter_output_stream_new (ostream1
, compressor
);
769 g_assert (g_converter_output_stream_get_converter (G_CONVERTER_OUTPUT_STREAM (costream1
)) == compressor
);
771 g_output_stream_splice (costream1
, istream0
, 0, NULL
, &error
);
772 g_assert_no_error (error
);
774 g_object_unref (costream1
);
776 g_converter_reset (compressor
);
777 g_object_get (compressor
, "format", &fmt
, "level", &lvl
, NULL
);
778 g_assert_cmpint (fmt
, ==, test
->format
);
779 g_assert_cmpint (lvl
, ==, test
->level
);
780 g_object_unref (compressor
);
781 data1
= g_memory_output_stream_steal_data (G_MEMORY_OUTPUT_STREAM (ostream1
));
782 data1_size
= g_memory_output_stream_get_data_size (
783 G_MEMORY_OUTPUT_STREAM (ostream1
));
784 g_object_unref (ostream1
);
785 g_object_unref (istream0
);
787 istream1
= g_memory_input_stream_new_from_data (data1
, data1_size
, g_free
);
788 decompressor
= G_CONVERTER (g_zlib_decompressor_new (test
->format
));
789 cistream1
= g_converter_input_stream_new (istream1
, decompressor
);
791 ostream2
= g_memory_output_stream_new (NULL
, 0, g_realloc
, g_free
);
793 g_output_stream_splice (ostream2
, cistream1
, 0, NULL
, &error
);
794 g_assert_no_error (error
);
796 g_assert_cmpmem (data0
, DATA_LENGTH
* sizeof (guint32
),
797 g_memory_output_stream_get_data (G_MEMORY_OUTPUT_STREAM (ostream2
)),
798 g_memory_output_stream_get_data_size (G_MEMORY_OUTPUT_STREAM (ostream2
)));
799 g_object_unref (istream1
);
800 g_converter_reset (decompressor
);
801 g_object_get (decompressor
, "format", &fmt
, NULL
);
802 g_assert_cmpint (fmt
, ==, test
->format
);
803 g_object_unref (decompressor
);
804 g_object_unref (cistream1
);
805 g_object_unref (ostream2
);
811 const gchar
*charset_in
;
812 const gchar
*text_in
;
813 const gchar
*charset_out
;
814 const gchar
*text_out
;
819 test_charset (gconstpointer data
)
821 const CharsetTest
*test
= data
;
822 GInputStream
*in
, *in2
;
830 conv
= (GConverter
*)g_charset_converter_new (test
->charset_out
, test
->charset_in
, NULL
);
831 g_object_get (conv
, "use-fallback", &fallback
, NULL
);
832 g_assert (!fallback
);
834 in
= g_memory_input_stream_new_from_data (test
->text_in
, -1, NULL
);
835 in2
= g_converter_input_stream_new (in
, conv
);
837 count
= 2 * strlen (test
->text_out
);
838 buffer
= g_malloc0 (count
);
840 g_input_stream_read_all (in2
, buffer
, count
, &bytes_read
, NULL
, &error
);
841 if (test
->n_fallbacks
== 0)
843 g_assert_no_error (error
);
844 g_assert_cmpint (bytes_read
, ==, strlen (test
->text_out
));
845 g_assert_cmpstr (buffer
, ==, test
->text_out
);
849 g_assert_error (error
, G_IO_ERROR
, G_IO_ERROR_INVALID_DATA
);
850 g_error_free (error
);
854 g_object_unref (in2
);
857 if (test
->n_fallbacks
== 0)
859 g_object_unref (conv
);
863 g_converter_reset (conv
);
865 g_assert (!g_charset_converter_get_use_fallback (G_CHARSET_CONVERTER (conv
)));
866 g_charset_converter_set_use_fallback (G_CHARSET_CONVERTER (conv
), TRUE
);
868 in
= g_memory_input_stream_new_from_data (test
->text_in
, -1, NULL
);
869 in2
= g_converter_input_stream_new (in
, conv
);
871 count
= 2 * strlen (test
->text_out
);
872 buffer
= g_malloc0 (count
);
874 g_input_stream_read_all (in2
, buffer
, count
, &bytes_read
, NULL
, &error
);
875 g_assert_no_error (error
);
876 g_assert_cmpstr (buffer
, ==, test
->text_out
);
877 g_assert_cmpint (bytes_read
, ==, strlen (test
->text_out
));
878 g_assert_cmpint (test
->n_fallbacks
, ==, g_charset_converter_get_num_fallbacks (G_CHARSET_CONVERTER (conv
)));
881 g_object_unref (in2
);
884 g_object_unref (conv
);
889 client_connected (GObject
*source
,
890 GAsyncResult
*result
,
893 GSocketClient
*client
= G_SOCKET_CLIENT (source
);
894 GSocketConnection
**conn
= user_data
;
895 GError
*error
= NULL
;
897 *conn
= g_socket_client_connect_finish (client
, result
, &error
);
898 g_assert_no_error (error
);
902 server_connected (GObject
*source
,
903 GAsyncResult
*result
,
906 GSocketListener
*listener
= G_SOCKET_LISTENER (source
);
907 GSocketConnection
**conn
= user_data
;
908 GError
*error
= NULL
;
910 *conn
= g_socket_listener_accept_finish (listener
, result
, NULL
, &error
);
911 g_assert_no_error (error
);
915 make_socketpair (GIOStream
**left
,
919 GSocketAddress
*saddr
, *effective_address
;
920 GSocketListener
*listener
;
921 GSocketClient
*client
;
922 GError
*error
= NULL
;
923 GSocketConnection
*client_conn
= NULL
, *server_conn
= NULL
;
925 iaddr
= g_inet_address_new_loopback (G_SOCKET_FAMILY_IPV4
);
926 saddr
= g_inet_socket_address_new (iaddr
, 0);
927 g_object_unref (iaddr
);
929 listener
= g_socket_listener_new ();
930 g_socket_listener_add_address (listener
, saddr
,
931 G_SOCKET_TYPE_STREAM
,
932 G_SOCKET_PROTOCOL_TCP
,
936 g_assert_no_error (error
);
937 g_object_unref (saddr
);
939 client
= g_socket_client_new ();
941 g_socket_client_connect_async (client
,
942 G_SOCKET_CONNECTABLE (effective_address
),
943 NULL
, client_connected
, &client_conn
);
944 g_socket_listener_accept_async (listener
, NULL
,
945 server_connected
, &server_conn
);
947 while (!client_conn
|| !server_conn
)
948 g_main_context_iteration (NULL
, TRUE
);
950 g_object_unref (client
);
951 g_object_unref (listener
);
952 g_object_unref (effective_address
);
954 *left
= G_IO_STREAM (client_conn
);
955 *right
= G_IO_STREAM (server_conn
);
959 test_converter_pollable (void)
961 GIOStream
*left
, *right
;
962 guint8
*converted
, *inptr
;
963 guint8
*expanded
, *outptr
, *expanded_end
;
964 gsize n_read
, expanded_size
;
967 gboolean is_readable
;
968 GConverterResult cres
;
969 GInputStream
*cstream
;
970 GPollableInputStream
*pollable_in
;
971 GOutputStream
*socket_out
, *mem_out
, *cstream_out
;
972 GPollableOutputStream
*pollable_out
;
973 GConverter
*expander
, *compressor
;
977 expander
= g_expander_converter_new ();
978 expanded
= g_malloc (100*1000); /* Large enough */
979 cres
= g_converter_convert (expander
,
980 unexpanded_data
, sizeof(unexpanded_data
),
982 G_CONVERTER_INPUT_AT_END
,
983 &n_read
, &expanded_size
, NULL
);
984 g_assert (cres
== G_CONVERTER_FINISHED
);
985 g_assert (n_read
== 11);
986 g_assert (expanded_size
== 41030);
987 expanded_end
= expanded
+ expanded_size
;
989 make_socketpair (&left
, &right
);
991 compressor
= g_compressor_converter_new ();
993 converted
= g_malloc (100*1000); /* Large enough */
995 cstream
= g_converter_input_stream_new (g_io_stream_get_input_stream (left
),
997 pollable_in
= G_POLLABLE_INPUT_STREAM (cstream
);
998 g_assert (g_pollable_input_stream_can_poll (pollable_in
));
1000 socket_out
= g_io_stream_get_output_stream (right
);
1009 if (outptr
< expanded_end
)
1011 res
= g_output_stream_write (socket_out
,
1013 MIN (1000, (expanded_end
- outptr
)),
1015 g_assert_cmpint (res
, >, 0);
1018 else if (socket_out
)
1020 g_object_unref (right
);
1024 /* Wait a few ticks to check for the pipe to propagate the
1025 * write. Finesses the race condition in the following test,
1026 * where is_readable fails because the write hasn't propagated,
1027 * but the read then succeeds because it has. */
1030 is_readable
= g_pollable_input_stream_is_readable (pollable_in
);
1031 res
= g_pollable_input_stream_read_nonblocking (pollable_in
,
1035 /* is_readable can be a false positive, but not a false negative */
1037 g_assert_cmpint (res
, ==, -1);
1039 /* After closing the write end, we can't get WOULD_BLOCK any more */
1041 g_assert_cmpint (res
, !=, -1);
1045 g_assert_error (error
, G_IO_ERROR
, G_IO_ERROR_WOULD_BLOCK
);
1046 g_error_free (error
);
1057 /* "n_read - 1" because last 2 zeros are combined */
1058 g_assert_cmpmem (unexpanded_data
, n_read
- 1, converted
, total_read
);
1060 g_object_unref (cstream
);
1061 g_object_unref (left
);
1063 g_converter_reset (compressor
);
1065 /* This doesn't actually test the behavior on
1066 * G_IO_ERROR_WOULD_BLOCK; to do that we'd need to implement a
1067 * custom GOutputStream that we could control blocking on.
1070 mem_out
= g_memory_output_stream_new (NULL
, 0, g_realloc
, g_free
);
1071 cstream_out
= g_converter_output_stream_new (mem_out
, compressor
);
1072 g_object_unref (mem_out
);
1073 pollable_out
= G_POLLABLE_OUTPUT_STREAM (cstream_out
);
1074 g_assert (g_pollable_output_stream_can_poll (pollable_out
));
1075 g_assert (g_pollable_output_stream_is_writable (pollable_out
));
1077 for (i
= 0; i
< expanded_size
; i
++)
1080 res
= g_pollable_output_stream_write_nonblocking (pollable_out
,
1083 g_assert (res
!= -1);
1086 g_assert (i
== expanded_size
-1);
1089 g_assert (res
== 1);
1092 g_output_stream_close (cstream_out
, NULL
, NULL
);
1094 /* "n_read - 1" because last 2 zeros are combined */
1095 g_assert_cmpmem (g_memory_output_stream_get_data (G_MEMORY_OUTPUT_STREAM (mem_out
)),
1096 g_memory_output_stream_get_data_size (G_MEMORY_OUTPUT_STREAM (mem_out
)),
1100 g_object_unref (cstream_out
);
1104 g_object_unref (expander
);
1105 g_object_unref (compressor
);
1109 test_truncation (gconstpointer data
)
1111 const CompressorTest
*test
= data
;
1112 GError
*error
= NULL
;
1113 guint32
*data0
, *data1
;
1116 GInputStream
*istream0
, *istream1
, *cistream1
;
1117 GOutputStream
*ostream1
, *ostream2
, *costream1
;
1118 GConverter
*compressor
, *decompressor
;
1120 data0
= g_malloc (DATA_LENGTH
* sizeof (guint32
));
1121 for (i
= 0; i
< DATA_LENGTH
; i
++)
1122 data0
[i
] = g_random_int ();
1124 istream0
= g_memory_input_stream_new_from_data (data0
,
1125 DATA_LENGTH
* sizeof (guint32
), NULL
);
1127 ostream1
= g_memory_output_stream_new (NULL
, 0, g_realloc
, g_free
);
1128 compressor
= G_CONVERTER (g_zlib_compressor_new (test
->format
, -1));
1129 costream1
= g_converter_output_stream_new (ostream1
, compressor
);
1130 g_assert (g_converter_output_stream_get_converter (G_CONVERTER_OUTPUT_STREAM (costream1
)) == compressor
);
1132 g_output_stream_splice (costream1
, istream0
, 0, NULL
, &error
);
1133 g_assert_no_error (error
);
1135 g_object_unref (costream1
);
1136 g_object_unref (compressor
);
1138 data1
= g_memory_output_stream_steal_data (G_MEMORY_OUTPUT_STREAM (ostream1
));
1139 data1_size
= g_memory_output_stream_get_data_size (
1140 G_MEMORY_OUTPUT_STREAM (ostream1
));
1141 g_object_unref (ostream1
);
1142 g_object_unref (istream0
);
1147 istream1
= g_memory_input_stream_new_from_data (data1
, data1_size
, g_free
);
1148 decompressor
= G_CONVERTER (g_zlib_decompressor_new (test
->format
));
1149 cistream1
= g_converter_input_stream_new (istream1
, decompressor
);
1151 ostream2
= g_memory_output_stream_new (NULL
, 0, g_realloc
, g_free
);
1153 g_output_stream_splice (ostream2
, cistream1
, 0, NULL
, &error
);
1154 g_assert_error (error
, G_IO_ERROR
, G_IO_ERROR_PARTIAL_INPUT
);
1155 g_error_free (error
);
1157 g_object_unref (istream1
);
1158 g_object_unref (decompressor
);
1159 g_object_unref (cistream1
);
1160 g_object_unref (ostream2
);
1165 test_converter_basics (void)
1167 GConverter
*converter
;
1168 GError
*error
= NULL
;
1172 converter
= (GConverter
*)g_charset_converter_new ("utf-8", "latin1", &error
);
1173 g_assert_no_error (error
);
1174 g_object_get (converter
,
1176 "from-charset", &from
,
1179 g_assert_cmpstr (to
, ==, "utf-8");
1180 g_assert_cmpstr (from
, ==, "latin1");
1184 g_object_unref (converter
);
1191 CompressorTest compressor_tests
[] = {
1192 { "/converter-output-stream/roundtrip/zlib-0", G_ZLIB_COMPRESSOR_FORMAT_ZLIB
, 0 },
1193 { "/converter-output-stream/roundtrip/zlib-9", G_ZLIB_COMPRESSOR_FORMAT_ZLIB
, 9 },
1194 { "/converter-output-stream/roundtrip/gzip-0", G_ZLIB_COMPRESSOR_FORMAT_GZIP
, 0 },
1195 { "/converter-output-stream/roundtrip/gzip-9", G_ZLIB_COMPRESSOR_FORMAT_GZIP
, 9 },
1196 { "/converter-output-stream/roundtrip/raw-0", G_ZLIB_COMPRESSOR_FORMAT_RAW
, 0 },
1197 { "/converter-output-stream/roundtrip/raw-9", G_ZLIB_COMPRESSOR_FORMAT_RAW
, 9 },
1199 CompressorTest truncation_tests
[] = {
1200 { "/converter-input-stream/truncation/zlib", G_ZLIB_COMPRESSOR_FORMAT_ZLIB
, 0 },
1201 { "/converter-input-stream/truncation/gzip", G_ZLIB_COMPRESSOR_FORMAT_GZIP
, 0 },
1202 { "/converter-input-stream/truncation/raw", G_ZLIB_COMPRESSOR_FORMAT_RAW
, 0 },
1204 CharsetTest charset_tests
[] = {
1205 { "/converter-input-stream/charset/utf8->latin1", "UTF-8", "\303\205rr Sant\303\251", "ISO-8859-1", "\305rr Sant\351", 0 },
1206 { "/converter-input-stream/charset/latin1->utf8", "ISO-8859-1", "\305rr Sant\351", "UTF-8", "\303\205rr Sant\303\251", 0 },
1207 { "/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 },
1212 g_test_init (&argc
, &argv
, NULL
);
1214 g_test_bug_base ("http://bugzilla.gnome.org/");
1216 g_test_add_func ("/converter/basics", test_converter_basics
);
1217 g_test_add_func ("/converter-input-stream/expander", test_expander
);
1218 g_test_add_func ("/converter-input-stream/compressor", test_compressor
);
1220 for (i
= 0; i
< G_N_ELEMENTS (compressor_tests
); i
++)
1221 g_test_add_data_func (compressor_tests
[i
].path
, &compressor_tests
[i
], test_roundtrip
);
1223 for (i
= 0; i
< G_N_ELEMENTS (truncation_tests
); i
++)
1224 g_test_add_data_func (truncation_tests
[i
].path
, &truncation_tests
[i
], test_truncation
);
1226 for (i
= 0; i
< G_N_ELEMENTS (charset_tests
); i
++)
1227 g_test_add_data_func (charset_tests
[i
].path
, &charset_tests
[i
], test_charset
);
1229 g_test_add_func ("/converter-stream/pollable", test_converter_pollable
);
1230 g_test_add_func ("/converter-stream/leftover", test_converter_leftover
);
1232 return g_test_run();