Created
September 11, 2011 11:53
-
-
Save dmatveev/1209489 to your computer and use it in GitHub Desktop.
GFileMonitor test for gio/kqueue GSoC project
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <glib.h> | |
#include <glib/gprintf.h> | |
#include <gio/gio.h> | |
#include <string.h> /* memset, strlen */ | |
#include <stdlib.h> /* system */ | |
#define MAX_EXPECTED_EVENTS 10 | |
#ifndef EVENT_EXPECT_TIME | |
# define EVENT_EXPECT_TIME 5 | |
#endif | |
/* #define MORE_LOGS */ | |
#ifdef MORE_LOGS | |
# define gft_log g_printf | |
#else | |
# define gft_log | |
#endif | |
typedef struct { | |
GFileMonitorEvent flags; | |
gchar *file1; | |
gchar *file2; | |
} registered_event; | |
typedef struct { | |
int caret; | |
registered_event events[MAX_EXPECTED_EVENTS]; | |
} registered_events; | |
typedef struct { | |
GFileMonitorEvent event; | |
const gchar *humanr; | |
gchar *file1; | |
gchar *file2; | |
} humanr_event; | |
typedef struct { | |
const gchar *action; | |
humanr_event events[MAX_EXPECTED_EVENTS]; | |
} test_case; | |
#define EV_(sym, f1, f2) {G_FILE_MONITOR_EVENT_##sym, #sym, f1, f2} | |
#define END {-1, ""} | |
#define NOT_END(x) ((x.event) != -1) | |
#define SELF "%s" | |
typedef struct { | |
const char *name; | |
const char *filename; | |
GFileMonitorFlags flags; | |
test_case *cases; | |
int count; | |
} test; | |
void register_activity (GFileMonitor *mon, | |
GFile *first, | |
GFile *second, | |
GFileMonitorEvent event, | |
gpointer udata); | |
gpointer run_test (gpointer ptr); | |
int run_test_case (test *t, | |
test_case *tc, | |
registered_events *regd); | |
void run_suite (test *tests, int count); | |
void test_complete (); | |
void | |
decode (GFileMonitorEvent event, gchar *events) | |
{ | |
#define CHECK(x, def) \ | |
if (((x) & (def)) == def) { \ | |
g_sprintf (events, "%s ", #def); \ | |
events += (strlen (#def) + 1); \ | |
} | |
CHECK(event, G_FILE_MONITOR_EVENT_CHANGED); | |
CHECK(event, G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT); | |
CHECK(event, G_FILE_MONITOR_EVENT_DELETED); | |
CHECK(event, G_FILE_MONITOR_EVENT_CREATED); | |
CHECK(event, G_FILE_MONITOR_EVENT_ATTRIBUTE_CHANGED); | |
CHECK(event, G_FILE_MONITOR_EVENT_PRE_UNMOUNT); | |
CHECK(event, G_FILE_MONITOR_EVENT_UNMOUNTED); | |
CHECK(event, G_FILE_MONITOR_EVENT_MOVED); | |
#undef CHECK | |
} | |
void | |
register_activity (GFileMonitor *mon, | |
GFile *first, | |
GFile *second, | |
GFileMonitorEvent event, | |
gpointer udata) | |
{ | |
registered_event *ev; | |
(void) mon; | |
(void) first; | |
(void) second; | |
g_assert (udata != NULL); | |
registered_events *registered = (registered_events *) udata; | |
ev = ®istered->events[registered->caret++]; | |
ev->flags = event; | |
ev->file1 = first ? g_file_get_basename (first) : NULL; | |
ev->file2 = second ? g_file_get_basename (second) : NULL; | |
} | |
int | |
matched_fname (const gchar *test_file, /* associated with the entire test case */ | |
const gchar *expected_file, /* (mask) associated an expected event */ | |
const gchar *registered_name) /* what have have got in the "changed" */ | |
{ | |
if (expected_file) { | |
gchar final_filename[1024]; | |
g_sprintf (final_filename, expected_file, test_file); | |
gft_log (" -- Comparing %s and %s\n", final_filename, registered_name); | |
if (strcmp (final_filename, registered_name) != 0) { | |
gft_log (" -- NOT EQUAL\n"); | |
return 1; /* should continue */ | |
} | |
} | |
return 0; /* normal */ | |
} | |
#define file_or(a, b) ((a) > 0 ? (a) : (b)) | |
int | |
run_test_case (test *t, test_case *tc, registered_events *regd) | |
{ | |
g_assert (t != NULL); | |
g_assert (tc != NULL); | |
g_assert (regd != NULL); | |
int j, k, registered_count; | |
gchar action[1024]; | |
g_sprintf (action, tc->action, t->filename, t->filename); | |
system (action); | |
g_usleep (G_USEC_PER_SEC * EVENT_EXPECT_TIME); | |
registered_count = regd->caret; | |
for (j = 0; j < MAX_EXPECTED_EVENTS; j++) { | |
humanr_event he = tc->events[j]; | |
if (NOT_END(he)) { | |
gft_log ("-- Looking for %s (%d) [%s; %s]\n", | |
he.humanr, | |
he.event, | |
file_or (he.file1, "--"), | |
file_or (he.file2, "--")); | |
for (k = 0; k < regd->caret; k++) { | |
gft_log (" -- Probing an registered one #%d (code %d) [%s; %s]\n", | |
k, | |
regd->events[k].flags, | |
file_or (regd->events[k].file1, "--"), | |
file_or (regd->events[k].file2, "--")); | |
if ((regd->events[k].flags & he.event) == he.event) { | |
gft_log (" -- Event code matched!\n"); | |
if (matched_fname (t->filename, he.file1, regd->events[k].file1) | |
|| matched_fname (t->filename, he.file2, regd->events[k].file2)) { | |
gft_log (" -- One of file names NOT matched too, continuing...\n"); | |
continue; | |
} | |
gft_log (" -- Looks like we\'ve found it!\n"); | |
break; | |
} | |
} | |
if (k != regd->caret) { | |
--registered_count; | |
} | |
g_printf ("%s (%s): %s on \"%s\"\n", | |
(k == regd->caret) ? "FAIL" : "PASS", | |
t->name, | |
he.humanr, | |
action); | |
} else { | |
break; | |
} | |
} | |
if (registered_count) { | |
g_printf ("*** (%s) Warning! There are %d unexpected event(s) registered on \"%s\"\n", | |
t->name, | |
registered_count, | |
action); | |
gft_log ("*** The full event list is:\n"); | |
for (k = 0; k < regd->caret; k++) { | |
g_printf (" %02d: Event code %d, file 1: \"%s\", file 2: \"%s\"\n", | |
k, | |
regd->events[k].flags, | |
file_or(regd->events[k].file1, "--"), | |
file_or(regd->events[k].file2, "--")); | |
} | |
} | |
} | |
gpointer | |
run_test (gpointer ptr) | |
{ | |
test *t = (test *) ptr; | |
g_assert (t != NULL); | |
g_assert (t->name != NULL); | |
g_assert (t->filename != NULL); | |
g_assert (t->cases != NULL); | |
GFileMonitor *mon; | |
GFile *file; | |
int i; | |
registered_events regd; | |
file = g_file_new_for_path (t->filename); | |
g_assert (file != NULL); | |
mon = g_file_monitor (file, t->flags, NULL, NULL); | |
g_assert (mon != NULL); | |
g_signal_connect (mon, "changed", G_CALLBACK (register_activity), ®d); | |
for (i = 0; i < t->count; i++) { | |
memset (®d, 0, sizeof (registered_events)); | |
run_test_case (t, &t->cases[i], ®d); | |
} | |
g_file_monitor_cancel (mon); | |
g_object_unref (G_OBJECT(mon)); | |
g_object_unref (G_OBJECT(file)); | |
test_complete (); | |
return NULL; | |
} | |
GMainLoop *loop; | |
int num_tests; | |
GStaticMutex mutex = G_STATIC_MUTEX_INIT; | |
void | |
run_suite (test *tests, int count) | |
{ | |
int i; | |
g_static_mutex_lock (&mutex); | |
num_tests = count; | |
for (i = 0; i < count; i++) { | |
g_thread_create (run_test, &tests[i], FALSE, NULL); | |
} | |
g_static_mutex_unlock (&mutex); | |
} | |
void | |
test_complete () | |
{ | |
g_assert (loop != NULL); | |
g_static_mutex_lock (&mutex); | |
if (--num_tests == 0) { | |
g_main_loop_quit (loop); | |
} | |
g_static_mutex_unlock (&mutex); | |
} | |
test_case file_test_cases[] = { | |
{"touch %s", {EV_(CREATED, SELF, NULL), END}}, | |
{"touch %s", {EV_(ATTRIBUTE_CHANGED, SELF, NULL), END}}, | |
{"echo 1 >> %s", {EV_(CHANGED, SELF, NULL), EV_(CHANGES_DONE_HINT, NULL, NULL), END}}, | |
{"rm %s", {EV_(DELETED, SELF, NULL), END}}, | |
{"touch %s", {EV_(CREATED, SELF, NULL), END}}, | |
{"mv %s gfmt-ft-moved", {EV_(MOVED, SELF, NULL), END}}, | |
{"rm gfmt-ft-moved", {EV_(DELETED, SELF, NULL), END}}, | |
}; | |
test_case dir_test_cases[] = { | |
{"mkdir %s", {EV_(CREATED, SELF, NULL), END}}, | |
{"touch %s", {EV_(ATTRIBUTE_CHANGED, SELF, NULL), END}}, | |
{"touch %s/foo", {EV_(CREATED, "foo", NULL), END}}, | |
{"rm %s/foo", {EV_(DELETED, "foo", NULL), END}}, | |
{"touch %s/foo", {EV_(CREATED, "foo", NULL), END}}, | |
{"touch %s/bar", {EV_(CREATED, "bar", NULL), END}}, | |
{"mv %s/foo %s/bar", {EV_(MOVED, "foo", "bar"), END}}, | |
{"rm %s/bar", {EV_(DELETED, "bar", NULL), END}}, | |
{"touch %s/baz", {EV_(CREATED, "baz", NULL), END}}, | |
{"mv %s/baz %s/bazz", {EV_(MOVED, "baz", "bazz"), END}}, | |
{"rm %s/bazz", {EV_(DELETED, "bazz", NULL), END}}, | |
{"mkdir %s/dir", {EV_(CREATED, "dir", NULL), END}}, | |
{"rmdir %s/dir", {EV_(DELETED, "dir", NULL), END}}, | |
{"mv %s gfmt-dt-moved", {EV_(MOVED, SELF, NULL), END}}, | |
{"rm -rf gfmt-dt-moved", {EV_(DELETED, SELF, NULL), END}}, | |
}; | |
test_case move_test_cases[] = { | |
{"mkdir %s", {EV_(CREATED, SELF, NULL), END}}, | |
{"touch %s/foo", {EV_(CREATED, "foo", NULL), END}}, | |
{"mv %s/foo %s/bar", {EV_(DELETED, "foo", NULL), EV_(CREATED, "bar", NULL), END}}, | |
{"rm %s/bar", {EV_(DELETED, "bar", NULL), END}}, | |
{"rm -rf %s", {EV_(DELETED, SELF, NULL), END}}, | |
}; | |
test test_suite[] = { | |
{ "File test", | |
"gfmt-test", | |
G_FILE_MONITOR_SEND_MOVED, | |
file_test_cases, | |
G_N_ELEMENTS (file_test_cases) | |
}, | |
{"Directory test", | |
"gfmt-testdir", | |
G_FILE_MONITOR_SEND_MOVED, | |
dir_test_cases, | |
G_N_ELEMENTS (dir_test_cases) | |
}, | |
{"Movements test", | |
"gfmt-movedir", | |
G_FILE_MONITOR_NONE, | |
move_test_cases, | |
G_N_ELEMENTS (move_test_cases) | |
}, | |
}; | |
int | |
main (int argc, char *argv[]) | |
{ | |
g_type_init (); | |
g_thread_init (NULL); | |
g_printf ("Starting tests for Glib %d.%d.%d...\n", | |
GLIB_MAJOR_VERSION, | |
GLIB_MINOR_VERSION, | |
GLIB_MICRO_VERSION); | |
run_suite (test_suite, G_N_ELEMENTS(test_suite)); | |
loop = g_main_loop_new (NULL, FALSE); | |
g_main_loop_run (loop); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment