| /* GLib testing framework examples and tests | |
| * Authors: Jesse van den Kieboom <jessevdk@gnome.org> | |
| * | |
| * SPDX-License-Identifier: LicenseRef-old-glib-tests | |
| * | |
| * This work is provided "as is"; redistribution and modification | |
| * in whole or in part, in any medium, physical or electronic is | |
| * permitted without restriction. | |
| * | |
| * This work is distributed in the hope that it will be useful, | |
| * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | |
| * | |
| * In no event shall the authors or contributors be liable for any | |
| * direct, indirect, incidental, special, exemplary, or consequential | |
| * damages (including, but not limited to, procurement of substitute | |
| * goods or services; loss of use, data, or profits; or business | |
| * interruption) however caused and on any theory of liability, whether | |
| * in contract, strict liability, or tort (including negligence or | |
| * otherwise) arising in any way out of the use of this software, even | |
| * if advised of the possibility of such damage. | |
| */ | |
| #include <glib/glib.h> | |
| #include <gio/gio.h> | |
| #include <stdlib.h> | |
| #include <string.h> | |
| #define DATA_TO_WRITE "Hello world\n" | |
| typedef struct | |
| { | |
| GOutputStream *conv_stream; | |
| GOutputStream *data_stream; | |
| gchar *expected_output; | |
| gsize expected_size; | |
| GMainLoop *main_loop; | |
| } SetupData; | |
| static void | |
| create_streams (SetupData *data) | |
| { | |
| GConverter *converter; | |
| converter = G_CONVERTER (g_zlib_compressor_new (G_ZLIB_COMPRESSOR_FORMAT_GZIP, -1)); | |
| data->data_stream = g_memory_output_stream_new (NULL, 0, g_realloc, g_free); | |
| data->conv_stream = g_converter_output_stream_new (data->data_stream, | |
| converter); | |
| g_object_unref (converter); | |
| } | |
| static void | |
| destroy_streams (SetupData *data) | |
| { | |
| g_object_unref (data->data_stream); | |
| g_object_unref (data->conv_stream); | |
| } | |
| static void | |
| write_data_to_stream (SetupData *data) | |
| { | |
| gsize bytes_written; | |
| GError *error = NULL; | |
| /* just write the data synchronously */ | |
| g_output_stream_write_all (data->conv_stream, | |
| DATA_TO_WRITE, | |
| sizeof (DATA_TO_WRITE), | |
| &bytes_written, | |
| NULL, | |
| &error); | |
| g_assert_no_error (error); | |
| g_assert_cmpint (sizeof (DATA_TO_WRITE), ==, bytes_written); | |
| } | |
| static void | |
| setup_data (SetupData *data, | |
| gconstpointer user_data) | |
| { | |
| data->main_loop = g_main_loop_new (NULL, FALSE); | |
| create_streams (data); | |
| } | |
| static void | |
| teardown_data (SetupData *data, | |
| gconstpointer user_data) | |
| { | |
| /* cleanup */ | |
| g_main_loop_unref (data->main_loop); | |
| destroy_streams (data); | |
| g_free (data->expected_output); | |
| } | |
| static void | |
| compare_output (SetupData *data) | |
| { | |
| gsize size; | |
| gpointer written; | |
| written = g_memory_output_stream_get_data (G_MEMORY_OUTPUT_STREAM (data->data_stream)); | |
| size = g_memory_output_stream_get_data_size (G_MEMORY_OUTPUT_STREAM (data->data_stream)); | |
| g_assert_cmpmem (written, size, data->expected_output, data->expected_size); | |
| } | |
| static void | |
| async_close_ready (GOutputStream *stream, | |
| GAsyncResult *result, | |
| SetupData *data) | |
| { | |
| GError *error = NULL; | |
| /* finish the close */ | |
| g_output_stream_close_finish (stream, result, &error); | |
| g_assert_no_error (error); | |
| /* compare the output with the desired output */ | |
| compare_output (data); | |
| g_main_loop_quit (data->main_loop); | |
| } | |
| static void | |
| prepare_data (SetupData *data, | |
| gboolean manual_flush) | |
| { | |
| GError *error = NULL; | |
| gpointer written; | |
| write_data_to_stream (data); | |
| if (manual_flush) | |
| { | |
| g_output_stream_flush (data->conv_stream, NULL, &error); | |
| g_assert_no_error (error); | |
| } | |
| g_output_stream_close (data->conv_stream, NULL, &error); | |
| g_assert_no_error (error); | |
| written = g_memory_output_stream_get_data (G_MEMORY_OUTPUT_STREAM (data->data_stream)); | |
| data->expected_size = g_memory_output_stream_get_data_size (G_MEMORY_OUTPUT_STREAM (data->data_stream)); | |
| g_assert_cmpuint (data->expected_size, >, 0); | |
| data->expected_output = g_memdup2 (written, data->expected_size); | |
| /* then recreate the streams and prepare them for the asynchronous close */ | |
| destroy_streams (data); | |
| create_streams (data); | |
| write_data_to_stream (data); | |
| } | |
| static void | |
| test_without_flush (SetupData *data, | |
| gconstpointer user_data) | |
| { | |
| prepare_data (data, FALSE); | |
| g_test_bug ("https://bugzilla.gnome.org/show_bug.cgi?id=617937"); | |
| /* just close asynchronously */ | |
| g_output_stream_close_async (data->conv_stream, | |
| G_PRIORITY_DEFAULT, | |
| NULL, | |
| (GAsyncReadyCallback)async_close_ready, | |
| data); | |
| g_main_loop_run (data->main_loop); | |
| } | |
| static void | |
| test_with_flush (SetupData *data, gconstpointer user_data) | |
| { | |
| GError *error = NULL; | |
| g_test_bug ("https://bugzilla.gnome.org/show_bug.cgi?id=617937"); | |
| prepare_data (data, TRUE); | |
| g_output_stream_flush (data->conv_stream, NULL, &error); | |
| g_assert_no_error (error); | |
| /* then close asynchronously */ | |
| g_output_stream_close_async (data->conv_stream, | |
| G_PRIORITY_DEFAULT, | |
| NULL, | |
| (GAsyncReadyCallback)async_close_ready, | |
| data); | |
| g_main_loop_run (data->main_loop); | |
| } | |
| static void | |
| async_flush_ready (GOutputStream *stream, | |
| GAsyncResult *result, | |
| SetupData *data) | |
| { | |
| GError *error = NULL; | |
| g_output_stream_flush_finish (stream, result, &error); | |
| g_assert_no_error (error); | |
| /* then close async after the flush */ | |
| g_output_stream_close_async (data->conv_stream, | |
| G_PRIORITY_DEFAULT, | |
| NULL, | |
| (GAsyncReadyCallback)async_close_ready, | |
| data); | |
| } | |
| static void | |
| test_with_async_flush (SetupData *data, | |
| gconstpointer user_data) | |
| { | |
| g_test_bug ("https://bugzilla.gnome.org/show_bug.cgi?id=617937"); | |
| prepare_data (data, TRUE); | |
| /* first flush async */ | |
| g_output_stream_flush_async (data->conv_stream, | |
| G_PRIORITY_DEFAULT, | |
| NULL, | |
| (GAsyncReadyCallback)async_flush_ready, | |
| data); | |
| g_main_loop_run (data->main_loop); | |
| } | |
| int | |
| main (int argc, | |
| char *argv[]) | |
| { | |
| SetupData *data; | |
| g_test_init (&argc, &argv, NULL); | |
| data = g_slice_new (SetupData); | |
| /* test closing asynchronously without flushing manually */ | |
| g_test_add ("/close-async/without-flush", | |
| SetupData, | |
| data, | |
| setup_data, | |
| test_without_flush, | |
| teardown_data); | |
| /* test closing asynchronously with a synchronous manually flush */ | |
| g_test_add ("/close-async/with-flush", | |
| SetupData, | |
| data, | |
| setup_data, | |
| test_with_flush, | |
| teardown_data); | |
| /* test closing asynchronously with an asynchronous manually flush */ | |
| g_test_add ("/close-async/with-async-flush", | |
| SetupData, | |
| data, | |
| setup_data, | |
| test_with_async_flush, | |
| teardown_data); | |
| g_slice_free (SetupData, data); | |
| return g_test_run(); | |
| } |