summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSam Thursfield <sam@afuera.me.uk>2015-08-11 16:10:53 +0200
committerSam Thursfield <sam@afuera.me.uk>2015-08-11 20:59:02 +0200
commitd4e6a08315aa5dea3955e1725b5e10bdf1301c54 (patch)
tree69c7106414500356cf6bd384fb93df0e9591e4a3
parent0ed5f9ee81ac1dc5d12e5f1d978fd9878f489e3a (diff)
downloadtracker-d4e6a08315aa5dea3955e1725b5e10bdf1301c54.tar.gz
functional-tests: Initial 'on-demand indexing' test cases
-rwxr-xr-xtests/functional-tests/302-miner-on-demand.py94
-rw-r--r--tests/functional-tests/common/utils/helpers.py53
-rw-r--r--tests/functional-tests/common/utils/minertest.py12
3 files changed, 157 insertions, 2 deletions
diff --git a/tests/functional-tests/302-miner-on-demand.py b/tests/functional-tests/302-miner-on-demand.py
new file mode 100755
index 000000000..6f6e6af39
--- /dev/null
+++ b/tests/functional-tests/302-miner-on-demand.py
@@ -0,0 +1,94 @@
+#!/usr/bin/python
+
+# Copyright (C) 2015, Sam Thursfield (ssssam@gmail.com)
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This library 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
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program. If not, see <http://www.gnu.org/licenses/>.
+
+"""
+Test on-demand indexing of locations.
+
+This feature exists so that applications can trigger the indexing of a
+removable device.
+
+See: https://bugzilla.gnome.org/show_bug.cgi?id=680834
+"""
+
+from gi.repository import Gio
+
+import time
+import unittest2 as ut
+
+from common.utils.helpers import log
+from common.utils.minertest import CommonTrackerMinerTest, uri
+
+
+class MinerOnDemandIndexingTest (CommonTrackerMinerTest):
+# def test_01_index_file (self):
+# """
+# Indexing a file outside the configured indexing locations.
+#
+# This can also be done from the commandline with `tracker index FILE`.
+# """
+#
+# # This is created by CommonTrackerMinerTest.setup() from
+# # common.utils.minertest module.
+# unmonitored_file = 'test-no-monitored/file0.txt'
+#
+# self.assertFileMissing(uri(unmonitored_file))
+#
+# log("Queuing %s for indexing" % uri(unmonitored_file))
+# self.system.miner_fs.index_iface.IndexFile(uri(unmonitored_file))
+# self.system.store.await_resource_inserted('nfo:TextDocument',
+# url=uri(unmonitored_file))
+#
+ def test_02_index_file_for_process(self):
+ """
+ Indexing a directory tree for a specific D-Bus name.
+
+ The idea is that the indexing stops if the D-Bus name disappears, so
+ that indexing of large removable devices can be tied to the lifetime of
+ certain applications that let users 'opt in' to indexing a device.
+ """
+ unmonitored_file = 'test-no-monitored/file0.txt'
+ self.assertFileMissing(uri(unmonitored_file))
+
+ miner = self.system.miner_fs
+
+ fake_app = Gio.bus_get_sync(Gio.BusType.SESSION)
+ log("Opened D-Bus connection %s" % fake_app.get_unique_name())
+
+ # Index a file for the fake_app process, but then close the fake_app
+ # straight away so the file doesn't get indexed. We do this while the
+ # miner is paused, because otherwise the file might get indexed before
+ # the app disappears, which would cause a spurious test failure.
+ cookie = miner.miner_fs.PauseForProcess(
+ fake_app.get_unique_name(),
+ "Avoid test process racing with miner process.")
+ miner.index_iface.IndexFile(uri(unmonitored_file))
+ fake_app.close()
+ log("Closed temporary D-Bus connection.")
+
+ # The file should never get indexed, because the process disappeared.
+ miner.miner_fs.Resume(cookie)
+ time.sleep(5)
+ #self.assertFileMissing(uri(unmonitored_file))
+ self.system.store.await_resource_inserted('nfo:TextDocument',
+ url=uri(unmonitored_file))
+ self.assertFilePresent(uri(unmonitored_file))
+
+
+ # hammer index_file_for_process 50000 times
+
+if __name__ == "__main__":
+ ut.main()
diff --git a/tests/functional-tests/common/utils/helpers.py b/tests/functional-tests/common/utils/helpers.py
index 556f11f5f..7b3ca88a9 100644
--- a/tests/functional-tests/common/utils/helpers.py
+++ b/tests/functional-tests/common/utils/helpers.py
@@ -39,6 +39,49 @@ def log (message):
if options.is_verbose ():
print (message)
+
+def wait_for_bus_name(bus, bus_admin, wanted_name):
+ """
+ Wait for a D-Bus name independently of a process.
+
+ This is used for 'sub' interfaces of a process, which may not appear
+ straight away after the process starts up. For example, the
+ org.freedesktop.Tracker1.Miner.Files.Index object provided by
+ tracker-miner-fs appears a random amount of time *after*
+ the main org.freedesktop.Tracker1.Miner.Filesobject.
+ """
+ available = False
+ loop = GObject.MainLoop ()
+
+ def name_owner_changed_cb(name, old_owner, new_owner):
+ if name == wanted_name:
+ if len(old_owner) == 0 and len(new_owner) > 0:
+ log ("%s appeared on bus (%s)." % (wanted_name, new_owner))
+ available = True
+ elif len(old_owner) > 0 and len(new_owner) == 0:
+ log ("%s disappeared from bus (was %s)." % (
+ wanted_name, old_owner))
+ available = False
+ else:
+ log ("%s name owner changed (%s => %s)." % (
+ wanted_name, old_owner, new_owner))
+ loop.quit ()
+
+ name_owner_match = bus.add_signal_receiver (name_owner_changed_cb,
+ signal_name="NameOwnerChanged",
+ path="/org/freedesktop/DBus",
+ dbus_interface="org.freedesktop.DBus")
+
+ if bus_admin.NameHasOwner(wanted_name):
+ log ("%s available on bus." % wanted_name)
+ return
+
+ # Run the loop until the bus name appears. (FIXME: we should have a
+ # timeout in case it doesn't ever appear).
+ loop.run()
+ return
+
+
class Helper:
"""
Abstract helper for Tracker processes. Launches the process manually
@@ -137,7 +180,6 @@ class Helper:
self.timeout_id = None
return False
-
def start (self):
"""
Start an instance of process and wait for it to appear on the bus.
@@ -604,6 +646,15 @@ class MinerFsHelper (Helper):
self.miner_fs = dbus.Interface (bus_object,
dbus_interface = cfg.MINER_IFACE)
+
+ # 'Index' interface is a separate interface, provided by the same
+ # process.
+ wait_for_bus_name(self.bus, self.bus_admin, cfg.MINERFS_INDEX_BUSNAME)
+ index_bus_object = self.bus.get_object (cfg.MINERFS_INDEX_BUSNAME,
+ cfg.MINERFS_INDEX_OBJ_PATH)
+ self.index_iface = dbus.Interface (index_bus_object,
+ dbus_interface = cfg.MINER_INDEX_IFACE)
+
def stop (self):
Helper.stop (self)
diff --git a/tests/functional-tests/common/utils/minertest.py b/tests/functional-tests/common/utils/minertest.py
index 5aae50f19..1aa63ac1b 100644
--- a/tests/functional-tests/common/utils/minertest.py
+++ b/tests/functional-tests/common/utils/minertest.py
@@ -25,7 +25,6 @@ from gi.repository import GLib
import shutil
import os
-import warnings
from itertools import chain
MINER_TMP_DIR = cfg.TEST_MONITORED_TMP_DIR
@@ -120,3 +119,14 @@ class CommonTrackerMinerTest (ut.TestCase):
def assertResourceMissing (self, urn):
if self.tracker.ask ("ASK { <%s> a rdfs:Resource }" % urn) == True:
self.fail ("Resource <%s> should not exist" % urn)
+
+ def assertFilePresent (self, file_url):
+ query = "ASK { ?r a nie:DataObject ; nie:url <%s> }" % file_url
+ if self.tracker.ask (query) == False:
+ self.fail ("File <%s> does not exist in the database" % file_url)
+
+ def assertFileMissing (self, file_url):
+ query = "ASK { ?r a nie:DataObject ; nie:url <%s> }" % file_url
+ if self.tracker.ask (query) == True:
+ self.fail ("File <%s> should not be present in the database" %
+ file_url)