• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* GLib testing framework examples and tests
2  * Copyright (C) 2010-2012 Collabora Ltd.
3  * Authors: Xavier Claessens <xclaesse@gmail.com>
4  *          Mike Ruprecht <mike.ruprecht@collabora.co.uk>
5  *
6  * This work is provided "as is"; redistribution and modification
7  * in whole or in part, in any medium, physical or electronic is
8  * permitted without restriction.
9  *
10  * This work is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13  *
14  * In no event shall the authors or contributors be liable for any
15  * direct, indirect, incidental, special, exemplary, or consequential
16  * damages (including, but not limited to, procurement of substitute
17  * goods or services; loss of use, data, or profits; or business
18  * interruption) however caused and on any theory of liability, whether
19  * in contract, strict liability, or tort (including negligence or
20  * otherwise) arising in any way out of the use of this software, even
21  * if advised of the possibility of such damage.
22  */
23 
24 #include <glib/glib.h>
25 #include <glib/gstdio.h>
26 #include <gio/gio.h>
27 #include <stdlib.h>
28 #include <string.h>
29 
30 typedef enum
31 {
32   TEST_THREADED_NONE    = 0,
33   TEST_THREADED_ISTREAM = 1,
34   TEST_THREADED_OSTREAM = 2,
35   TEST_CANCEL           = 4,
36   TEST_THREADED_BOTH    = TEST_THREADED_ISTREAM | TEST_THREADED_OSTREAM,
37 } TestThreadedFlags;
38 
39 typedef struct
40 {
41   GMainLoop *main_loop;
42   const gchar *data;
43   GInputStream *istream;
44   GOutputStream *ostream;
45   TestThreadedFlags flags;
46   gchar *input_path;
47   gchar *output_path;
48 } TestCopyChunksData;
49 
50 static void
test_copy_chunks_splice_cb(GObject * source,GAsyncResult * res,gpointer user_data)51 test_copy_chunks_splice_cb (GObject      *source,
52                             GAsyncResult *res,
53                             gpointer      user_data)
54 {
55   TestCopyChunksData *data = user_data;
56   gchar *received_data;
57   GError *error = NULL;
58   gssize bytes_spliced;
59 
60   bytes_spliced = g_output_stream_splice_finish (G_OUTPUT_STREAM (source),
61                                                  res, &error);
62 
63   if (data->flags & TEST_CANCEL)
64     {
65       g_assert_error (error, G_IO_ERROR, G_IO_ERROR_CANCELLED);
66       g_main_loop_quit (data->main_loop);
67       return;
68     }
69 
70   g_assert_no_error (error);
71   g_assert_cmpint (bytes_spliced, ==, strlen (data->data));
72 
73   if (data->flags & TEST_THREADED_OSTREAM)
74     {
75       gsize length = 0;
76 
77       g_file_get_contents (data->output_path, &received_data,
78                            &length, &error);
79       g_assert_no_error (error);
80       g_assert_cmpstr (received_data, ==, data->data);
81       g_free (received_data);
82     }
83   else
84     {
85       received_data = g_memory_output_stream_get_data (G_MEMORY_OUTPUT_STREAM (data->ostream));
86       g_assert_cmpstr (received_data, ==, data->data);
87     }
88 
89   g_assert (g_input_stream_is_closed (data->istream));
90   g_assert (g_output_stream_is_closed (data->ostream));
91 
92   if (data->flags & TEST_THREADED_ISTREAM)
93     {
94       g_unlink (data->input_path);
95       g_free (data->input_path);
96     }
97 
98   if (data->flags & TEST_THREADED_OSTREAM)
99     {
100       g_unlink (data->output_path);
101       g_free (data->output_path);
102     }
103 
104   g_main_loop_quit (data->main_loop);
105 }
106 
107 static void
test_copy_chunks_start(TestThreadedFlags flags)108 test_copy_chunks_start (TestThreadedFlags flags)
109 {
110   TestCopyChunksData data;
111   GError *error = NULL;
112   GCancellable *cancellable = NULL;
113 
114   data.main_loop = g_main_loop_new (NULL, FALSE);
115   data.data = "abcdefghijklmnopqrstuvwxyz";
116   data.flags = flags;
117 
118   if (data.flags & TEST_CANCEL)
119     {
120       cancellable = g_cancellable_new ();
121       g_cancellable_cancel (cancellable);
122     }
123 
124   if (data.flags & TEST_THREADED_ISTREAM)
125     {
126       GFile *file;
127       GFileIOStream *stream;
128 
129       file = g_file_new_tmp ("test-inputXXXXXX", &stream, &error);
130       g_assert_no_error (error);
131       g_object_unref (stream);
132       data.input_path = g_file_get_path (file);
133       g_file_set_contents (data.input_path,
134                            data.data, strlen (data.data),
135                            &error);
136       g_assert_no_error (error);
137       data.istream = G_INPUT_STREAM (g_file_read (file, NULL, &error));
138       g_assert_no_error (error);
139       g_object_unref (file);
140     }
141   else
142     {
143       data.istream = g_memory_input_stream_new_from_data (data.data, -1, NULL);
144     }
145 
146   if (data.flags & TEST_THREADED_OSTREAM)
147     {
148       GFile *file;
149       GFileIOStream *stream;
150 
151       file = g_file_new_tmp ("test-outputXXXXXX", &stream, &error);
152       g_assert_no_error (error);
153       g_object_unref (stream);
154       data.output_path = g_file_get_path (file);
155       data.ostream = G_OUTPUT_STREAM (g_file_replace (file, NULL, FALSE,
156                                                       G_FILE_CREATE_NONE,
157                                                       NULL, &error));
158       g_assert_no_error (error);
159       g_object_unref (file);
160     }
161   else
162     {
163       data.ostream = g_memory_output_stream_new (NULL, 0, g_realloc, g_free);
164     }
165 
166   g_output_stream_splice_async (data.ostream, data.istream,
167                                 G_OUTPUT_STREAM_SPLICE_CLOSE_SOURCE |
168                                 G_OUTPUT_STREAM_SPLICE_CLOSE_TARGET,
169                                 G_PRIORITY_DEFAULT, cancellable,
170                                 test_copy_chunks_splice_cb, &data);
171 
172   /* We do not hold a ref in data struct, this is to make sure the operation
173    * keeps the iostream objects alive until it finishes
174    */
175   g_object_unref (data.istream);
176   g_object_unref (data.ostream);
177   g_clear_object (&cancellable);
178 
179   g_main_loop_run (data.main_loop);
180   g_main_loop_unref (data.main_loop);
181 }
182 
183 static void
test_copy_chunks(void)184 test_copy_chunks (void)
185 {
186   test_copy_chunks_start (TEST_THREADED_NONE);
187 }
188 
189 static void
test_copy_chunks_threaded_input(void)190 test_copy_chunks_threaded_input (void)
191 {
192   test_copy_chunks_start (TEST_THREADED_ISTREAM);
193 }
194 
195 static void
test_copy_chunks_threaded_output(void)196 test_copy_chunks_threaded_output (void)
197 {
198   test_copy_chunks_start (TEST_THREADED_OSTREAM);
199 }
200 
201 static void
test_copy_chunks_threaded(void)202 test_copy_chunks_threaded (void)
203 {
204   test_copy_chunks_start (TEST_THREADED_BOTH);
205 }
206 
207 static void
test_cancelled(void)208 test_cancelled (void)
209 {
210   test_copy_chunks_start (TEST_THREADED_NONE | TEST_CANCEL);
211 }
212 
213 int
main(int argc,char * argv[])214 main (int   argc,
215       char *argv[])
216 {
217   g_test_init (&argc, &argv, NULL);
218 
219   g_test_add_func ("/async-splice/copy-chunks", test_copy_chunks);
220   g_test_add_func ("/async-splice/copy-chunks-threaded-input",
221                    test_copy_chunks_threaded_input);
222   g_test_add_func ("/async-splice/copy-chunks-threaded-output",
223                    test_copy_chunks_threaded_output);
224   g_test_add_func ("/async-splice/copy-chunks-threaded",
225                    test_copy_chunks_threaded);
226   g_test_add_func ("/async-splice/cancelled",
227                    test_cancelled);
228 
229   return g_test_run();
230 }
231