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 GExpanderConverter *conv;
96 const guint8 *in, *in_end;
101 conv = G_EXPANDER_CONVERTER (converter);
105 in_end = in + inbuf_size;
114 block_size = v * 1000;
116 if (outbuf_size < block_size)
119 return G_CONVERTER_CONVERTED;
121 g_set_error_literal (error, G_IO_ERROR,
124 return G_CONVERTER_ERROR;
129 *bytes_written += block_size;
130 outbuf_size -= block_size;
131 for (i = 0; i < block_size; i++)
135 if (in == in_end && (flags & G_CONVERTER_INPUT_AT_END))
136 return G_CONVERTER_FINISHED;
137 return G_CONVERTER_CONVERTED;
141 g_expander_converter_iface_init (GConverterIface *iface)
143 iface->convert = g_expander_converter_convert;
144 iface->reset = g_expander_converter_reset;
147 #define G_TYPE_COMPRESSOR_CONVERTER (g_compressor_converter_get_type ())
148 #define G_COMPRESSOR_CONVERTER(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), G_TYPE_COMPRESSOR_CONVERTER, GCompressorConverter))
149 #define G_COMPRESSOR_CONVERTER_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), G_TYPE_COMPRESSOR_CONVERTER, GCompressorConverterClass))
150 #define G_IS_COMPRESSOR_CONVERTER(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_TYPE_COMPRESSOR_CONVERTER))
151 #define G_IS_COMPRESSOR_CONVERTER_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), G_TYPE_COMPRESSOR_CONVERTER))
152 #define G_COMPRESSOR_CONVERTER_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), G_TYPE_COMPRESSOR_CONVERTER, GCompressorConverterClass))
154 typedef struct _GCompressorConverter GCompressorConverter;
155 typedef struct _GCompressorConverterClass GCompressorConverterClass;
157 struct _GCompressorConverterClass
159 GObjectClass parent_class;
162 GType g_compressor_converter_get_type (void) G_GNUC_CONST;
163 GConverter *g_compressor_converter_new (void);
167 static void g_compressor_converter_iface_init (GConverterIface *iface);
169 struct _GCompressorConverter
171 GObject parent_instance;
174 G_DEFINE_TYPE_WITH_CODE (GCompressorConverter, g_compressor_converter, G_TYPE_OBJECT,
175 G_IMPLEMENT_INTERFACE (G_TYPE_CONVERTER,
176 g_compressor_converter_iface_init))
179 g_compressor_converter_class_init (GCompressorConverterClass *klass)
184 g_compressor_converter_init (GCompressorConverter *local)
189 g_compressor_converter_new (void)
193 conv = g_object_new (G_TYPE_COMPRESSOR_CONVERTER, NULL);
199 g_compressor_converter_reset (GConverter *converter)
203 static GConverterResult
204 g_compressor_converter_convert (GConverter *converter,
209 GConverterFlags flags,
211 gsize *bytes_written,
214 GCompressorConverter *conv;
215 const guint8 *in, *in_end;
220 conv = G_COMPRESSOR_CONVERTER (converter);
224 in_end = in + inbuf_size;
233 while (in+block_size < in_end && *(in+block_size) == 0)
237 block_size = v * 1000;
239 /* Not enough data */
240 if (in_end - in < block_size)
244 g_set_error_literal (error, G_IO_ERROR,
245 G_IO_ERROR_PARTIAL_INPUT,
247 return G_CONVERTER_ERROR;
250 for (i = 0; i < block_size; i++)
256 g_set_error_literal (error, G_IO_ERROR,
257 G_IO_ERROR_INVALID_DATA,
259 return G_CONVERTER_ERROR;
263 if (v == 0 && in_end - in == block_size && (flags & G_CONVERTER_INPUT_AT_END) == 0)
267 g_set_error_literal (error, G_IO_ERROR,
268 G_IO_ERROR_PARTIAL_INPUT,
270 return G_CONVERTER_ERROR;
275 *bytes_read += block_size;
279 if (in == in_end && (flags & G_CONVERTER_INPUT_AT_END))
280 return G_CONVERTER_FINISHED;
281 return G_CONVERTER_CONVERTED;
285 g_compressor_converter_iface_init (GConverterIface *iface)
287 iface->convert = g_compressor_converter_convert;
288 iface->reset = g_compressor_converter_reset;
291 guint8 unexpanded_data[] = { 0,1,3,4,5,6,7,3,12,0,0};
296 guint8 *converted1, *converted2, *ptr;
297 gsize n_read, n_written;
300 GConverterResult cres;
301 GInputStream *mem, *cstream;
302 GOutputStream *mem_out, *cstream_out;
303 GConverter *expander;
304 GConverter *converter;
308 expander = g_expander_converter_new ();
310 converted1 = g_malloc (100*1000); /* Large enough */
311 converted2 = g_malloc (100*1000); /* Large enough */
313 cres = g_converter_convert (expander,
314 unexpanded_data, sizeof(unexpanded_data),
315 converted1, 100*1000,
316 G_CONVERTER_INPUT_AT_END,
317 &n_read, &n_written, NULL);
319 g_assert (cres == G_CONVERTER_FINISHED);
320 g_assert (n_read == 11);
321 g_assert (n_written == 41030);
323 g_converter_reset (expander);
325 mem = g_memory_input_stream_new_from_data (unexpanded_data,
326 sizeof (unexpanded_data),
328 cstream = g_converter_input_stream_new (mem, expander);
329 g_assert (g_converter_input_stream_get_converter (G_CONVERTER_INPUT_STREAM (cstream)) == expander);
330 g_object_get (cstream, "converter", &converter, NULL);
331 g_assert (converter == expander);
332 g_object_unref (converter);
333 g_object_unref (mem);
340 res = g_input_stream_read (cstream,
343 g_assert (res != -1);
350 g_assert (total_read == n_written);
351 g_assert (memcmp (converted1, converted2, n_written) == 0);
353 g_converter_reset (expander);
355 mem_out = g_memory_output_stream_new (NULL, 0, g_realloc, g_free);
356 cstream_out = g_converter_output_stream_new (mem_out, expander);
357 g_assert (g_converter_output_stream_get_converter (G_CONVERTER_OUTPUT_STREAM (cstream_out)) == expander);
358 g_object_get (cstream_out, "converter", &converter, NULL);
359 g_assert (converter == expander);
360 g_object_unref (converter);
361 g_object_unref (mem_out);
363 for (i = 0; i < sizeof(unexpanded_data); i++)
366 res = g_output_stream_write (cstream_out,
367 unexpanded_data + i, 1,
369 g_assert (res != -1);
372 g_assert (i == sizeof(unexpanded_data) -1);
378 g_output_stream_close (cstream_out, NULL, NULL);
380 g_assert (g_memory_output_stream_get_data_size (G_MEMORY_OUTPUT_STREAM (mem_out)) == n_written);
381 g_assert (memcmp (g_memory_output_stream_get_data (G_MEMORY_OUTPUT_STREAM (mem_out)),
387 g_object_unref (cstream);
388 g_object_unref (cstream_out);
389 g_object_unref (expander);
393 test_compressor (void)
395 guint8 *converted, *expanded, *ptr;
396 gsize n_read, expanded_size;
399 GConverterResult cres;
400 GInputStream *mem, *cstream;
401 GOutputStream *mem_out, *cstream_out;
402 GConverter *expander, *compressor;
406 expander = g_expander_converter_new ();
407 expanded = g_malloc (100*1000); /* Large enough */
408 cres = g_converter_convert (expander,
409 unexpanded_data, sizeof(unexpanded_data),
411 G_CONVERTER_INPUT_AT_END,
412 &n_read, &expanded_size, NULL);
413 g_assert (cres == G_CONVERTER_FINISHED);
414 g_assert (n_read == 11);
415 g_assert (expanded_size == 41030);
417 compressor = g_compressor_converter_new ();
419 converted = g_malloc (100*1000); /* Large enough */
421 mem = g_memory_input_stream_new_from_data (expanded,
424 cstream = g_converter_input_stream_new (mem, compressor);
425 g_object_unref (mem);
432 res = g_input_stream_read (cstream,
435 g_assert (res != -1);
442 g_assert (total_read == n_read - 1); /* Last 2 zeros are combined */
443 g_assert (memcmp (converted, unexpanded_data, total_read) == 0);
445 g_object_unref (cstream);
447 g_converter_reset (compressor);
449 mem_out = g_memory_output_stream_new (NULL, 0, g_realloc, g_free);
450 cstream_out = g_converter_output_stream_new (mem_out, compressor);
451 g_object_unref (mem_out);
453 for (i = 0; i < expanded_size; i++)
456 res = g_output_stream_write (cstream_out,
459 g_assert (res != -1);
462 g_assert (i == expanded_size -1);
468 g_output_stream_close (cstream_out, NULL, NULL);
470 g_assert (g_memory_output_stream_get_data_size (G_MEMORY_OUTPUT_STREAM (mem_out)) == n_read - 1); /* Last 2 zeros are combined */
471 g_assert (memcmp (g_memory_output_stream_get_data (G_MEMORY_OUTPUT_STREAM (mem_out)),
473 g_memory_output_stream_get_data_size (G_MEMORY_OUTPUT_STREAM (mem_out))) == 0);
475 g_object_unref (cstream_out);
477 g_converter_reset (compressor);
479 memset (expanded, 5, 5*1000*2);
481 mem = g_memory_input_stream_new_from_data (expanded,
484 cstream = g_converter_input_stream_new (mem, compressor);
485 g_object_unref (mem);
492 res = g_input_stream_read (cstream,
495 g_assert (res != -1);
502 g_assert (total_read == 1);
503 g_assert (*converted == 5);
505 g_object_unref (cstream);
507 mem = g_memory_input_stream_new_from_data (expanded,
510 cstream = g_converter_input_stream_new (mem, compressor);
511 g_object_unref (mem);
518 res = g_input_stream_read (cstream,
521 g_assert (res != -1);
528 g_assert (total_read == 2);
529 g_assert (converted[0] == 5);
530 g_assert (converted[1] == 5);
532 g_object_unref (cstream);
534 g_converter_reset (compressor);
536 mem = g_memory_input_stream_new_from_data (expanded,
539 cstream = g_converter_input_stream_new (mem, compressor);
540 g_object_unref (mem);
547 res = g_input_stream_read (cstream,
552 g_assert_error (error, G_IO_ERROR, G_IO_ERROR_PARTIAL_INPUT);
553 g_error_free (error);
562 g_assert (total_read == 1);
563 g_assert (converted[0] == 5);
565 g_object_unref (cstream);
569 g_object_unref (expander);
570 g_object_unref (compressor);
573 #define DATA_LENGTH 1000000
576 test_corruption (GZlibCompressorFormat format, gint level)
578 GError *error = NULL;
579 guint32 *data0, *data1;
582 GInputStream *istream0, *istream1, *cistream1;
583 GOutputStream *ostream1, *ostream2, *costream1;
584 GConverter *compressor, *decompressor;
585 GZlibCompressorFormat fmt;
588 data0 = g_malloc (DATA_LENGTH * sizeof (guint32));
589 for (i = 0; i < DATA_LENGTH; i++)
590 data0[i] = g_random_int ();
592 istream0 = g_memory_input_stream_new_from_data (data0,
593 DATA_LENGTH * sizeof (guint32), NULL);
595 ostream1 = g_memory_output_stream_new (NULL, 0, g_realloc, NULL);
596 compressor = G_CONVERTER (g_zlib_compressor_new (format, level));
597 costream1 = g_converter_output_stream_new (ostream1, compressor);
598 g_assert (g_converter_output_stream_get_converter (G_CONVERTER_OUTPUT_STREAM (costream1)) == compressor);
600 g_output_stream_splice (costream1, istream0, 0, NULL, &error);
601 g_assert_no_error (error);
603 g_object_unref (costream1);
605 g_converter_reset (compressor);
606 g_object_get (compressor, "format", &fmt, "level", &lvl, NULL);
607 g_assert_cmpint (fmt, ==, format);
608 g_assert_cmpint (lvl, ==, level);
609 g_object_unref (compressor);
610 data1 = g_memory_output_stream_get_data (G_MEMORY_OUTPUT_STREAM (ostream1));
611 data1_size = g_memory_output_stream_get_data_size (
612 G_MEMORY_OUTPUT_STREAM (ostream1));
613 g_object_unref (ostream1);
614 g_object_unref (istream0);
616 istream1 = g_memory_input_stream_new_from_data (data1, data1_size, NULL);
617 decompressor = G_CONVERTER (g_zlib_decompressor_new (format));
618 cistream1 = g_converter_input_stream_new (istream1, decompressor);
620 ostream2 = g_memory_output_stream_new (NULL, 0, g_realloc, NULL);
622 g_output_stream_splice (ostream2, cistream1, 0, NULL, &error);
623 g_assert_no_error (error);
625 g_assert_cmpuint (DATA_LENGTH * sizeof (guint32), ==,
626 g_memory_output_stream_get_data_size (G_MEMORY_OUTPUT_STREAM (ostream2)));
627 g_assert (memcmp (data0, g_memory_output_stream_get_data (
628 G_MEMORY_OUTPUT_STREAM (ostream2)), DATA_LENGTH * sizeof (guint32)) == 0);
629 g_object_unref (istream1);
630 g_converter_reset (decompressor);
631 g_object_get (decompressor, "format", &fmt, NULL);
632 g_assert_cmpint (fmt, ==, format);
633 g_object_unref (decompressor);
634 g_object_unref (cistream1);
635 g_object_unref (ostream2);
640 GZlibCompressorFormat format;
645 test_roundtrip (gconstpointer data)
647 const CompressorTest *test = data;
649 g_test_bug ("162549");
651 test_corruption (test->format, test->level);
656 const gchar *charset_in;
657 const gchar *text_in;
658 const gchar *charset_out;
659 const gchar *text_out;
664 test_charset (gconstpointer data)
666 const CharsetTest *test = data;
667 GInputStream *in, *in2;
675 conv = (GConverter *)g_charset_converter_new (test->charset_out, test->charset_in, NULL);
676 g_object_get (conv, "use-fallback", &fallback, NULL);
677 g_assert (!fallback);
679 in = g_memory_input_stream_new_from_data (test->text_in, -1, NULL);
680 in2 = g_converter_input_stream_new (in, conv);
682 count = 2 * strlen (test->text_out);
683 buffer = g_malloc0 (count);
685 g_input_stream_read_all (in2, buffer, count, &bytes_read, NULL, &error);
686 if (test->n_fallbacks == 0)
688 g_assert_no_error (error);
689 g_assert_cmpint (bytes_read, ==, strlen (test->text_out));
690 g_assert_cmpstr (buffer, ==, test->text_out);
694 g_assert_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_DATA);
695 g_error_free (error);
699 g_object_unref (in2);
702 if (test->n_fallbacks == 0)
704 g_object_unref (conv);
708 g_converter_reset (conv);
710 g_assert (!g_charset_converter_get_use_fallback (G_CHARSET_CONVERTER (conv)));
711 g_charset_converter_set_use_fallback (G_CHARSET_CONVERTER (conv), TRUE);
713 in = g_memory_input_stream_new_from_data (test->text_in, -1, NULL);
714 in2 = g_converter_input_stream_new (in, conv);
716 count = 2 * strlen (test->text_out);
717 buffer = g_malloc0 (count);
719 g_input_stream_read_all (in2, buffer, count, &bytes_read, NULL, &error);
720 g_assert_no_error (error);
721 g_assert_cmpstr (buffer, ==, test->text_out);
722 g_assert_cmpint (bytes_read, ==, strlen (test->text_out));
723 g_assert_cmpint (test->n_fallbacks, ==, g_charset_converter_get_num_fallbacks (G_CHARSET_CONVERTER (conv)));
726 g_object_unref (in2);
729 g_object_unref (conv);
736 CompressorTest compressor_tests[] = {
737 { "/converter-output-stream/corruption/zlib-0", G_ZLIB_COMPRESSOR_FORMAT_ZLIB, 0 },
738 { "/converter-output-stream/corruption/zlib-9", G_ZLIB_COMPRESSOR_FORMAT_ZLIB, 9 },
739 { "/converter-output-stream/corruption/gzip-0", G_ZLIB_COMPRESSOR_FORMAT_GZIP, 0 },
740 { "/converter-output-stream/corruption/gzip-9", G_ZLIB_COMPRESSOR_FORMAT_GZIP, 9 },
741 { "/converter-output-stream/corruption/raw-0", G_ZLIB_COMPRESSOR_FORMAT_RAW, 0 },
742 { "/converter-output-stream/corruption/raw-9", G_ZLIB_COMPRESSOR_FORMAT_RAW, 9 },
744 CharsetTest charset_tests[] = {
745 { "/converter-input-stream/charset/utf8->latin1", "UTF-8", "\303\205rr Sant\303\251", "ISO-8859-1", "\305rr Sant\351", 0 },
746 { "/converter-input-stream/charset/latin1->utf8", "ISO-8859-1", "\305rr Sant\351", "UTF-8", "\303\205rr Sant\303\251", 0 },
747 { "/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 },
754 g_test_init (&argc, &argv, NULL);
756 g_test_bug_base ("http://bugzilla.gnome.org/");
758 g_test_add_func ("/converter-input-stream/expander", test_expander);
759 g_test_add_func ("/converter-input-stream/compressor", test_compressor);
761 for (i = 0; i < G_N_ELEMENTS (compressor_tests); i++)
762 g_test_add_data_func (compressor_tests[i].path, &compressor_tests[i], test_roundtrip);
764 for (i = 0; i < G_N_ELEMENTS (charset_tests); i++)
765 g_test_add_data_func (charset_tests[i].path, &charset_tests[i], test_charset);