Add some async file tests
[platform/upstream/glib.git] / gio / tests / file.c
1 #include <string.h>
2 #include <gio/gio.h>
3 #include <gio/gfiledescriptorbased.h>
4
5 static void
6 test_basic (void)
7 {
8   GFile *file;
9   gchar *s;
10
11   file = g_file_new_for_path ("./some/directory/testfile");
12
13   s = g_file_get_basename (file);
14   g_assert_cmpstr (s, ==, "testfile");
15   g_free (s);
16
17   s = g_file_get_uri (file);
18   g_assert (g_str_has_prefix (s, "file://"));
19   g_assert (g_str_has_suffix (s, "/some/directory/testfile"));
20   g_free (s);
21
22   g_assert (g_file_has_uri_scheme (file, "file"));
23   s = g_file_get_uri_scheme (file);
24   g_assert_cmpstr (s, ==, "file");
25   g_free (s);
26
27   g_object_unref (file);
28 }
29
30 static void
31 test_parent (void)
32 {
33   GFile *file;
34   GFile *file2;
35   GFile *parent;
36   GFile *root;
37
38   file = g_file_new_for_path ("./some/directory/testfile");
39   file2 = g_file_new_for_path ("./some/directory");
40   root = g_file_new_for_path ("/");
41
42   g_assert (g_file_has_parent (file, file2));
43
44   parent = g_file_get_parent (file);
45   g_assert (g_file_equal (parent, file2));
46   g_object_unref (parent);
47
48   g_assert (g_file_get_parent (root) == NULL);
49
50   g_object_unref (file);
51   g_object_unref (file2);
52   g_object_unref (root);
53 }
54
55 static void
56 test_child (void)
57 {
58   GFile *file;
59   GFile *child;
60   GFile *child2;
61
62   file = g_file_new_for_path ("./some/directory");
63   child = g_file_get_child (file, "child");
64   g_assert (g_file_has_parent (child, file));
65
66   child2 = g_file_get_child_for_display_name (file, "child2", NULL);
67   g_assert (g_file_has_parent (child2, file));
68
69   g_object_unref (child);
70   g_object_unref (child2);
71   g_object_unref (file);
72 }
73
74 static void
75 test_type (void)
76 {
77   GFile *file;
78   GFileType type;
79
80   file = g_file_new_for_path (SRCDIR "/file.c");
81   type = g_file_query_file_type (file, 0, NULL);
82   g_assert_cmpint (type, ==, G_FILE_TYPE_REGULAR);
83   g_object_unref (file);
84
85   file = g_file_new_for_path (SRCDIR "/schema-tests");
86   type = g_file_query_file_type (file, 0, NULL);
87   g_assert_cmpint (type, ==, G_FILE_TYPE_DIRECTORY);
88   g_object_unref (file);
89 }
90
91
92 typedef struct
93 {
94   GFile *file;
95   GFileMonitor *monitor;
96   GOutputStream *ostream;
97   GInputStream *istream;
98   GMainLoop *loop;
99
100   gint monitor_created;
101   gint monitor_deleted;
102   gint monitor_changed;
103   gchar *monitor_path;
104   gchar *data;
105   gchar *buffer;
106 } CreateDeleteData;
107
108 static void
109 monitor_changed (GFileMonitor      *monitor,
110                  GFile             *file,
111                  GFile             *other_file,
112                  GFileMonitorEvent  event_type,
113                  gpointer           user_data)
114 {
115   CreateDeleteData *data = user_data;
116
117   g_assert_cmpstr (data->monitor_path, ==, g_file_get_path (file));
118
119   if (event_type == G_FILE_MONITOR_EVENT_CREATED)
120     data->monitor_created++;
121   if (event_type == G_FILE_MONITOR_EVENT_DELETED)
122     data->monitor_deleted++;
123   if (event_type == G_FILE_MONITOR_EVENT_CHANGED)
124     data->monitor_changed++;
125 }
126
127
128 static gboolean
129 quit_idle (gpointer user_data)
130 {
131   CreateDeleteData *data = user_data;
132
133   g_main_loop_quit (data->loop);
134
135   return FALSE;
136 }
137
138 static void
139 iclosed_cb (GObject      *source,
140             GAsyncResult *res,
141             gpointer      user_data)
142 {
143   CreateDeleteData *data = user_data;
144   GError *error;
145   gboolean ret;
146
147   error = NULL;
148   ret = g_input_stream_close_finish (data->istream, res, &error);
149   g_assert_no_error (error);
150   g_assert (ret);
151
152   g_assert (g_input_stream_is_closed (data->istream));
153
154   ret = g_file_delete (data->file, NULL, &error);
155   g_assert (ret);
156   g_assert_no_error (error);
157
158   /* work around file monitor bug:
159    * inotify events are only processed every 1000 ms, regardless
160    * of the rate limit set on the file monitor
161    */
162   g_timeout_add (2000, quit_idle, data);
163 }
164
165 static void
166 read_cb (GObject      *source,
167          GAsyncResult *res,
168          gpointer      user_data)
169 {
170   CreateDeleteData *data = user_data;
171   GError *error;
172   gssize size;
173
174   error = NULL;
175   size = g_input_stream_read_finish (data->istream, res, &error);
176   g_assert_no_error (error);
177   g_assert_cmpint (size, ==, strlen (data->data));
178   g_assert_cmpstr (data->buffer, ==, data->data);
179
180   g_assert (!g_input_stream_is_closed (data->istream));
181
182   g_input_stream_close_async (data->istream, 0, NULL, iclosed_cb, data);
183 }
184
185 static void
186 opened_cb (GObject      *source,
187            GAsyncResult *res,
188            gpointer      user_data)
189 {
190   CreateDeleteData *data = user_data;
191   GError *error;
192
193   error = NULL;
194   data->istream = (GInputStream *)g_file_read_finish (data->file, res, &error);
195   g_assert_no_error (error);
196
197   data->buffer = g_new0 (gchar, strlen (data->data) + 1);
198   g_input_stream_read_async (data->istream,
199                              data->buffer,
200                              strlen (data->data),
201                              0,
202                              NULL,
203                              read_cb,
204                              data);
205 }
206
207 static void
208 oclosed_cb (GObject      *source,
209             GAsyncResult *res,
210             gpointer      user_data)
211 {
212   CreateDeleteData *data = user_data;
213   GError *error;
214   gboolean ret;
215
216   error = NULL;
217   ret = g_output_stream_close_finish (data->ostream, res, &error);
218   g_assert_no_error (error);
219   g_assert (ret);
220   g_assert (g_output_stream_is_closed (data->ostream));
221
222   g_file_read_async (data->file, 0, NULL, opened_cb, data);
223 }
224
225 static void
226 written_cb (GObject      *source,
227             GAsyncResult *res,
228             gpointer      user_data)
229 {
230   CreateDeleteData *data = user_data;
231   gssize size;
232   GError *error;
233
234   error = NULL;
235   size = g_output_stream_write_finish (data->ostream, res, &error);
236   g_assert_no_error (error);
237   g_assert_cmpint (size, ==, strlen (data->data));
238   g_assert (!g_output_stream_is_closed (data->ostream));
239
240   g_output_stream_close_async (data->ostream, 0, NULL, oclosed_cb, data);
241 }
242
243 static void
244 created_cb (GObject      *source,
245             GAsyncResult *res,
246             gpointer      user_data)
247 {
248   CreateDeleteData *data = user_data;
249   GError *error;
250
251   error = NULL;
252   data->ostream = (GOutputStream *)g_file_create_finish (G_FILE (source), res, &error);
253   g_assert_no_error (error);
254   g_assert (g_file_query_exists  (data->file, NULL));
255
256   data->data = "abcdefghijklmnopqrstuvxyz";
257   g_output_stream_write_async (data->ostream,
258                                data->data,
259                                strlen (data->data),
260                                0,
261                                NULL,
262                                written_cb,
263                                data);
264 }
265
266 static gboolean
267 stop_timeout (gpointer data)
268 {
269   g_assert_not_reached ();
270
271   return FALSE;
272 }
273
274 /*
275  * This test does a fully async create-write-read-delete.
276  * Callbackistan.
277  */
278 static void
279 test_create_delete (void)
280 {
281   gint fd;
282   GError *error;
283   CreateDeleteData *data;
284
285   data = g_new0 (CreateDeleteData, 1);
286
287   error = NULL;
288   fd = g_file_open_tmp ("g_file_create_delete_XXXXXX", &data->monitor_path, &error);
289   g_assert_no_error (error);
290   unlink (data->monitor_path);
291   close (fd);
292
293   data->file = g_file_new_for_path (data->monitor_path);
294   g_assert (!g_file_query_exists  (data->file, NULL));
295
296   data->monitor = g_file_monitor_file (data->file, 0, NULL, &error);
297   g_file_monitor_set_rate_limit (data->monitor, 100);
298   g_assert_no_error (error);
299
300   g_signal_connect (data->monitor, "changed", G_CALLBACK (monitor_changed), data);
301
302   data->loop = g_main_loop_new (NULL, FALSE);
303
304   g_timeout_add (5000, stop_timeout, NULL);
305
306   g_file_create_async (data->file, 0, 0, NULL, created_cb, data);
307
308   g_main_loop_run (data->loop);
309
310   g_assert_cmpint (data->monitor_created, ==, 1);
311   g_assert_cmpint (data->monitor_deleted, ==, 1);
312   g_assert_cmpint (data->monitor_changed, >, 0);
313
314   g_main_loop_unref (data->loop);
315   g_file_monitor_cancel (data->monitor);
316   g_object_unref (data->monitor);
317   g_object_unref (data->ostream);
318   g_object_unref (data->istream);
319   g_object_unref (data->file);
320   g_free (data->monitor_path);
321   g_free (data->buffer);
322   g_free (data);
323 }
324
325 int
326 main (int argc, char *argv[])
327 {
328   g_type_init ();
329
330   g_test_init (&argc, &argv, NULL);
331
332   g_test_add_func ("/file/basic", test_basic);
333   g_test_add_func ("/file/parent", test_parent);
334   g_test_add_func ("/file/child", test_child);
335   g_test_add_func ("/file/type", test_type);
336   g_test_add_func ("/file/create-delete", test_create_delete);
337
338   return g_test_run ();
339 }