[tracker/wip/removable-device-completed: 9/11] tests: Add GIO module to generate fake removable devices
- From: Sam Thursfield <sthursfield src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [tracker/wip/removable-device-completed: 9/11] tests: Add GIO module to generate fake removable devices
- Date: Fri, 22 Jun 2012 17:29:49 +0000 (UTC)
commit 19f845b7dab450aee6d2b19153eec5b832b6ca42
Author: Sam Thursfield <sam thursfield codethink co uk>
Date: Mon May 28 12:03:56 2012 +0900
tests: Add GIO module to generate fake removable devices
tracker-test-volume-monitor is a GIO module that can be loaded via
GIO_EXTRA_MODULES in the environment and will expose fake removable
devices.
tracker-test-mount-service is a D-Bus service that controls all of the
test volume monitors within a D-Bus session. This allows the
functional tests to simulate removable devices without needing any
hooks inside the actual Tracker processes.
tests/common/Makefile.am | 22 ++-
tests/common/tracker-test-mount-service.vala | 129 ++++++++++
tests/common/tracker-test-volume-monitor.vala | 316 +++++++++++++++++++++++++
utils/tracker-sandbox | 7 +
4 files changed, 473 insertions(+), 1 deletions(-)
---
diff --git a/tests/common/Makefile.am b/tests/common/Makefile.am
index acca798..11b46ab 100644
--- a/tests/common/Makefile.am
+++ b/tests/common/Makefile.am
@@ -1,12 +1,27 @@
include $(top_srcdir)/Makefile.decl
-noinst_LTLIBRARIES = libtracker-testcommon.la
+# Don't install the test volume monitor into gio/modules or it will
+# be loaded system-wide ... would be better to not install it at all,
+# but it's used by the functional tests which operate on an installed
+# Tracker.
+moduledir = $(libdir)/tracker
+
+noinst_LTLIBRARIES = \
+ libtracker-testcommon.la
+
+module_LTLIBRARIES = \
+ libtracker-test-volume-monitor.la
+
+libexec_PROGRAMS = \
+ tracker-test-mounter-service
AM_CPPFLAGS = \
$(BUILD) \
-DTEST_TEXT=\""$(top_srcdir)"/tests/libtracker-common/non-utf8.txt\" \
$(LIBTRACKER_COMMON_CFLAGS)
+AM_VALAFLAGS = --pkg=gio-2.0 --pkg=gmodule-2.0 -g
+
LDADD = \
$(BUILD_LIBS) \
$(LIBTRACKER_COMMON_LIBS)
@@ -15,3 +30,8 @@ libtracker_testcommon_la_SOURCES = \
tracker-test-helpers.c \
tracker-test-helpers.h
+libtracker_test_volume_monitor_la_SOURCES = \
+ tracker-test-volume-monitor.vala
+
+tracker_test_mounter_service_SOURCES = \
+ tracker-test-mount-service.vala
diff --git a/tests/common/tracker-test-mount-service.vala b/tests/common/tracker-test-mount-service.vala
new file mode 100644
index 0000000..30613ed
--- /dev/null
+++ b/tests/common/tracker-test-mount-service.vala
@@ -0,0 +1,129 @@
+/*
+ * Copyright (C) 2012, Codethink Ltd <sam thursfield codethink co uk>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+/* A slightly overengineed method of implementing test mounts. It might be
+ * nicer if GVfs would support this directly, see:
+ * https://bugzilla.gnome.org/show_bug.cgi?id=659739
+ *
+ * Tests can run this daemon and use it to control the
+ * tracker-test-volume-monitor GIO module, creating fake mounts for all of the
+ * Tracker processes.
+ */
+
+using GLib;
+
+struct Tracker.TestMountInfo {
+ public string root_path;
+ public uint id;
+}
+
+[DBus (name="org.freedesktop.Tracker1.TestMounter")]
+public class Tracker.TestMountService {
+ List<TestMountInfo?> mount_list;
+ uint id_counter;
+
+ internal void on_bus_acquired (DBusConnection connection,
+ string name) {
+ try {
+ connection.register_object ("/org/freedesktop/Tracker1/TestMounter", this);
+ }
+ catch (IOError e) {
+ stderr.printf ("tracker-test-volume-monitor: Error exporting on bus: %s\n", e.message);
+ }
+ }
+
+ internal void on_name_acquired (DBusConnection connection,
+ string name) {
+ }
+
+ internal void on_name_lost (DBusConnection connection,
+ string name) {
+ stderr.printf ("tracker-test-volume-monitor: Unable to own bus name\n");
+ }
+
+ public Variant list_mounts () {
+ var result = new VariantBuilder ((VariantType) "a(su)");
+
+ foreach (var mount_info in this.mount_list)
+ result.add ("(su)", mount_info.root_path, mount_info.id);
+
+ return result.end();
+ }
+
+ private unowned List<TestMountInfo?>? find_mount_info_node (string root_path) {
+ for (unowned List<TestMountInfo?> l = this.mount_list; l != null; l = l.next) {
+ if (l.data.root_path == root_path)
+ return l;
+ }
+
+ return null;
+ }
+
+ public void mount (string root_path)
+ throws GLib.IOError {
+ unowned List<TestMountInfo?> node = this.find_mount_info_node (root_path);
+
+ if (node != null)
+ throw new IOError.ALREADY_MOUNTED ("Unable to mount %s: already mounted", root_path);
+
+ var mount_info = TestMountInfo ();
+
+ mount_info.root_path = root_path;
+ mount_info.id = this.id_counter ++;
+
+ this.mount_list.append (mount_info);
+
+ this.mount_added (mount_info.root_path, mount_info.id);
+ }
+
+ public void unmount (string root_path)
+ throws IOError {
+ unowned List<TestMountInfo?> node = this.find_mount_info_node (root_path);
+
+ if (node == null)
+ throw new IOError.NOT_MOUNTED ("Unable to unmount %s: not mounted", root_path);
+
+ var mount_info = node.data;
+
+ this.mount_list.remove_link (node);
+
+ this.mount_removed (mount_info.root_path);
+ }
+
+ public signal void mount_added (string root_path,
+ uint id);
+
+ public signal void mount_removed (string root_path);
+}
+
+public int main (string args[]) {
+ var loop = new MainLoop ();
+ var service = new Tracker.TestMountService ();
+
+ Bus.own_name (BusType.SESSION,
+ "org.freedesktop.Tracker1.TestMounter",
+ BusNameOwnerFlags.NONE,
+ service.on_bus_acquired,
+ service.on_name_acquired,
+ service.on_name_lost);
+
+ loop.run ();
+
+ return 0;
+}
diff --git a/tests/common/tracker-test-volume-monitor.vala b/tests/common/tracker-test-volume-monitor.vala
new file mode 100644
index 0000000..ee8b470
--- /dev/null
+++ b/tests/common/tracker-test-volume-monitor.vala
@@ -0,0 +1,316 @@
+/*
+ * Copyright (C) 2012, Codethink Ltd <sam thursfield codethink co uk>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+/* WARNING: due to issues in gio-2.0.vapi, this file is really hard to
+ * compile with Vala. See https://bugzilla.gnome.org/show_bug.cgi?id=677073
+ * for more information. Use either 0.15.0 or >= 0.17.1
+ */
+
+private class Tracker.TestMount: GLib.Mount, GLib.Object {
+ internal File root;
+ internal string root_path;
+ internal uint id;
+
+ public TestMount (string root_path,
+ uint id) {
+ this.root_path = root_path;
+ this.id = id;
+ }
+
+ public File get_root () {
+ if (root == null)
+ // Can't create a GLib.File in the constructor due to locking in GIO
+ this.root = File.new_for_path (root_path);
+
+ return root;
+ }
+
+ public Icon get_icon () {
+ return null;
+ }
+
+ public string get_name () {
+ return "Test Mount %u".printf(id);
+ }
+
+ public File get_default_location () {
+ return this.get_root ();
+ }
+
+ public string get_uuid () {
+ return "FFFF-F%03u".printf(id);
+ }
+
+ public Volume get_volume () {
+ return null;
+ }
+
+ public Drive get_drive () {
+ return null;
+ }
+
+ public bool can_unmount () {
+ return true;
+ }
+
+ public bool can_eject () {
+ return false;
+ }
+
+ public async bool eject (GLib.MountUnmountFlags flags,
+ GLib.Cancellable? cancellable)
+ throws GLib.Error {
+ return false;
+ }
+
+ public async bool eject_with_operation (GLib.MountUnmountFlags flags,
+ GLib.MountOperation? mount_operation,
+ GLib.Cancellable? cancellable)
+ throws GLib.Error {
+ return false;
+ }
+
+
+ public string[] guess_content_type_sync (bool force_rescan,
+ Cancellable? cancellable)
+ throws GLib.Error {
+ return new string[1];
+ }
+
+ public async string[] guess_content_type (bool force_rescan,
+ Cancellable? cancellable)
+ throws GLib.Error {
+ return guess_content_type_sync (force_rescan, cancellable);
+ }
+
+ public async bool remount (GLib.MountMountFlags flags,
+ GLib.MountOperation? mount_operation,
+ GLib.Cancellable? cancellable)
+ throws GLib.Error {
+ return false;
+ }
+
+ public async bool unmount (MountUnmountFlags flags,
+ Cancellable? cancellable)
+ throws GLib.Error {
+ return yield this.unmount_with_operation (flags, null, cancellable);
+ }
+
+ public async bool unmount_with_operation (MountUnmountFlags flags,
+ MountOperation? operation,
+ Cancellable? cancellable)
+ throws GLib.Error {
+ return false;
+ }
+
+#if GLIB_2_32
+ public unowned string get_sort_key () {
+ return null;
+ }
+#endif
+}
+
+public class Tracker.TestVolumeMonitor: GLib.VolumeMonitor {
+ List<Mount> mount_list;
+ uint dbus_mount_added_id;
+ uint dbus_mount_removed_id;
+
+ construct {
+ // GObject construction is required because GUnionVolumeMonitor has to
+ // use g_object_new() to create an instance.
+
+ this.mount_list = null;
+
+ Bus.watch_name (BusType.SESSION,
+ "org.freedesktop.Tracker1.TestMounter",
+ BusNameWatcherFlags.NONE,
+ on_test_mount_service_appeared,
+ on_test_mount_service_vanished);
+ }
+
+ void on_test_mount_service_appeared (DBusConnection connection,
+ string name,
+ string name_owner) {
+ dbus_mount_added_id = connection.signal_subscribe
+ (name,
+ "org.freedesktop.Tracker1.TestMounter",
+ "MountAdded",
+ "/org/freedesktop/Tracker1/TestMounter",
+ null,
+ DBusSignalFlags.NONE,
+ dbus_mount_added_cb);
+
+ dbus_mount_removed_id = connection.signal_subscribe
+ (name,
+ "org.freedesktop.Tracker1.TestMounter",
+ "MountRemoved",
+ "/org/freedesktop/Tracker1/TestMounter",
+ null,
+ DBusSignalFlags.NONE,
+ dbus_mount_removed_cb);
+
+ connection.call.begin (name,
+ "/org/freedesktop/Tracker1/TestMounter",
+ "org.freedesktop.Tracker1.TestMounter",
+ "ListMounts",
+ null, null, DBusCallFlags.NONE, -1, null,
+ (s, r) => {
+ Variant reply;
+
+ try {
+ reply = connection.call.end (r);
+ }
+ catch (Error e) {
+ warning ("Call to org.freedesktop.Tracker1.TestMounter.ListMounts() failed: %s", e.message);
+ return;
+ }
+
+ string root_path;
+ uint id;
+
+ var mount_iter = reply.get_child_value(0).get_child_value(0).iterator ();
+ while (mount_iter.next ("(su)", out root_path, out id))
+ this.add_mount (root_path, id);
+ });
+ }
+
+ void on_test_mount_service_vanished (DBusConnection connection,
+ string name) {
+ foreach (Mount m in mount_list)
+ this.mount_removed (m);
+
+ connection.signal_unsubscribe (this.dbus_mount_added_id);
+ connection.signal_unsubscribe (this.dbus_mount_removed_id);
+
+ this.mount_list = null;
+ }
+
+ unowned List<Mount>? find_mount_by_root_path (string root_path) {
+ for (unowned List<Mount> l = this.mount_list; l != null; l = l.next)
+ if (((Tracker.TestMount)l.data).root_path == root_path)
+ return l;
+
+ return null;
+ }
+
+ void add_mount (string root_path,
+ uint id) {
+ unowned List<Mount> l = find_mount_by_root_path (root_path);
+
+ if (l != null)
+ return;
+
+ Mount mount = new Tracker.TestMount (root_path, id);
+
+ this.mount_list.prepend (mount);
+
+ this.mount_added (mount);
+ }
+
+ void remove_mount (string root_path) {
+ unowned List<Mount> l = find_mount_by_root_path (root_path);
+
+ if (l == null)
+ return;
+
+ Mount mount = l.data;
+ this.mount_list.delete_link (l);
+ this.mount_removed (mount);
+ }
+
+ void dbus_mount_added_cb (DBusConnection connection,
+ string sender_name,
+ string object_path,
+ string interface_name,
+ string signal_name,
+ Variant parameters) {
+ string root_path;
+ uint id;
+
+ parameters.get ("(su)", out root_path, out id);
+ this.add_mount (root_path, id);
+ }
+
+ void dbus_mount_removed_cb (DBusConnection connection,
+ string sender_name,
+ string object_path,
+ string interface_name,
+ string signal_name,
+ Variant parameters) {
+ string root_path;
+
+ parameters.get ("(s)", out root_path);
+ this.remove_mount (root_path);
+ }
+
+
+ public override bool is_supported () {
+ return true;
+ }
+
+ public override List<unowned Mount> get_mounts () {
+ return this.mount_list.copy ();
+ }
+
+ public override List<Volume> get_volumes () {
+ return null;
+ }
+
+ public override List<Drive> get_connected_drives () {
+ return null;
+ }
+
+ public override Volume get_volume_for_uuid (string uuid) {
+ return null;
+ }
+
+ public override Mount get_mount_for_uuid (string uuid) {
+ return null;
+ }
+
+ public Mount? get_mount_for_mount_path (string mount_path) {
+ foreach (Mount m in this.mount_list) {
+ if (m.get_root().get_path() == mount_path)
+ return m;
+ }
+
+ return null;
+ }
+}
+
+public static void g_io_module_load (IOModule module) {
+ tracker_test_volume_monitor_register_types (module);
+}
+
+public static void g_io_module_unload (IOModule module) {
+}
+
+[CCode (array_length = false)]
+public static string[] g_io_module_query () {
+ return {"gio-volume-monitor"};
+}
+
+[ModuleInit]
+public static void tracker_test_volume_monitor_register_types (TypeModule module) {
+ GLib.IOExtensionPoint.implement ("gio-volume-monitor",
+ typeof (Tracker.TestVolumeMonitor),
+ "tracker-test-volume-monitor",
+ 0);
+}
+
diff --git a/utils/tracker-sandbox b/utils/tracker-sandbox
index bf6ee43..a7ff26d 100755
--- a/utils/tracker-sandbox
+++ b/utils/tracker-sandbox
@@ -107,6 +107,13 @@ if [ -n "$PREFIX" ]; then
export TRACKER_LANGUAGE_STOPWORDS_DIR="$PREFIX/share/tracker/languages"
fi
+# FIXME: should be in lib/tracker-0.14 ;)
+# Allow use of test mounter, if desired ... this is bit of a black art which
+# requires executing libexec/tracker-test-mount-service and then calling its
+# DBus API manually for now.
+export GIO_EXTRA_MODULES="$(dirname $(which tracker-control))/../lib/tracker"
+export GIO_USE_VOLUME_MONITOR="tracker-test-volume-monitor"
+
set -o nounset
if [ "$SEPARATE_USER_MODE" != "true" ]; then
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]