| 
									
										
										
										
											2013-06-02 19:59:48 -04:00
										 |  |  | #include <gio/gio.h>
 | 
					
						
							| 
									
										
										
										
											2017-08-18 10:01:18 +01:00
										 |  |  | #include <gstdio.h>
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | typedef struct | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   gchar *tmp_dir; | 
					
						
							|  |  |  | } Fixture; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void | 
					
						
							|  |  |  | setup (Fixture       *fixture, | 
					
						
							|  |  |  |        gconstpointer  user_data) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   GError *error = NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   fixture->tmp_dir = g_dir_make_tmp ("gio-test-file-monitor_XXXXXX", &error); | 
					
						
							|  |  |  |   g_assert_no_error (error); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   g_test_message ("Using temporary directory: %s", fixture->tmp_dir); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void | 
					
						
							|  |  |  | teardown (Fixture       *fixture, | 
					
						
							|  |  |  |           gconstpointer  user_data) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   g_assert_cmpint (g_rmdir (fixture->tmp_dir), ==, 0); | 
					
						
							|  |  |  |   g_clear_pointer (&fixture->tmp_dir, g_free); | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2013-06-02 19:59:48 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | typedef struct { | 
					
						
							|  |  |  |   GFile *file; | 
					
						
							|  |  |  |   GOutputStream *stream; | 
					
						
							|  |  |  |   GMainLoop *loop; | 
					
						
							|  |  |  |   gint state; | 
					
						
							|  |  |  | } MonitorData; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static gboolean | 
					
						
							|  |  |  | create_file_idle (gpointer data) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   MonitorData *d = data; | 
					
						
							|  |  |  |   GError *error = NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   g_assert (d->state == 0); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   d->stream = (GOutputStream*)g_file_create (d->file, 0, NULL, &error); | 
					
						
							|  |  |  |   g_assert_no_error (error); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   d->state = 1; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return G_SOURCE_REMOVE; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static gboolean | 
					
						
							|  |  |  | write_file_idle (gpointer data) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   MonitorData *d = data; | 
					
						
							|  |  |  |   GError *error = NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   g_assert (d->state == 2); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   g_output_stream_write (d->stream, "abcd", 4, NULL, &error); | 
					
						
							|  |  |  |   g_assert_no_error (error); | 
					
						
							|  |  |  |   g_object_unref (d->stream); | 
					
						
							|  |  |  |   d->stream = NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   d->state = 3; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return G_SOURCE_REMOVE; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static gboolean | 
					
						
							|  |  |  | delete_file_idle (gpointer data) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   MonitorData *d = data; | 
					
						
							|  |  |  |   GError *error = NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   g_assert (d->state == 4); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   g_file_delete (d->file, NULL, &error); | 
					
						
							|  |  |  |   g_assert_no_error (error); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   d->state = 5; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return G_SOURCE_REMOVE; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void | 
					
						
							|  |  |  | changed_cb (GFileMonitor      *monitor, | 
					
						
							|  |  |  |             GFile             *file, | 
					
						
							|  |  |  |             GFile             *other_file, | 
					
						
							|  |  |  |             GFileMonitorEvent  event, | 
					
						
							|  |  |  |             gpointer           data) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   MonitorData *d = data; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   switch (d->state) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |     case 1: | 
					
						
							|  |  |  |       g_assert (event == G_FILE_MONITOR_EVENT_CREATED); | 
					
						
							|  |  |  |       d->state = 2; | 
					
						
							|  |  |  |       g_idle_add (write_file_idle, data); | 
					
						
							|  |  |  |       break; | 
					
						
							|  |  |  |     case 3: | 
					
						
							|  |  |  |       g_assert (event == G_FILE_MONITOR_EVENT_CHANGED || | 
					
						
							|  |  |  |                 event == G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT); | 
					
						
							|  |  |  |       if (event == G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |           d->state = 4; | 
					
						
							|  |  |  |           g_idle_add (delete_file_idle, data); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |       break; | 
					
						
							|  |  |  |     case 5: | 
					
						
							|  |  |  |       g_assert (event == G_FILE_MONITOR_EVENT_DELETED); | 
					
						
							|  |  |  |       d->state = 6; | 
					
						
							|  |  |  |       if (d->loop) | 
					
						
							|  |  |  |         g_main_loop_quit (d->loop); | 
					
						
							|  |  |  |       break; | 
					
						
							|  |  |  |     default: | 
					
						
							|  |  |  |       g_assert_not_reached (); | 
					
						
							|  |  |  |       break; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void | 
					
						
							|  |  |  | file_changed_cb (GFileMonitor      *monitor, | 
					
						
							|  |  |  |                  GFile             *file, | 
					
						
							|  |  |  |                  GFile             *other_file, | 
					
						
							|  |  |  |                  GFileMonitorEvent  event, | 
					
						
							|  |  |  |                  gpointer           data) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   gint *state = data; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   switch (*state) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |     case 0: | 
					
						
							|  |  |  |       g_assert (event == G_FILE_MONITOR_EVENT_CREATED); | 
					
						
							|  |  |  |       *state = 1; | 
					
						
							|  |  |  |       break; | 
					
						
							|  |  |  |     case 1: | 
					
						
							|  |  |  |       g_assert (event == G_FILE_MONITOR_EVENT_CHANGED || | 
					
						
							|  |  |  |                 event == G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT); | 
					
						
							|  |  |  |       if (event == G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT) | 
					
						
							|  |  |  |         *state = 2; | 
					
						
							|  |  |  |       break; | 
					
						
							|  |  |  |     case 2: | 
					
						
							|  |  |  |       g_assert (event == G_FILE_MONITOR_EVENT_DELETED); | 
					
						
							|  |  |  |       *state = 3; | 
					
						
							|  |  |  |       break; | 
					
						
							|  |  |  |     default: | 
					
						
							|  |  |  |       g_assert_not_reached (); | 
					
						
							|  |  |  |       break; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void | 
					
						
							| 
									
										
										
										
											2017-08-18 10:01:18 +01:00
										 |  |  | test_directory_monitor (Fixture       *fixture, | 
					
						
							|  |  |  |                         gconstpointer  user_data) | 
					
						
							| 
									
										
										
										
											2013-06-02 19:59:48 -04:00
										 |  |  | { | 
					
						
							|  |  |  |   GFile *file; | 
					
						
							|  |  |  |   GFile *child; | 
					
						
							|  |  |  |   GFileMonitor *dir_monitor; | 
					
						
							|  |  |  |   GFileMonitor *file_monitor; | 
					
						
							|  |  |  |   GError *error = NULL; | 
					
						
							|  |  |  |   MonitorData data; | 
					
						
							|  |  |  |   gint state; | 
					
						
							|  |  |  |   GMainLoop *loop; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-08-18 10:01:18 +01:00
										 |  |  |   file = g_file_new_for_path (fixture->tmp_dir); | 
					
						
							| 
									
										
										
										
											2013-06-02 19:59:48 -04:00
										 |  |  |   dir_monitor = g_file_monitor_directory (file, 0, NULL, &error); | 
					
						
							|  |  |  |   g_assert_no_error (error); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   child = g_file_get_child (file, "test-file"); | 
					
						
							|  |  |  |   file_monitor = g_file_monitor_file (child, 0, NULL, &error); | 
					
						
							|  |  |  |   g_assert_no_error (error); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   loop = g_main_loop_new (NULL, FALSE); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   g_signal_connect (dir_monitor, "changed", G_CALLBACK (changed_cb), &data); | 
					
						
							|  |  |  |   g_signal_connect (file_monitor, "changed", G_CALLBACK (file_changed_cb), &state); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   data.loop = loop; | 
					
						
							|  |  |  |   data.file = child; | 
					
						
							|  |  |  |   data.state = 0; | 
					
						
							|  |  |  |   state = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   g_idle_add (create_file_idle, &data); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   g_main_loop_run (loop); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   g_assert_cmpint (data.state, ==, 6); | 
					
						
							|  |  |  |   g_assert_cmpint (state, ==, 3); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   g_main_loop_unref (loop); | 
					
						
							|  |  |  |   g_object_unref (dir_monitor); | 
					
						
							|  |  |  |   g_object_unref (file_monitor); | 
					
						
							|  |  |  |   g_object_unref (child); | 
					
						
							|  |  |  |   g_object_unref (file); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int | 
					
						
							|  |  |  | main (int argc, char *argv[]) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   g_test_init (&argc, &argv, NULL); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-08-18 10:01:18 +01:00
										 |  |  |   g_test_add ("/monitor/directory", Fixture, NULL, setup, test_directory_monitor, teardown); | 
					
						
							| 
									
										
										
										
											2013-06-02 19:59:48 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  |   return g_test_run (); | 
					
						
							|  |  |  | } |