[tracker/sam/index-mount-points: 7/11] functional-tests: Initial 'on-demand indexing' test cases



commit d4e6a08315aa5dea3955e1725b5e10bdf1301c54
Author: Sam Thursfield <sam afuera me uk>
Date:   Tue Aug 11 16:10:53 2015 +0200

    functional-tests: Initial 'on-demand indexing' test cases

 tests/functional-tests/302-miner-on-demand.py    |   94 ++++++++++++++++++++++
 tests/functional-tests/common/utils/helpers.py   |   53 ++++++++++++-
 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 0000000..6f6e6af
--- /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 556f11f..7b3ca88 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 5aae50f..1aa63ac 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)


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]