diff options
author | Sam Thursfield <sam@afuera.me.uk> | 2015-08-11 16:10:53 +0200 |
---|---|---|
committer | Sam Thursfield <sam@afuera.me.uk> | 2015-08-11 20:59:02 +0200 |
commit | d4e6a08315aa5dea3955e1725b5e10bdf1301c54 (patch) | |
tree | 69c7106414500356cf6bd384fb93df0e9591e4a3 | |
parent | 0ed5f9ee81ac1dc5d12e5f1d978fd9878f489e3a (diff) | |
download | tracker-d4e6a08315aa5dea3955e1725b5e10bdf1301c54.tar.gz |
functional-tests: Initial 'on-demand indexing' test cases
-rwxr-xr-x | tests/functional-tests/302-miner-on-demand.py | 94 | ||||
-rw-r--r-- | tests/functional-tests/common/utils/helpers.py | 53 | ||||
-rw-r--r-- | tests/functional-tests/common/utils/minertest.py | 12 |
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) |