Merge lp:~rainct/nautilus/nautilus-zg into lp:~rainct/nautilus/nautilus-orig

Proposed by Siegfried Gevatter
Status: Needs review
Proposed branch: lp:~rainct/nautilus/nautilus-zg
Merge into: lp:~rainct/nautilus/nautilus-orig
Diff against target: 740 lines (+613/-1)
6 files modified
libnautilus-private/Makefile.am (+2/-0)
libnautilus-private/nautilus-file-operations.c (+184/-0)
libnautilus-private/nautilus-file.c (+28/-1)
test/Makefile.am (+6/-0)
test/run-zeitgeist-test.sh (+50/-0)
test/test-nautilus-zeitgeist.c (+343/-0)
To merge this branch: bzr merge lp:~rainct/nautilus/nautilus-zg
Reviewer Review Type Date Requested Status
Sebastien Bacher (community) Needs Fixing
Michal Hruby (community) Approve
Mikkel Kamstrup Erlandsen (community) Needs Fixing
Siegfried Gevatter Pending
Review via email: mp+91505@code.launchpad.net
To post a comment you must log in.
Revision history for this message
Mikkel Kamstrup Erlandsen (kamstrup) wrote :

Really nice! :-)

95 + origin = g_path_get_dirname (uri);

This should be URI formatted I think.

200 + while (g_hash_table_iter_next (&iter, (void **) &file, (void **) &done)) {
201 + if (done) {
202 ...

It's not quite obvious what 'done' is or how it's used here..? Can you clarify?

I think you can just rely on the new libzg already and bump the configure check to 0.3.13 which is what trunk has to get rid of the fixmes.

I'll take it for a test spin monday.

review: Needs Fixing
Revision history for this message
Mikkel Kamstrup Erlandsen (kamstrup) wrote :

Oh - and can you attach it to a bug report against Nautilus please?

lp:~rainct/nautilus/nautilus-zg updated
273. By Siegfried Gevatter

Update for new libzg.

Revision history for this message
Siegfried Gevatter (rainct) wrote :

11:42 <RainCT> kamstrup: "g_path_get_dirname (uri)" I'm giving it an URI so it's supposed to work
11:42 <kamstrup> RainCT: ah, of course
11:43 <kamstrup> RainCT: should be fine as is

12:03 <RainCT> kamstrup: `done' is supposed to get the value of debuting_files[file] and it'll be TRUE if the operation was completed for the file
12:03 <kamstrup> ah, that way
12:04 <kamstrup> so you're filtering out stuff that didn't complete properly

lp:~rainct/nautilus/nautilus-zg updated
274. By Siegfried Gevatter

And let it compile even

Revision history for this message
Mikkel Kamstrup Erlandsen (kamstrup) wrote :

180 + gboolean *done;
181 + g_hash_table_iter_init (&iter, job->debuting_files);
182 + while (g_hash_table_iter_next (&iter, (void **) &file, (void **) &done)) {

Woopsiedaisy... This looks like a stackoverflow on 64 bit... A pointer to a pointer to a gboolean. I think you must declare 'done' without the asterisk ;-)

You have this error one other place as well.

review: Needs Fixing
lp:~rainct/nautilus/nautilus-zg updated
275. By Siegfried Gevatter

change gboolean* -> gboolean

276. By Siegfried Gevatter

Start working on tests.

277. By Siegfried Gevatter

Tests are working! Now we just need to add some more.

278. By Siegfried Gevatter

Add more tests! \o/

279. By Siegfried Gevatter

remove thing

Revision history for this message
Siegfried Gevatter (rainct) wrote :

Added test cases!

Revision history for this message
Michal Hruby (mhr3) wrote :

43 + zeitgeist_log_insert_events_no_reply (log, event, NULL);

Is this running in the main thread or some worker?

182 + while (g_hash_table_iter_next (&iter, (void **) &file, (void **) &done)) {

Why the (void**) cast?

Nice job on the tests, but could we use the dbus-test-runner now that it works?

review: Needs Information
lp:~rainct/nautilus/nautilus-zg updated
280. By Siegfried Gevatter

Minor changes (show debug, don't abort on warning, void**->gpointer*,
run Zeitgeist without FTS).

Revision history for this message
Siegfried Gevatter (rainct) wrote :

> Is this running in the main thread or some worker?
The Zeitgeist code is inside a g_io_scheduler_job_send_to_mainloop_async callback, so main.

> Why the (void**) cast?
Cause it's way more awesome than gpointer.

> Nice job on the tests, but could we use the dbus-test-runner now that it works?
Problem is someone eats the environment variables (to run Zeitgeist with temporary database). A way around this is launching zeitgeist-explicitly, but then it doesn't stop running until dbus-test-runner times out (30 sec).

Revision history for this message
Michal Hruby (mhr3) wrote :

All good then, approve from me.

review: Approve
Revision history for this message
Sebastien Bacher (seb128) wrote :

the tests/Makefile.am first change needs a trailing '\' on its line or that breaks the makefile and fails to build

review: Needs Fixing
Revision history for this message
Sebastien Bacher (seb128) wrote :

I've uploaded nautilus with that patch (with the previous issue fixed) to https://launchpad.net/~ubuntu-desktop/+archive/ppa for testing

lp:~rainct/nautilus/nautilus-zg updated
281. By Siegfried Gevatter

patch by mhr3

282. By Siegfried Gevatter

Fix by Chris Coulson

Revision history for this message
Sebastien Bacher (seb128) wrote :

just for the record bug #944624 is a segfault on 64 bit archs created by it

Chris Coulson fixed it:

nautilus (1:3.3.90-0ubuntu6) precise; urgency=low

  * Fix LP: #944624 - Don't stick a pointer to an int, as it causes stack
    corruption on 64-bit architectures

http://launchpadlibrarian.net/95198642/nautilus_1%3A3.3.90-0ubuntu5_1%3A3.3.90-0ubuntu6.diff.gz

Revision history for this message
Sebastien Bacher (seb128) wrote :

Siegfried, could you update the GNOME bug with the fixed version?

Revision history for this message
Sebastien Bacher (seb128) wrote :

bug #947489 (segfault in_log_zeitgeist_event_for_file_cb()) seems also due to this change

lp:~rainct/nautilus/nautilus-zg updated
283. By Siegfried Gevatter

Make sure data->original_uri isn't NULL before freeing it.

284. By Siegfried Gevatter

Initialize GError to NULL.

From http://developer.gnome.org/glib/2.31/glib-Error-Reporting.html:
 "A GError* must be initialized to NULL before passing its address to a
  function that can report errors."

Revision history for this message
Sebastien Bacher (seb128) wrote :

r284 is weird, it added diffs to quite some autogenerated files?

lp:~rainct/nautilus/nautilus-zg updated
285. By Siegfried Gevatter

Revert accidentally committed changes

Revision history for this message
Sebastien Bacher (seb128) wrote :

r282 is weird

- while (g_hash_table_iter_next (&iter, (void **) &file, (void **) &done)) {
+ while (g_hash_table_iter_next (&iter, (void **) &file, done)) {

did you really mean to change &done to done?

lp:~rainct/nautilus/nautilus-zg updated
286. By Siegfried Gevatter

fix typo

Revision history for this message
Siegfried Gevatter (rainct) wrote :

Not really, 282 is supposed to be Chris' changes. Sorry.

Revision history for this message
Sebastien Bacher (seb128) wrote :

thanks, r286 has that now:

-if (data->original_uri) g_free (data->original_uri);
+g_free (data->original_uri);

seems to revert a null check fix from a previous revision? wanted?

lp:~rainct/nautilus/nautilus-zg updated
287. By Siegfried Gevatter

Revert r283, dunno what I was doing there.

So, the only change since Chris' is initializing the GError.

Revision history for this message
Michal Hruby (mhr3) wrote :

> thanks, r286 has that now:
>
> -if (data->original_uri) g_free (data->original_uri);
> +g_free (data->original_uri);
>
> seems to revert a null check fix from a previous revision? wanted?

FWIW g_free is NULL-safe, so it doesn't matter.

Revision history for this message
Sebastien Bacher (seb128) wrote :

could somebody set that one as merge or rejected? it got in but the vcs used is wrong

Unmerged revisions

287. By Siegfried Gevatter

Revert r283, dunno what I was doing there.

So, the only change since Chris' is initializing the GError.

286. By Siegfried Gevatter

fix typo

285. By Siegfried Gevatter

Revert accidentally committed changes

284. By Siegfried Gevatter

Initialize GError to NULL.

From http://developer.gnome.org/glib/2.31/glib-Error-Reporting.html:
 "A GError* must be initialized to NULL before passing its address to a
  function that can report errors."

283. By Siegfried Gevatter

Make sure data->original_uri isn't NULL before freeing it.

282. By Siegfried Gevatter

Fix by Chris Coulson

281. By Siegfried Gevatter

patch by mhr3

280. By Siegfried Gevatter

Minor changes (show debug, don't abort on warning, void**->gpointer*,
run Zeitgeist without FTS).

279. By Siegfried Gevatter

remove thing

278. By Siegfried Gevatter

Add more tests! \o/

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'libnautilus-private/Makefile.am'
2--- libnautilus-private/Makefile.am 2012-02-02 12:48:30 +0000
3+++ libnautilus-private/Makefile.am 2012-03-08 17:15:43 +0000
4@@ -12,6 +12,7 @@
5 $(WARNING_CFLAGS) \
6 $(DISABLE_DEPRECATED_CFLAGS) \
7 $(TRACKER_CFLAGS) \
8+ `pkg-config --cflags zeitgeist-1.0` \
9 -DDATADIR=\""$(datadir)"\" \
10 -DSYSCONFDIR=\""$(sysconfdir)"\" \
11 -DNAUTILUS_DATADIR=\""$(datadir)/nautilus"\" \
12@@ -44,6 +45,7 @@
13
14 libnautilus_private_la_LDFLAGS = \
15 -no-undefined \
16+ `pkg-config --libs zeitgeist-1.0` \
17 $(NULL)
18
19 libnautilus_private_la_LIBADD = \
20
21=== modified file 'libnautilus-private/nautilus-file-operations.c'
22--- libnautilus-private/nautilus-file-operations.c 2012-02-02 12:48:30 +0000
23+++ libnautilus-private/nautilus-file-operations.c 2012-03-08 17:15:43 +0000
24@@ -64,6 +64,8 @@
25 #include "nautilus-file-utilities.h"
26 #include "nautilus-file-conflict-dialog.h"
27
28+#include <zeitgeist.h>
29+
30 /* TODO: TESTING!!! */
31
32 typedef struct {
33@@ -189,6 +191,104 @@
34 #define MERGE_ALL _("Merge _All")
35 #define COPY_FORCE _("Copy _Anyway")
36
37+#define ZEITGEIST_NAUTILUS_ACTOR "application://nautilus.desktop"
38+
39+static void
40+send_event_to_zeitgeist (ZeitgeistEvent *event)
41+{
42+ ZeitgeistLog *log = zeitgeist_log_get_default ();
43+ zeitgeist_log_insert_events_no_reply (log, event, NULL);
44+}
45+
46+typedef struct {
47+ const char *event_interpretation;
48+ //char *event_origin;
49+ GFile *file;
50+ gchar *original_uri; // for MOVE_EVENT
51+} _ZeitgeistFileEventData;
52+
53+static void
54+_log_zeitgeist_event_for_file_cb (GObject *source_object,
55+ GAsyncResult *res, gpointer user_data)
56+{
57+ _ZeitgeistFileEventData *data;
58+ GError *error;
59+ GFileInfo *info;
60+ gchar *uri;
61+ gchar *origin;
62+ const gchar *display_name;
63+ const gchar *mimetype;
64+
65+ data = user_data;
66+
67+ error = NULL;
68+ info = g_file_query_info_finish (G_FILE (source_object), res, &error);
69+
70+ if (info) {
71+ uri = g_file_get_uri (data->file);
72+ origin = g_path_get_dirname (uri);
73+ display_name = g_file_info_get_display_name (info);
74+ mimetype = g_file_info_get_content_type (info);
75+ } else {
76+ g_warning ("Error getting info: %s\n", error->message);
77+ g_error_free (error);
78+ g_object_unref (data->file);
79+ g_free (data->original_uri);
80+ g_free (data);
81+ return; // skip this event
82+ }
83+
84+ ZeitgeistSubject *subject = zeitgeist_subject_new_full (
85+ (data->original_uri) ? (data->original_uri) : uri,
86+ NULL, // subject interpretation - auto-guess
87+ NULL, // suject manifestation - auto-guess
88+ mimetype,
89+ origin,
90+ display_name,
91+ NULL // storage - auto-guess
92+ );
93+
94+ if (data->original_uri)
95+ zeitgeist_subject_set_current_uri (subject, uri);
96+
97+ g_free (uri);
98+ g_free (origin);
99+ g_object_unref (info);
100+
101+ if (subject) {
102+ ZeitgeistEvent *event = zeitgeist_event_new_full (
103+ data->event_interpretation,
104+ ZEITGEIST_ZG_USER_ACTIVITY,
105+ ZEITGEIST_NAUTILUS_ACTOR,
106+ subject, NULL);
107+ send_event_to_zeitgeist (event);
108+ }
109+
110+ g_object_unref (data->file);
111+ g_free (data->original_uri);
112+ g_free (data);
113+}
114+
115+static void
116+log_zeitgeist_event_for_file_no_reply (const char *event_interpretation,
117+ GFile *file, gchar *original_uri)
118+{
119+ _ZeitgeistFileEventData *data;
120+ data = g_new0 (_ZeitgeistFileEventData, 1);
121+
122+ data->event_interpretation = event_interpretation;
123+ data->original_uri = original_uri;
124+ data->file = file;
125+
126+ g_file_query_info_async (file,
127+ G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME ","
128+ G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE,
129+ G_FILE_QUERY_INFO_NONE,
130+ G_PRIORITY_DEFAULT,
131+ NULL,
132+ _log_zeitgeist_event_for_file_cb, data);
133+}
134+
135 static void
136 mark_desktop_file_trusted (CommonJob *common,
137 GCancellable *cancellable,
138@@ -1835,6 +1935,35 @@
139
140 job = user_data;
141
142+ // Send event to Zeitgeist for deletions/trash
143+ GList *file_iter = job->files;
144+ while (file_iter != NULL) {
145+ gchar *uri = g_file_get_uri (file_iter->data);
146+ gchar *origin = g_path_get_dirname (uri);
147+ gchar *parse_name = g_file_get_parse_name (file_iter->data);
148+ gchar *display_name = g_path_get_basename (parse_name);
149+ ZeitgeistEvent *event = zeitgeist_event_new_full (
150+ ZEITGEIST_ZG_DELETE_EVENT,
151+ ZEITGEIST_ZG_USER_ACTIVITY,
152+ ZEITGEIST_NAUTILUS_ACTOR,
153+ zeitgeist_subject_new_full (
154+ uri,
155+ NULL, // subject interpretation - auto-guess
156+ NULL, // suject manifestation - auto-guess
157+ NULL, // mime-type
158+ origin,
159+ display_name,
160+ NULL // storage - auto-guess
161+ ), NULL);
162+ send_event_to_zeitgeist (event);
163+ g_free (uri);
164+ g_free (origin);
165+ g_free (parse_name);
166+ g_free (display_name);
167+ file_iter = g_list_next (file_iter);
168+ }
169+ // ---
170+
171 g_list_free_full (job->files, g_object_unref);
172
173 if (job->done_callback) {
174@@ -4433,6 +4562,23 @@
175 job->done_callback (job->debuting_files, job->done_callback_data);
176 }
177
178+ // Send event to Zeitgeist
179+ GHashTableIter iter;
180+ GFile *file;
181+ gpointer done;
182+ g_hash_table_iter_init (&iter, job->debuting_files);
183+ while (g_hash_table_iter_next (&iter, (gpointer *) &file, &done)) {
184+ if (GPOINTER_TO_INT (done)) {
185+ // operation was completed successfully for this file
186+ g_object_ref (file);
187+ // FIXME: Set event origin to the original file URI, if we
188+ // can somehow figure out which one it is.
189+ log_zeitgeist_event_for_file_no_reply (
190+ ZEITGEIST_ZG_CREATE_EVENT, file, NULL);
191+ }
192+ }
193+ // ---
194+
195 g_list_free_full (job->files, g_object_unref);
196 if (job->destination) {
197 g_object_unref (job->destination);
198@@ -4978,6 +5124,19 @@
199 job->done_callback (job->debuting_files, job->done_callback_data);
200 }
201
202+ // Send event to Zeitgeist for moved files (not renaming)
203+ GList *file_iter = job->files;
204+ while (file_iter != NULL) {
205+ char *basename = g_file_get_basename (file_iter->data);
206+ GFile *new_file = g_file_get_child (job->destination, basename);
207+ g_free (basename);
208+
209+ log_zeitgeist_event_for_file_no_reply (ZEITGEIST_ZG_MOVE_EVENT,
210+ new_file, g_file_get_uri (file_iter->data));
211+ file_iter = g_list_next (file_iter);
212+ }
213+ // ---
214+
215 g_list_free_full (job->files, g_object_unref);
216 g_object_unref (job->destination);
217 g_hash_table_unref (job->debuting_files);
218@@ -5295,6 +5454,23 @@
219 job->done_callback (job->debuting_files, job->done_callback_data);
220 }
221
222+ // Send event to Zeitgeist
223+ GHashTableIter iter;
224+ GFile *file;
225+ gpointer done;
226+ g_hash_table_iter_init (&iter, job->debuting_files);
227+ while (g_hash_table_iter_next (&iter, (gpointer *) &file, &done)) {
228+ if (GPOINTER_TO_INT (done)) {
229+ // operation was completed successfully for this file
230+ g_object_ref (file);
231+ // FIXME: Set event origin to the original file URI, if we
232+ // can somehow figure out which one it is.
233+ log_zeitgeist_event_for_file_no_reply (
234+ ZEITGEIST_ZG_CREATE_EVENT, file, NULL);
235+ }
236+ }
237+ // ---
238+
239 g_list_free_full (job->files, g_object_unref);
240 g_object_unref (job->destination);
241 g_hash_table_unref (job->debuting_files);
242@@ -5726,6 +5902,14 @@
243 job->done_callback (job->created_file, job->done_callback_data);
244 }
245
246+ // Send event to Zeitgeist
247+ if (job->created_file) {
248+ g_object_ref (job->created_file);
249+ log_zeitgeist_event_for_file_no_reply (
250+ ZEITGEIST_ZG_CREATE_EVENT, job->created_file, NULL);
251+ }
252+ // ---
253+
254 g_object_unref (job->dest_dir);
255 if (job->src) {
256 g_object_unref (job->src);
257
258=== modified file 'libnautilus-private/nautilus-file.c'
259--- libnautilus-private/nautilus-file.c 2012-02-02 12:48:30 +0000
260+++ libnautilus-private/nautilus-file.c 2012-03-08 17:15:43 +0000
261@@ -88,6 +88,9 @@
262 #define DEBUG_REF_PRINTF printf
263 #endif
264
265+#include <zeitgeist.h>
266+#define ZEITGEIST_NAUTILUS_ACTOR "application://nautilus.desktop"
267+
268 /* Files that start with these characters sort after files that don't. */
269 #define SORT_LAST_CHAR1 '.'
270 #define SORT_LAST_CHAR2 '#'
271@@ -1721,10 +1724,34 @@
272 old_name = g_strdup (eel_ref_str_peek (op->file->details->name));
273
274 update_info_and_name (op->file, new_info);
275-
276+
277 g_free (old_name);
278
279 new_uri = nautilus_file_get_uri (op->file);
280+
281+ // Send event to Zeitgeist
282+ ZeitgeistLog *log = zeitgeist_log_get_default ();
283+ gchar *origin = g_path_get_dirname (new_uri);
284+ ZeitgeistSubject *subject = zeitgeist_subject_new_full (
285+ old_uri,
286+ NULL, // subject interpretation - auto-guess
287+ NULL, // subject manifestation - auto-guess
288+ g_file_info_get_content_type (new_info), // const char*
289+ origin,
290+ new_name,
291+ NULL // storage - auto-guess
292+ );
293+ zeitgeist_subject_set_current_uri (subject, new_uri);
294+ g_free (origin);
295+ // FIXME: zeitgeist_subject_set_current_uri ();
296+ ZeitgeistEvent *event = zeitgeist_event_new_full (
297+ ZEITGEIST_ZG_MOVE_EVENT,
298+ ZEITGEIST_ZG_USER_ACTIVITY,
299+ ZEITGEIST_NAUTILUS_ACTOR,
300+ subject, NULL);
301+ zeitgeist_log_insert_events_no_reply (log, event, NULL);
302+ // ---
303+
304 nautilus_directory_moved (old_uri, new_uri);
305 g_free (new_uri);
306 g_free (old_uri);
307
308=== modified file 'test/Makefile.am'
309--- test/Makefile.am 2011-05-16 18:53:51 +0000
310+++ test/Makefile.am 2012-03-08 17:15:43 +0000
311@@ -6,6 +6,7 @@
312 $(COMMON_CFLAGS) \
313 $(NAUTILUS_CFLAGS) \
314 $(WARNING_CFLAGS) \
315+ `pkg-config --cflags zeitgeist-1.0` \
316 -DVERSION="\"$(VERSION)\"" \
317 -DNAUTILUS_DATADIR=\""$(datadir)/nautilus"\" \
318 -DGNOMELOCALEDIR=\""$(prefix)/${DATADIRNAME}/locale"\" \
319@@ -22,6 +23,7 @@
320 test-nautilus-search-engine \
321 test-nautilus-directory-async \
322 test-nautilus-copy \
323+ test-nautilus-zeitgeist \
324 test-eel-editable-label \
325 $(NULL)
326
327@@ -31,6 +33,10 @@
328
329 test_nautilus_directory_async_SOURCES = test-nautilus-directory-async.c
330
331+test_nautilus_zeitgeist_SOURCES = test-nautilus-zeitgeist.c
332+
333+test_nautilus_zeitgeist_LDCONFIG = `pkg-config --libs zeitgeist-1.0`
334+
335 EXTRA_DIST = \
336 test.h \
337 $(NULL)
338
339=== added file 'test/run-zeitgeist-test.sh'
340--- test/run-zeitgeist-test.sh 1970-01-01 00:00:00 +0000
341+++ test/run-zeitgeist-test.sh 2012-03-08 17:15:43 +0000
342@@ -0,0 +1,50 @@
343+#! /bin/sh -e
344+
345+#echo "Building..."
346+#gcc test-nautilus-zeitgeist.c -o test-nautilus-zeitgeist \
347+# ../libnautilus-private/nautilus-file-operations.c \
348+# `pkg-config --cflags --libs glib-2.0 gtk+-3.0 zeitgeist-1.0` -I.. \
349+[ "`basename $(pwd)`" = "test" ] || echo "Please cd into test/"
350+[ "`basename $(pwd)`" = "test" ] || exit
351+make
352+
353+echo "Configuring environment..."
354+
355+TMP_PATH="/tmp/nautilus-zg-test"
356+
357+rm -rf "${TMP_PATH}"
358+mkdir -p "${TMP_PATH}/cache"
359+
360+# Launching Zeitgeist
361+export ZEITGEIST_DATA_PATH="${TMP_PATH}"
362+export ZEITGEIST_DATABASE_PATH=":memory:"
363+export ZEITGEIST_DISABLED_EXTENSIONS="SearchEngine"
364+export XDG_CACHE_HOME="${TMP_PATH}/cache"
365+zeitgeist-daemon --replace --no-datahub >/dev/null 2>&1 &
366+
367+echo "Creating files to be used by the tests..."
368+
369+# test_copy_move
370+mkdir "${TMP_PATH}/move_dest"
371+touch "${TMP_PATH}/moveme.txt"
372+
373+# test_copy and test_new_file_from_template
374+echo "#! /usr/bin/env python\nprint 'hi!'" > "${TMP_PATH}/a.py"
375+
376+# test_delete
377+touch "${TMP_PATH}/del1.txt" "${TMP_PATH}/del2.txt"
378+
379+echo "Testing..."
380+export G_MESSAGES_DEBUG=all
381+#dbus-test-runner \
382+# --task zeitgeist-daemon \
383+# --parameter --no-datahub \
384+# --parameter --log-level=DEBUG \
385+# --task gtester \
386+# --parameter --verbose \
387+# --parameter ./test-nautilus-zeitgeist
388+./test-nautilus-zeitgeist
389+
390+echo "Cleaning up..."
391+zeitgeist-daemon --quit
392+rm -r "${TMP_PATH}"
393
394=== added file 'test/test-nautilus-zeitgeist.c'
395--- test/test-nautilus-zeitgeist.c 1970-01-01 00:00:00 +0000
396+++ test/test-nautilus-zeitgeist.c 2012-03-08 17:15:43 +0000
397@@ -0,0 +1,343 @@
398+/*
399+ * Copyright © 2012 Canonical Ltd.
400+ * By Siegfried-A. Gevatter <siegfried.gevatter@collabora.co.uk>
401+ *
402+ * License: GPLv2+
403+ *
404+ * The tests in this file require that certain directories and files exist
405+ * in order to operate on them. Please use ./run-zeitgeist-test.sh to launch
406+ * this test, since it'll create them for you (in a temporary directory).
407+ *
408+ * */
409+
410+#include <glib.h>
411+#include <glib-object.h>
412+#include <zeitgeist.h>
413+#include <string.h>
414+
415+#include <libnautilus-private/nautilus-file-operations.h>
416+
417+// After doing a file operation and before checking Zeitgeist for
418+// events, we needed to give Nautilus some time to insert the events
419+// (because of g_file_query_info, etc).
420+#define SLEEP_TIME 400
421+
422+// Test location
423+#define TEST_PATH "/tmp/nautilus-zg-test"
424+#define TEST_URI "file://" TEST_PATH
425+
426+typedef struct
427+{
428+ ZeitgeistLog *log;
429+ GMainLoop *mainloop;
430+ ZeitgeistTimeRange *query_time_range;
431+ GPtrArray *expected_events;
432+ guint num_expected_events;
433+} Fixture;
434+
435+static void
436+setup_test (Fixture *fix, gconstpointer data)
437+{
438+ fix->log = zeitgeist_log_new ();
439+ fix->mainloop = g_main_loop_new (NULL, FALSE);
440+ fix->query_time_range = zeitgeist_time_range_new_from_now ();
441+ fix->expected_events = g_ptr_array_new_with_free_func (
442+ (GDestroyNotify) g_object_unref);
443+ fix->num_expected_events = 0;
444+}
445+
446+static void teardown (Fixture *fix, gconstpointer data)
447+{
448+ g_object_unref (fix->log);
449+ g_object_unref (fix->query_time_range);
450+ g_ptr_array_free (fix->expected_events, TRUE);
451+ g_main_loop_unref (fix->mainloop);
452+
453+ fix->log = NULL;
454+ fix->mainloop = NULL;
455+ fix->query_time_range = NULL;
456+ fix->expected_events = NULL;
457+}
458+
459+static void
460+test_add_event_assertion (Fixture *fix,
461+ const char *event_interpretation, const char *uri, const char *current_uri,
462+ const char *origin, const char *text, const char *mimetype)
463+{
464+ // Create subject template
465+ ZeitgeistSubject *subject_template = zeitgeist_subject_new_full (
466+ uri, NULL, NULL, mimetype, origin, text, NULL);
467+ zeitgeist_subject_set_current_uri (subject_template, current_uri);
468+
469+ // Create event template
470+ ZeitgeistEvent *event_template = zeitgeist_event_new_full (
471+ event_interpretation, ZEITGEIST_ZG_USER_ACTIVITY, NULL,
472+ subject_template, NULL);
473+
474+ // Add event template to the fixture for later verification
475+ g_ptr_array_add (fix->expected_events, (gpointer) event_template);
476+ fix->num_expected_events++;
477+}
478+
479+static void
480+assert_event_matches_template (ZeitgeistEvent *event, ZeitgeistEvent *tmpl)
481+{
482+ int i;
483+ int num_subjects = zeitgeist_event_num_subjects (tmpl);
484+
485+ g_assert_cmpstr (zeitgeist_event_get_interpretation (event), ==,
486+ zeitgeist_event_get_interpretation (tmpl));
487+ g_assert_cmpstr (zeitgeist_event_get_manifestation (event), ==,
488+ zeitgeist_event_get_manifestation (tmpl));
489+ g_assert_cmpint (zeitgeist_event_num_subjects (event), ==, num_subjects);
490+
491+ for (i = 0; i < num_subjects; ++i)
492+ {
493+ ZeitgeistSubject *subject = zeitgeist_event_get_subject (event, i);
494+ ZeitgeistSubject *subj_templ = zeitgeist_event_get_subject (tmpl, i);
495+
496+ g_assert_cmpstr (zeitgeist_subject_get_uri (subject), ==,
497+ zeitgeist_subject_get_uri (subj_templ));
498+ g_assert_cmpstr (zeitgeist_subject_get_current_uri (subject), ==,
499+ zeitgeist_subject_get_current_uri (subj_templ));
500+ g_assert_cmpstr (zeitgeist_subject_get_origin (subject), ==,
501+ zeitgeist_subject_get_origin (subj_templ));
502+ g_assert_cmpstr (zeitgeist_subject_get_text (subject), ==,
503+ zeitgeist_subject_get_text (subj_templ));
504+ g_assert_cmpstr (zeitgeist_subject_get_mimetype (subject), ==,
505+ zeitgeist_subject_get_mimetype (subj_templ));
506+ }
507+}
508+
509+static void
510+assert_results_as_expected (Fixture *fix, ZeitgeistResultSet *results)
511+{
512+ int i;
513+
514+ g_assert_cmpint (zeitgeist_result_set_size (results), ==,
515+ fix->num_expected_events);
516+
517+ for (i = 0; i < fix->num_expected_events; ++i)
518+ {
519+ ZeitgeistEvent *event = zeitgeist_result_set_next (results);
520+ ZeitgeistEvent *tmpl = g_ptr_array_index (fix->expected_events, i);
521+ assert_event_matches_template (event, tmpl);
522+ }
523+}
524+
525+static void
526+_zeitgeist_test_cb2 (ZeitgeistLog *log, GAsyncResult *res, Fixture *fix)
527+{
528+ GError *error = NULL;
529+ ZeitgeistResultSet *results = zeitgeist_log_find_events_finish (
530+ log, res, &error);
531+ if (error)
532+ {
533+ g_warning ("Error with FindEventIds: %s", error->message);
534+ g_error_free (error);
535+ g_assert_not_reached ();
536+ }
537+
538+ assert_results_as_expected (fix, results);
539+ g_object_unref (results);
540+
541+ g_main_loop_quit (fix->mainloop);
542+}
543+
544+static gboolean
545+_zeitgeist_test_cb1 (Fixture *fix)
546+{
547+ zeitgeist_log_find_events (fix->log,
548+ fix->query_time_range,
549+ g_ptr_array_new (),
550+ ZEITGEIST_STORAGE_STATE_ANY,
551+ 50,
552+ ZEITGEIST_RESULT_TYPE_MOST_RECENT_EVENTS,
553+ NULL,
554+ (GAsyncReadyCallback) _zeitgeist_test_cb2,
555+ fix);
556+
557+ return FALSE;
558+}
559+
560+static void
561+zeitgeist_test_start (GHashTable *debuting_uris, Fixture *fix)
562+{
563+ g_timeout_add (SLEEP_TIME, (GSourceFunc) _zeitgeist_test_cb1, (gpointer) fix);
564+}
565+
566+static void
567+zeitgeist_test_start_3 (GHashTable *debuting_uris, gboolean user_cancel,
568+ gpointer callback_data)
569+{
570+ zeitgeist_test_start (debuting_uris, callback_data);
571+}
572+
573+static void
574+test_copy_move (Fixture *fix, gconstpointer data)
575+{
576+ test_add_event_assertion (fix, ZEITGEIST_ZG_MOVE_EVENT,
577+ TEST_URI "/moveme.txt",
578+ TEST_URI "/move_dest/moveme.txt",
579+ TEST_URI "/move_dest",
580+ "moveme.txt",
581+ "text/plain");
582+
583+ GList *item_uris = NULL;
584+ item_uris = g_list_prepend (item_uris,
585+ TEST_URI "/moveme.txt");
586+
587+ nautilus_file_operations_copy_move (
588+ item_uris,
589+ NULL,
590+ TEST_URI "/move_dest",
591+ GDK_ACTION_MOVE,
592+ NULL,
593+ (NautilusCopyCallback) zeitgeist_test_start,
594+ fix);
595+
596+ g_main_loop_run (fix->mainloop);
597+}
598+
599+static void
600+test_copy (Fixture *fix, gconstpointer data)
601+{
602+ test_add_event_assertion (fix, ZEITGEIST_ZG_CREATE_EVENT,
603+ TEST_URI "/b.py",
604+ TEST_URI "/b.py",
605+ TEST_URI,
606+ "b.py",
607+ "text/x-python");
608+
609+ nautilus_file_operations_copy_file (
610+ g_file_new_for_path (TEST_PATH "/a.py"),
611+ g_file_new_for_path (TEST_PATH),
612+ "a.py", "b.py",
613+ NULL,
614+ (NautilusCopyCallback) zeitgeist_test_start,
615+ fix);
616+
617+ g_main_loop_run (fix->mainloop);
618+}
619+
620+static void
621+test_new_folder (Fixture *fix, gconstpointer data)
622+{
623+ test_add_event_assertion (fix, ZEITGEIST_ZG_CREATE_EVENT,
624+ TEST_URI "/Untitled%20Folder",
625+ TEST_URI "/Untitled%20Folder",
626+ TEST_URI,
627+ "Untitled Folder",
628+ "inode/directory");
629+
630+ nautilus_file_operations_new_folder (
631+ NULL, NULL,
632+ TEST_URI,
633+ (NautilusCopyCallback) zeitgeist_test_start,
634+ fix);
635+
636+ g_main_loop_run (fix->mainloop);
637+}
638+
639+static void
640+test_new_file (Fixture *fix, gconstpointer data)
641+{
642+ test_add_event_assertion (fix, ZEITGEIST_ZG_CREATE_EVENT,
643+ TEST_URI "/new_file_test.txt",
644+ TEST_URI "/new_file_test.txt",
645+ TEST_URI,
646+ "new_file_test.txt",
647+ "text/plain");
648+
649+ const char content[] = "this is the content of a text file...\n";
650+ nautilus_file_operations_new_file (
651+ NULL, NULL,
652+ TEST_URI,
653+ "new_file_test.txt",
654+ content, strlen (content),
655+ (NautilusCopyCallback) zeitgeist_test_start,
656+ fix);
657+
658+ g_main_loop_run (fix->mainloop);
659+}
660+
661+static void
662+test_new_file_from_template (Fixture *fix, gconstpointer data)
663+{
664+ test_add_event_assertion (fix, ZEITGEIST_ZG_CREATE_EVENT,
665+ TEST_URI "/new_tpl_file_test.py",
666+ TEST_URI "/new_tpl_file_test.py",
667+ TEST_URI,
668+ "new_tpl_file_test.py",
669+ "text/x-python");
670+
671+ nautilus_file_operations_new_file_from_template (
672+ NULL, NULL,
673+ TEST_URI,
674+ "new_tpl_file_test.py",
675+ TEST_URI "/a.py",
676+ (NautilusCopyCallback) zeitgeist_test_start,
677+ fix);
678+
679+ g_main_loop_run (fix->mainloop);
680+}
681+
682+static void
683+test_delete (Fixture *fix, gconstpointer data)
684+{
685+ test_add_event_assertion (fix, ZEITGEIST_ZG_DELETE_EVENT,
686+ TEST_URI "/del1.txt",
687+ TEST_URI "/del1.txt",
688+ TEST_URI,
689+ "del1.txt",
690+ NULL);
691+ test_add_event_assertion (fix, ZEITGEIST_ZG_DELETE_EVENT,
692+ TEST_URI "/del2.txt",
693+ TEST_URI "/del2.txt",
694+ TEST_URI,
695+ "del2.txt",
696+ NULL);
697+
698+ GList *file_list = NULL;
699+ file_list = g_list_prepend (file_list,
700+ g_file_new_for_path (TEST_PATH "/del1.txt"));
701+ file_list = g_list_prepend (file_list,
702+ g_file_new_for_path (TEST_PATH "/del2.txt"));
703+
704+ // Nautilus_file_operations_trash_or_delete is exactly the same
705+ // NOTE: This operation will ask for manual confirmation of the delete.
706+ // There isn't really any nice way around this :(.
707+ nautilus_file_operations_delete (
708+ file_list,
709+ NULL,
710+ (NautilusDeleteCallback) zeitgeist_test_start_3,
711+ fix);
712+
713+ g_main_loop_run (fix->mainloop);
714+}
715+
716+int
717+main (int argc, char* argv[])
718+{
719+ g_type_init ();
720+
721+ g_test_init (&argc, &argv, NULL);
722+ gtk_init (&argc, &argv);
723+
724+ g_log_set_always_fatal (G_LOG_LEVEL_CRITICAL);
725+
726+ g_test_add ("/Zeitgeist/CopyMove", Fixture, 0,
727+ setup_test, test_copy_move, teardown);
728+ g_test_add ("/Zeitgeist/Copy", Fixture, 0,
729+ setup_test, test_copy, teardown);
730+ g_test_add ("/Zeitgeist/NewFolder", Fixture, 0,
731+ setup_test, test_new_folder, teardown);
732+ g_test_add ("/Zeitgeist/NewFile", Fixture, 0,
733+ setup_test, test_new_file, teardown);
734+ g_test_add ("/Zeitgeist/NewFileFromTemplate", Fixture, 0,
735+ setup_test, test_new_file_from_template, teardown);
736+ g_test_add ("/Zeitgeist/Delete", Fixture, 0,
737+ setup_test, test_delete, teardown);
738+
739+ return g_test_run ();
740+}

Subscribers

People subscribed via source and target branches