2013-06-03 01:59:48 +02:00
|
|
|
#include <gio/gio.h>
|
2017-08-18 11:01:18 +02: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-03 01:59:48 +02: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;
|
|
|
|
}
|
|
|
|
|
2018-06-03 14:51:31 +02:00
|
|
|
static gboolean
|
|
|
|
stop_loop_idle (gpointer data)
|
|
|
|
{
|
|
|
|
MonitorData *d = data;
|
|
|
|
|
|
|
|
g_assert (d->state == 6);
|
|
|
|
|
|
|
|
if (d->loop)
|
|
|
|
g_main_loop_quit (d->loop);
|
|
|
|
|
|
|
|
return G_SOURCE_REMOVE;
|
|
|
|
}
|
|
|
|
|
2013-06-03 01:59:48 +02:00
|
|
|
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;
|
2018-06-03 14:51:31 +02:00
|
|
|
g_idle_add (stop_loop_idle, data);
|
2013-06-03 01:59:48 +02:00
|
|
|
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 11:01:18 +02:00
|
|
|
test_directory_monitor (Fixture *fixture,
|
|
|
|
gconstpointer user_data)
|
2013-06-03 01:59:48 +02:00
|
|
|
{
|
|
|
|
GFile *file;
|
|
|
|
GFile *child;
|
|
|
|
GFileMonitor *dir_monitor;
|
|
|
|
GFileMonitor *file_monitor;
|
|
|
|
GError *error = NULL;
|
|
|
|
MonitorData data;
|
|
|
|
gint state;
|
|
|
|
GMainLoop *loop;
|
|
|
|
|
2017-08-18 11:01:18 +02:00
|
|
|
file = g_file_new_for_path (fixture->tmp_dir);
|
2013-06-03 01:59:48 +02: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 11:01:18 +02:00
|
|
|
g_test_add ("/monitor/directory", Fixture, NULL, setup, test_directory_monitor, teardown);
|
2013-06-03 01:59:48 +02:00
|
|
|
|
|
|
|
return g_test_run ();
|
|
|
|
}
|