mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2024-12-26 23:46:15 +01:00
f288898485
Sometimes file monitor events may be slow to emit. Using g_idle_add makes it less possible for events to be scheduled later than the main loop quit, preventing test failure caused by missing events. This fixes test failure on FreeBSD.
221 lines
4.6 KiB
C
221 lines
4.6 KiB
C
#include <gio/gio.h>
|
|
#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);
|
|
}
|
|
|
|
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 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;
|
|
}
|
|
|
|
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;
|
|
g_idle_add (stop_loop_idle, data);
|
|
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
|
|
test_directory_monitor (Fixture *fixture,
|
|
gconstpointer user_data)
|
|
{
|
|
GFile *file;
|
|
GFile *child;
|
|
GFileMonitor *dir_monitor;
|
|
GFileMonitor *file_monitor;
|
|
GError *error = NULL;
|
|
MonitorData data;
|
|
gint state;
|
|
GMainLoop *loop;
|
|
|
|
file = g_file_new_for_path (fixture->tmp_dir);
|
|
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);
|
|
|
|
g_test_add ("/monitor/directory", Fixture, NULL, setup, test_directory_monitor, teardown);
|
|
|
|
return g_test_run ();
|
|
}
|