[tracker/functional-test-improvements: 2/5] functional-tests: Refactor common/utils/helpers.py



commit 690eecb143f6dd69ed3603934c3a7f521918baa8
Author: Sam Thursfield <samthursfield codethink co uk>
Date:   Wed Aug 10 13:22:02 2011 +0100

    functional-tests: Refactor common/utils/helpers.py
    
    * Add Helper base class.
    
    * New setup behaviour: start() runs the process and blocks until it is
      available on the bus. connect() and wait() are removed.
    
    * A new process is always explicitly spawned, instead of relying on DBus
      activation. This allows passing environment variables to the tracker
      processes being tested, regardless of whether they are being run in
      the session dbus or a nested bus from test-helper.sh.
    
    * common/utils/system.py: use Helper instead of our own LifeCycle
      classes because they now do the same thing.
    
    * StoreHelper: don't try to respawn the tracker-store unless it actually
      has disappeared from the bus - other exceptions are now passed to the
      caller.
    
    All tests fixed for new behaviour.

 tests/functional-tests/12-transactions.py          |    4 +-
 tests/functional-tests/17-ontology-changes.py      |    3 +-
 tests/functional-tests/200-backup-restore.py       |    6 -
 tests/functional-tests/400-extractor.py            |    4 +
 tests/functional-tests/500-writeback.py            |    9 +-
 tests/functional-tests/501-writeback-details.py    |    5 +-
 .../common/utils/applicationstest.py               |    4 +-
 tests/functional-tests/common/utils/helpers.py     |  333 ++++++++++++++++----
 tests/functional-tests/common/utils/minertest.py   |    6 +-
 tests/functional-tests/common/utils/storetest.py   |    3 +-
 tests/functional-tests/common/utils/system.py      |  285 +----------------
 11 files changed, 293 insertions(+), 369 deletions(-)
---
diff --git a/tests/functional-tests/12-transactions.py b/tests/functional-tests/12-transactions.py
index 7cfbb87..a3c19f4 100755
--- a/tests/functional-tests/12-transactions.py
+++ b/tests/functional-tests/12-transactions.py
@@ -75,14 +75,12 @@ class TrackerTransactionsTest (CommonTrackerStoreTest):
 
             self.system.tracker_store_stop_brutally ()
             self.system.tracker_store_start ()
-            # Reconnect dbus
-            self.tracker.connect ()
             try:
                 results = self.tracker.count_instances ("nmo:Email")
             except:
                 print "Timeout, probably replaying journal or something (wait 20 sec.)"
                 time.sleep (20)
-                results = self.count_instances ()
+                results = self.tracker.count_instances ()
 
             # Every iteration we are adding new instances in the store!
             self.assertEquals (results, NUMBER_OF_INSTANCES * (i+1))
diff --git a/tests/functional-tests/17-ontology-changes.py b/tests/functional-tests/17-ontology-changes.py
index 890a397..237f12d 100755
--- a/tests/functional-tests/17-ontology-changes.py
+++ b/tests/functional-tests/17-ontology-changes.py
@@ -86,8 +86,7 @@ class OntologyChangeTestTemplate (ut.TestCase):
 
 
         self.system.tracker_store_testing_start (ontodir=basic_ontologies)
-        self.tracker = StoreHelper ()
-        self.tracker.wait () #Safe guard. Returns when the store is ready
+        self.tracker = self.system.store
 
         self.insert_data ()
 
diff --git a/tests/functional-tests/200-backup-restore.py b/tests/functional-tests/200-backup-restore.py
index 61cc368..20cdabc 100755
--- a/tests/functional-tests/200-backup-restore.py
+++ b/tests/functional-tests/200-backup-restore.py
@@ -274,10 +274,6 @@ class JournalReplayTest (CommonTrackerStoreTest):
             self.system.tracker_store_stop_brutally ()
             self.system.tracker_store_corrupt_dbs ()
             self.system.tracker_store_start ()
-            ## Start it twice... the first time it detects the broken DB and aborts
-            #self.system.tracker_store_start ()
-
-            self.tracker.connect ()
 
             emails_now = self.tracker.count_instances ("nmo:Email")
             ie_now = self.tracker.count_instances ("nie:InformationElement")
@@ -311,8 +307,6 @@ class JournalReplayTest (CommonTrackerStoreTest):
             self.system.tracker_store_prepare_journal_replay ()
             self.system.tracker_store_start ()
 
-            self.tracker.connect ()
-
             emails_now = self.tracker.count_instances ("nmo:Email")
             ie_now = self.tracker.count_instances ("nie:InformationElement")
             contacts_now = self.tracker.count_instances ("nco:Contact")
diff --git a/tests/functional-tests/400-extractor.py b/tests/functional-tests/400-extractor.py
index 2e3762d..71050aa 100755
--- a/tests/functional-tests/400-extractor.py
+++ b/tests/functional-tests/400-extractor.py
@@ -95,6 +95,10 @@ class ExtractionTestCase (ut.TestCase):
 
     def setUp (self):
         self.extractor = ExtractorHelper ()
+        self.extractor.start ()
+
+    def tearDown (self):
+        self.extractor.stop ()
 
     def expected_failure_test_extraction (self):
         try:
diff --git a/tests/functional-tests/500-writeback.py b/tests/functional-tests/500-writeback.py
index e141610..734ae1e 100755
--- a/tests/functional-tests/500-writeback.py
+++ b/tests/functional-tests/500-writeback.py
@@ -24,7 +24,6 @@ on the files. Note that these tests are highly platform dependant.
 import os, dbus
 import time
 
-from common.utils.helpers import StoreHelper, ExtractorHelper
 from common.utils.writebacktest import CommonTrackerWritebackTest as CommonTrackerWritebackTest
 import unittest2 as ut
 from common.utils.expectedFailure import expectedFailureBug
@@ -37,12 +36,8 @@ class WritebackBasicDataTest (CommonTrackerWritebackTest):
     that the new values are actually in the file
     """
     def setUp (self):
-        self.tracker = StoreHelper ()
-        self.extractor = ExtractorHelper ()
-
-    def tearDown (self):
-        # Give it more time between tests to avoid random failures?
-        pass
+        self.tracker = self.system.store
+        self.extractor = self.system.extractor
 
     def __clean_property (self, property_name, fileuri, expectFailure=True):
         """
diff --git a/tests/functional-tests/501-writeback-details.py b/tests/functional-tests/501-writeback-details.py
index 35f9180..3db4f21 100755
--- a/tests/functional-tests/501-writeback-details.py
+++ b/tests/functional-tests/501-writeback-details.py
@@ -18,7 +18,6 @@
 # Boston, MA  02110-1301, USA.
 #
 from common.utils.writebacktest import CommonTrackerWritebackTest as CommonTrackerWritebackTest
-from common.utils.helpers import StoreHelper, ExtractorHelper
 import unittest2 as ut
 from common.utils.expectedFailure import expectedFailureBug
 import time
@@ -28,8 +27,8 @@ REASONABLE_TIMEOUT = 5 # Seconds we wait for tracker-writeback to do the work
 class WritebackKeepDateTest (CommonTrackerWritebackTest):
 
     def setUp (self):
-        self.tracker = StoreHelper ()
-        self.extractor = ExtractorHelper ()
+        self.tracker = self.system.store
+        self.extractor = self.system.extractor
         self.favorite = self.__prepare_favorite_tag ()
 
     def __prepare_favorite_tag (self):
diff --git a/tests/functional-tests/common/utils/applicationstest.py b/tests/functional-tests/common/utils/applicationstest.py
index 222a392..421b46d 100644
--- a/tests/functional-tests/common/utils/applicationstest.py
+++ b/tests/functional-tests/common/utils/applicationstest.py
@@ -19,7 +19,6 @@
 #
 from common.utils import configuration as cfg
 from common.utils.system import TrackerSystemAbstraction
-from common.utils.helpers import StoreHelper
 import unittest2 as ut
 
 import shutil
@@ -109,8 +108,7 @@ class CommonTrackerApplicationTest (ut.TestCase):
         self.system.tracker_all_testing_start (CONF_OPTIONS)
 
         # Returns when ready
-        self.tracker = StoreHelper ()
-        self.tracker.wait ()
+        self.tracker = self.system.store
 
         print "Ready to go!"
 
diff --git a/tests/functional-tests/common/utils/helpers.py b/tests/functional-tests/common/utils/helpers.py
index e6dc1c4..9cc0b17 100644
--- a/tests/functional-tests/common/utils/helpers.py
+++ b/tests/functional-tests/common/utils/helpers.py
@@ -18,18 +18,150 @@
 # 02110-1301, USA.
 #
 import dbus
+import glib
 import gobject
 import commands
 import os
 import signal
+import subprocess
+import time
 from dbus.mainloop.glib import DBusGMainLoop
-import configuration as cfg
 import re
 
+import configuration as cfg
+import options
+
 class NoMetadataException (Exception):
     pass
 
-class StoreHelper:
+REASONABLE_TIMEOUT = 30
+
+class Helper:
+    """
+    Abstract helper for Tracker processes. Launches the process manually
+    and waits for it to appear on the session bus.
+
+    The helper will fail if the process is already running. Use
+    test-runner.sh to ensure the processes run inside a separate DBus
+    session bus.
+    """
+
+    BUS_NAME = None
+    PROCESS_NAME = None
+
+    def __init__ (self):
+        self.loop = None
+        self.bus = None
+        self.bus_admin = None
+
+    def _get_bus (self):
+        if self.bus is not None:
+            return
+
+        self.loop = gobject.MainLoop ()
+
+        dbus_loop = DBusGMainLoop (set_as_default=True)
+        self.bus = dbus.SessionBus (dbus_loop)
+
+        obj = self.bus.get_object ("org.freedesktop.DBus",
+                                   "/org/freedesktop/DBus")
+        self.bus_admin = dbus.Interface (obj, dbus_interface = "org.freedesktop.DBus")
+
+    def _start_process (self):
+        path = getattr (self,
+                        "PROCESS_PATH",
+                        os.path.join (cfg.EXEC_PREFIX, self.PROCESS_NAME))
+
+        FNULL = open ('/dev/null', 'w')
+
+        if options.is_manual_start ():
+            print ("Start %s manually" % self.PROCESS_NAME)
+        else:
+            return subprocess.Popen ([path], stdout=FNULL, stderr=FNULL)
+
+    def _stop_process (self):
+        if options.is_manual_start ():
+            if self.available:
+                print ("Kill %s manually" % self.PROCESS_NAME)
+                self.loop.run ()
+        else:
+            self.process.terminate ()
+            self.process.wait ()
+        return False
+
+    def _name_owner_changed_cb (self, name, old_owner, new_owner):
+        if name == self.BUS_NAME:
+            if old_owner == '' and new_owner != '':
+                print ("[%s] appeared in the bus" % self.PROCESS_NAME)
+                self.available = True
+            elif old_owner != ''  and new_owner == '':
+                print ("[%s] disappeared from the bus" % self.PROCESS_NAME)
+                self.available = False
+            else:
+                print ("[%s] name change %s -> %s" % (self.PROCESS_NAME, old_owner, new_owner))
+
+            self.loop.quit ()
+
+    def _process_watch_cb (self):
+        status = self.process.poll ()
+
+        if status is None:
+            return True
+
+        raise Exception("%s exited with status: %i" % (self.PROCESS_NAME, status))
+
+    def _timeout_on_idle_cb (self):
+        print ("[%s] Timeout waiting... asumming idle." % self.PROCESS_NAME)
+        self.loop.quit ()
+        return False
+
+
+    def start (self):
+        """
+        Start an instance of process and wait for it to appear on the bus.
+        """
+
+        self._get_bus ()
+
+        if (self.bus_admin.NameHasOwner (self.BUS_NAME)):
+            raise Exception ("Unable to start test instance of %s: already running" % self.PROCESS_NAME)
+
+        self.name_owner_match = self.bus.add_signal_receiver (self._name_owner_changed_cb,
+                                                              signal_name="NameOwnerChanged",
+                                                              path="/org/freedesktop/DBus",
+                                                              dbus_interface="org.freedesktop.DBus")
+
+        self.process = self._start_process ()
+
+        # Run the loop until the bus name appears, or the process dies.
+        self.process_watch_timeout = glib.timeout_add (200, self._process_watch_cb)
+
+        self.loop.run ()
+
+        glib.source_remove (self.process_watch_timeout)
+
+    def stop (self):
+        if self.available:
+            # It should step out of this loop when the miner disappear from the bus
+            glib.idle_add (self._stop_process)
+            self.timeout_id = glib.timeout_add_seconds (REASONABLE_TIMEOUT, self._timeout_on_idle_cb)
+            self.loop.run ()
+
+        print ("[%s] stop." % self.PROCESS_NAME)
+        # Disconnect the signals of the next start we get duplicated messages
+        self.bus._clean_up_signal_match (self.name_owner_match)
+
+    def kill (self):
+        self.process.kill ()
+
+        # Name owner changed callback should take us out from this loop
+        self.loop.run ()
+
+        print ("[%s] killed." % self.PROCESS_NAME)
+        self.bus._clean_up_signal_match (self.name_owner_match)
+
+
+class StoreHelper (Helper):
     """
     Wrapper for the Store API
 
@@ -37,44 +169,60 @@ class StoreHelper:
     (some tests kill the daemon and make the connection useless)
     """
 
-    def __init__ (self):
-        self.connect ()
-        
-    def connect (self):
-        dbus_loop = DBusGMainLoop(set_as_default=True)
-        bus = dbus.SessionBus (mainloop=dbus_loop)
-        tracker = bus.get_object (cfg.TRACKER_BUSNAME, cfg.TRACKER_OBJ_PATH)
+    PROCESS_NAME = "tracker-store"
+    BUS_NAME = cfg.TRACKER_BUSNAME
+
+    def start (self):
+        Helper.start (self)
+
+        tracker = self.bus.get_object (cfg.TRACKER_BUSNAME,
+                                       cfg.TRACKER_OBJ_PATH)
+
         self.resources = dbus.Interface (tracker,
                                          dbus_interface=cfg.RESOURCES_IFACE)
-        tracker_backup = bus.get_object (cfg.TRACKER_BUSNAME, cfg.TRACKER_BACKUP_OBJ_PATH)
+
+        tracker_backup = self.bus.get_object (cfg.TRACKER_BUSNAME, cfg.TRACKER_BACKUP_OBJ_PATH)
         self.backup_iface = dbus.Interface (tracker_backup, dbus_interface=cfg.BACKUP_IFACE)
 
-        tracker_stats = bus.get_object (cfg.TRACKER_BUSNAME, cfg.TRACKER_STATS_OBJ_PATH)
+        tracker_stats = self.bus.get_object (cfg.TRACKER_BUSNAME, cfg.TRACKER_STATS_OBJ_PATH)
+
         self.stats_iface = dbus.Interface (tracker_stats, dbus_interface=cfg.STATS_IFACE)
 
-        tracker_status = bus.get_object (cfg.TRACKER_BUSNAME, cfg.TRACKER_STATUS_OBJ_PATH)
+        tracker_status = self.bus.get_object (cfg.TRACKER_BUSNAME,
+                                              cfg.TRACKER_STATUS_OBJ_PATH)
         self.status_iface = dbus.Interface (tracker_status, dbus_interface=cfg.STATUS_IFACE)
 
+        print ("[%s] booting..." % self.PROCESS_NAME)
+        self.status_iface.Wait ()
+        print ("[%s] ready." % self.PROCESS_NAME)
+
+
     def query (self, query, timeout=5000):
         try:
             return self.resources.SparqlQuery (query, timeout=timeout)
-        except dbus.DBusException:
-            self.connect ()
-            return self.resources.SparqlQuery (query, timeout=timeout)
+        except dbus.DBusException as (e):
+            if (e.get_dbus_name().startswith ("org.freedesktop.DBus")):
+                self.start ()
+                return self.resources.SparqlQuery (query, timeout=timeout)
+            raise (e)
 
     def update (self, update_sparql, timeout=5000):
         try:
             return self.resources.SparqlUpdate (update_sparql, timeout=timeout)
-        except dbus.DBusException:
-            self.connect ()
-            return self.resources.SparqlUpdate (update_sparql, timeout=timeout)
+        except dbus.DBusException as (e):
+            if (e.get_dbus_name().startswith ("org.freedesktop.DBus")):
+                self.start ()
+                return self.resources.SparqlUpdate (update_sparql, timeout=timeout)
+            raise (e)
 
     def batch_update (self, update_sparql):
         try:
             return self.resources.BatchSparqlUpdate (update_sparql)
-        except dbus.DBusException:
-            self.connect ()
-            return self.resources.BatchSparqlUpdate (update_sparql)
+        except dbus.DBusException as (e):
+            if (e.get_dbus_name().startswith ("org.freedesktop.DBus")):
+                self.start ()
+                return self.resources.BatchSparqlUpdate (update_sparql)
+            raise (e)
 
     def batch_commit (self):
         return self.resources.BatchCommit ()
@@ -82,30 +230,29 @@ class StoreHelper:
     def backup (self, backup_file):
         try:
             self.backup_iface.Save (backup_file)
-        except dbus.DBusException:
-            self.connect ()
-            self.backup_iface.Save (backup_file)
+        except dbus.DBusException as (e):
+            if (e.get_dbus_name().startswith ("org.freedesktop.DBus")):
+                self.start ()
+                return self.backup_iface.Save (backup_file)
+            raise (e)
             
     def restore (self, backup_file):
         try:
             return self.backup_iface.Restore (backup_file)
-        except dbus.DBusException:
-            self.connect ()
-            return self.backup_iface.Restore (backup_file)
+        except dbus.DBusException as (e):
+            if (e.get_dbus_name().startswith ("org.freedesktop.DBus")):
+                self.start ()
+                return self.backup_iface.Restore (backup_file)
+            raise (e)
 
     def get_stats (self):
         try:
             return self.stats_iface.Get ()
-        except dbus.DBusException:
-            self.connect ()
-            return self.stats_iface.Get ()
-
-    def wait (self):
-        try:
-            return self.status_iface.Wait ()
-        except dbus.DBusException:
-            self.connect ()
-            return self.status_iface.Wait ()
+        except dbus.DBusException as (e):
+            if (e.get_dbus_name().startswith ("org.freedesktop.DBus")):
+                self.start ()
+                return self.stats_iface.Get ()
+            raise (e)
 
 
     def get_tracker_iface (self):
@@ -139,38 +286,89 @@ class StoreHelper:
             return False
         else:
             raise Exception ("Something fishy is going on")
-            
-        
 
-        
-class MinerHelper ():
 
-    def __init__ (self):
-        self.connect ()
-
-    def connect (self):
-        dbus_loop = DBusGMainLoop(set_as_default=True)
-        bus = dbus.SessionBus (mainloop=dbus_loop)
-        minerfs = bus.get_object (cfg.MINERFS_BUSNAME, cfg.MINERFS_OBJ_PATH)
-        self.miner_fs = dbus.Interface (minerfs,
-                                        dbus_interface=cfg.MINER_IFACE)
-        
+class MinerFsHelper (Helper):
+
+    PROCESS_NAME = 'tracker-miner-fs'
+    PROCESS_PATH = os.path.join (cfg.EXEC_PREFIX, "tracker-miner-fs")
+    BUS_NAME = cfg.MINERFS_BUSNAME
+
+    def _stop_process (self):
+        if options.is_manual_start ():
+            if self.available:
+                print ("Kill %s manually" % self.PROCESS_NAME)
+                self.loop.run ()
+        else:
+            control_binary = os.path.join (cfg.BINDIR, "tracker-control")
+            FNULL = open('/dev/null', 'w')
+            subprocess.call ([control_binary, "--kill=miners"], stdout=FNULL)
+        return False
+
+    def _minerfs_status_cb (self, status, progress, remaining_time):
+        print ("[%s] status is now %s" % (self.PROCESS_NAME, status.encode ("utf-8")))
+
+        if (status == "Idle"):
+            self.loop.quit ()
+
+    def start (self):
+        Helper.start (self)
+
+        self.status_match = self.bus.add_signal_receiver (self._minerfs_status_cb,
+                                                          signal_name="Progress",
+                                                          path=cfg.MINERFS_OBJ_PATH,
+                                                          dbus_interface=cfg.MINER_IFACE)
+
+        # It should step out of this loop after progress changes to "Idle"
+        self.timeout_id = glib.timeout_add_seconds (REASONABLE_TIMEOUT, self._timeout_on_idle_cb)
+        self.loop.run ()
+        glib.source_remove (self.timeout_id)
+
+        bus_object = self.bus.get_object (cfg.MINERFS_BUSNAME,
+                                          cfg.MINERFS_OBJ_PATH)
+        self.miner_fs = dbus.Interface (bus_object,
+                                        dbus_interface = cfg.MINER_IFACE)
+
+    def stop (self):
+        Helper.stop (self)
+
+        self.bus._clean_up_signal_match (self.status_match)
+
     def ignore (self, filelist):
         self.miner_fs.IgnoreNextUpdate (filelist)
 
-        
-class ExtractorHelper ():
+    def wait_for_idle (self, timeout=REASONABLE_TIMEOUT):
+        """
+        Block until the miner has finished crawling and its status becomes "Idle"
+        """
 
-    def __init__ (self):
-        self.connect ()
-    
-    def connect (self):
-        dbus_loop = DBusGMainLoop(set_as_default=True)
-        bus = dbus.SessionBus (mainloop=dbus_loop)
-        tracker = bus.get_object (cfg.TRACKER_EXTRACT_BUSNAME, cfg.TRACKER_EXTRACT_OBJ_PATH)
-        self.extractor = dbus.Interface (tracker,
+        self.status_match = self.bus.add_signal_receiver (self._minerfs_status_cb,
+                                                          signal_name="Progress",
+                                                          path=cfg.MINERFS_OBJ_PATH,
+                                                          dbus_interface=cfg.MINER_IFACE)
+        self.timeout_id = glib.timeout_add_seconds (REASONABLE_TIMEOUT, self._timeout_on_idle_cb)
+
+        self.loop.run ()
+
+        glib.source_remove (self.timeout_id)
+        self.bus._clean_up_signal_match (self.status_match)
+
+
+class ExtractorHelper (Helper):
+
+    PROCESS_NAME = 'tracker-extract'
+    BUS_NAME = cfg.TRACKER_EXTRACT_BUSNAME
+
+    def start (self):
+        Helper.start (self)
+
+        bus_object = self.bus.get_object (cfg.TRACKER_EXTRACT_BUSNAME,
+                                          cfg.TRACKER_EXTRACT_OBJ_PATH)
+        self.extractor = dbus.Interface (bus_object,
                                          dbus_interface=cfg.TRACKER_EXTRACT_IFACE)
 
+        # FIXME: interface does not appear straight away
+        time.sleep (0.2)
 
     def get_metadata (self, filename, mime):
         """
@@ -269,10 +467,7 @@ class ExtractorHelper ():
             return results
         else:
             return [line]
-        
-
-        
-            
+       
     def __handle_anon_nodes (self, line):
         """
         Traslates anonymous nodes in 'flat' properties:
@@ -363,4 +558,10 @@ class ExtractorHelper ():
         clean = clean.replace ("\"", "")
             
         return clean.strip ()
-        
+
+
+class WritebackHelper (Helper):
+
+    PROCESS_NAME = 'tracker-writeback'
+    PROCESS_PATH = os.path.join (cfg.EXEC_PREFIX, 'tracker-writeback')
+    BUS_NAME = cfg.WRITEBACK_BUSNAME
diff --git a/tests/functional-tests/common/utils/minertest.py b/tests/functional-tests/common/utils/minertest.py
index fac3b35..5b8f9a2 100644
--- a/tests/functional-tests/common/utils/minertest.py
+++ b/tests/functional-tests/common/utils/minertest.py
@@ -97,10 +97,8 @@ class CommonTrackerMinerTest (ut.TestCase):
             confdir = os.path.join (cfg.DATADIR, "tracker-tests",
                                     "test-configurations", "miner-basic-ops")
         self.system.tracker_miner_fs_testing_start (CONF_OPTIONS)
-        # Returns when ready
-        self.tracker = StoreHelper ()
-        self.tracker.wait ()
-        print "Ready to go!"
+        self.system.tracker_miner_fs_wait_for_idle ()
+        self.tracker = self.system.store
         
     @classmethod
     def tearDownClass (self):
diff --git a/tests/functional-tests/common/utils/storetest.py b/tests/functional-tests/common/utils/storetest.py
index 31a6c33..be16b6c 100644
--- a/tests/functional-tests/common/utils/storetest.py
+++ b/tests/functional-tests/common/utils/storetest.py
@@ -37,8 +37,7 @@ class CommonTrackerStoreTest (ut.TestCase):
             #print "Starting the daemon in test mode"
             self.system = TrackerSystemAbstraction ()
             self.system.tracker_store_testing_start ()
-            self.tracker = StoreHelper ()
-            self.tracker.wait () #Safe guard. Returns when the store is ready
+            self.tracker = self.system.store
 
         @classmethod
         def tearDownClass (self):
diff --git a/tests/functional-tests/common/utils/system.py b/tests/functional-tests/common/utils/system.py
index 4ef0961..6960c0f 100644
--- a/tests/functional-tests/common/utils/system.py
+++ b/tests/functional-tests/common/utils/system.py
@@ -13,6 +13,8 @@ import time
 import options
 from dconf import DConfClient
 
+import helpers
+
 # Don't use /tmp (not enough space there)
 
 # Add this after fixing the backup/restore and ontology changes tests
@@ -33,271 +35,6 @@ REASONABLE_TIMEOUT = 30
 class UnableToBootException (Exception):
     pass
 
-class TrackerStoreLifeCycle ():
-
-    def __init__ (self):
-        self.timeout_id = 0
-        self.available = False
-        
-    def start (self):
-        """
-        call this method to start and instance of tracker-store. It will return when the store is ready
-        """
-        self.loop = gobject.MainLoop()
-        dbus_loop = DBusGMainLoop(set_as_default=True)
-        self.bus = dbus.SessionBus (dbus_loop)
-
-        obj = self.bus.get_object ("org.freedesktop.DBus",
-                                   "/org/freedesktop/DBus")
-        self.admin = dbus.Interface (obj, dbus_interface="org.freedesktop.DBus")
-        if (self.admin.NameHasOwner (cfg.TRACKER_BUSNAME)):
-            raise Exception ("Store is already running! kill it before starting this one")
-
-        self.name_owner_match = self.bus.add_signal_receiver (self.__name_owner_changed_cb,
-                                                         signal_name="NameOwnerChanged",
-                                                         path="/org/freedesktop/DBus",
-                                                         dbus_interface="org.freedesktop.DBus")
-        self.store_proc = self.__start_tracker_store ()
-
-        # It should step out of this loop when the miner is visible in DBus
-        self.loop.run ()
-
-        tracker = self.bus.get_object (cfg.TRACKER_BUSNAME, cfg.TRACKER_OBJ_PATH)
-        tracker_status = self.bus.get_object (cfg.TRACKER_BUSNAME, cfg.TRACKER_STATUS_OBJ_PATH)
-        self.status_iface = dbus.Interface (tracker_status, dbus_interface=cfg.STATUS_IFACE)
-        print "[store] booting..."
-        self.status_iface.Wait ()
-        print "[store] ready."
-
-
-    def stop (self):
-        self.__stop_tracker_store ()
-        if self.available:
-            # It should step out of this loop when the miner disappear from the bus
-            self.timeout_id = glib.timeout_add_seconds (REASONABLE_TIMEOUT, self.__timeout_on_idle)
-            self.loop.run ()
-
-        print "[store] stop."
-        # Disconnect the signals of the next start we get duplicated messages
-        self.bus._clean_up_signal_match (self.name_owner_match)
-
-    def kill (self):
-        self.store_proc.kill ()
-        self.loop.run ()
-        # Name owner changed cb should take us out from this loop
-
-        print "[store] killed."
-        self.bus._clean_up_signal_match (self.name_owner_match)
-
-    def __timeout_on_idle (self):
-        print "[store] Timeout waiting... asumming idle."
-        self.loop.quit ()
-        return False
-
-    def __name_owner_changed_cb (self, name, old_owner, new_owner):
-        if name == cfg.TRACKER_BUSNAME:
-            if old_owner == '' and new_owner != '':
-                print "[store] appears in the bus"
-                self.available = True
-            elif old_owner != ''  and new_owner == '':
-                print "[store] disappears from the bus"
-                self.available = False
-            else:
-                print "[store] name change %s -> %s" % (old_owner, new_owner)
-            self.loop.quit ()
-
-    def __start_tracker_store (self):
-        tracker_binary = os.path.join (cfg.EXEC_PREFIX, "tracker-store")
-        tracker = [tracker_binary]
-        # The env variables can be passed as parameters!
-        FNULL = open('/dev/null', 'w')
-        if options.is_manual_start ():
-            print "Start tracker-store manually"
-        else:
-            return subprocess.Popen (tracker, stdout=FNULL, stderr=FNULL)
-
-    def __stop_tracker_store (self):
-        #control_binary = os.path.join (cfg.BINDIR, "tracker-control")
-        #FNULL = open('/dev/null', 'w')
-        #subprocess.call ([control_binary, "-t"], stdout=FNULL)
-        if options.is_manual_start ():
-            if self.available:
-                print "Kill tracker-store manually"
-                # Quit when disappearing from the bus
-                self.loop.run ()
-        else:
-            self.store_proc.terminate ()
-
-
-class TrackerMinerFsLifeCycle():
-    """
-    Starts and monitors the miner-fs life cycle
-    """
-    def __init__ (self):
-        self.timeout_id = 0
-        self.available = False
-
-    def start (self):
-        """
-        call this method to start and instance of miner-fs. It will return when the miner is 'Idle'
-        after all the initial crawling
-        """
-        self.loop = gobject.MainLoop()
-        dbus_loop = DBusGMainLoop(set_as_default=True)
-        self.bus = dbus.SessionBus (dbus_loop)
-
-        obj = self.bus.get_object ("org.freedesktop.DBus",
-                                   "/org/freedesktop/DBus")
-        self.admin = dbus.Interface (obj, dbus_interface="org.freedesktop.DBus")
-        if (self.admin.NameHasOwner (cfg.MINERFS_BUSNAME)):
-            raise Exception ("Miner is already running! kill it before starting this one")
-
-        self.name_owner_match = self.bus.add_signal_receiver (self.__name_owner_changed_cb,
-                                                         signal_name="NameOwnerChanged",
-                                                         path="/org/freedesktop/DBus",
-                                                         dbus_interface="org.freedesktop.DBus")
-        self.__start_tracker_miner_fs ()
-
-        # It should step out of this loop when the miner is visible in DBus
-        self.loop.run ()
-
-        self.status_match = self.bus.add_signal_receiver (self.__minerfs_status_cb,
-                                                     signal_name="Progress",
-                                                     path=cfg.MINERFS_OBJ_PATH,
-                                                     dbus_interface=cfg.MINER_IFACE)
-        # It should step out of this loop after to "Idle" progress changes
-        self.timeout_id = glib.timeout_add_seconds (REASONABLE_TIMEOUT, self.__timeout_on_idle)
-        self.loop.run ()
-
-
-    def stop (self):
-        self.__stop_tracker_miner_fs ()
-        # It should step out of this loop when the miner disappear from the bus
-        if (self.available):
-            self.timeout_id = glib.timeout_add_seconds (REASONABLE_TIMEOUT, self.__timeout_on_idle)
-            self.loop.run ()
-
-        # Disconnect the signals of the next start we get duplicated messages
-        self.bus._clean_up_signal_match (self.name_owner_match)
-        self.bus._clean_up_signal_match (self.status_match)
-        print "[miner-fs] stop."
-
-
-    def wait_for_idle (self, timeout=REASONABLE_TIMEOUT):
-        # The signal is already connected
-        print "\n[miner-fs] waiting for Idle"
-        self.timeout_id = glib.timeout_add_seconds (timeout, self.__timeout_on_idle)
-        self.loop.run ()
-
-    def __timeout_on_idle (self):
-        print "[miner-fs] timeout... asumming idle"
-        self.loop.quit ()
-        return False
-
-    def __minerfs_status_cb (self, status, progress, remaining_time):
-        print "[miner-fs] status is now", status.encode ("utf-8")
-        if (status == "Idle"):
-            if (self.timeout_id != 0):
-                glib.source_remove (self.timeout_id)
-                self.timeout_id = 0
-            self.loop.quit ()
-
-
-    def __name_owner_changed_cb (self, name, old_owner, new_owner):
-        if name == cfg.MINERFS_BUSNAME:
-            if old_owner == '' and new_owner != '':
-                print "[miner-fs] appears in the bus"
-            elif old_owner != ''  and new_owner == '':
-                print "[miner-fs] disappears from the bus"
-            else:
-                print "[miner-fs] name change %s -> %s" % (old_owner, new_owner)
-            self.loop.quit ()
-
-    def __start_tracker_miner_fs (self):
-        miner_fs_binary = os.path.join (cfg.EXEC_PREFIX, "tracker-miner-fs")
-        FNULL = open ('/dev/null', 'w')
-        if options.is_manual_start ():
-            print "Start tracker-miner-fs manually"
-        else:
-            return subprocess.Popen ([miner_fs_binary], stdout=FNULL, stderr=FNULL)
-
-    def __stop_tracker_miner_fs (self):
-        control_binary = os.path.join (cfg.BINDIR, "tracker-control")
-        FNULL = open('/dev/null', 'w')
-        if options.is_manual_start ():
-            print "Kill miner manually"
-            self.loop.run ()
-        else:
-            subprocess.call ([control_binary, "-t"], stdout=FNULL)
-
-
-class TrackerWritebackLifeCycle():
-    """
-    Starts and monitors the writeback life cycle
-    """
-    def __init__ (self):
-        self.timeout_id = 0
-
-    def start (self):
-        """
-        call this method to start and instance of writeback.
-        It will return when the Writeback object is visible in dbus
-        """
-        self.loop = gobject.MainLoop()
-        dbus_loop = DBusGMainLoop(set_as_default=True)
-        self.bus = dbus.SessionBus (dbus_loop)
-
-        obj = self.bus.get_object ("org.freedesktop.DBus",
-                              "/org/freedesktop/DBus")
-        self.admin = dbus.Interface (obj, dbus_interface="org.freedesktop.DBus")
-        if (self.admin.NameHasOwner (cfg.WRITEBACK_BUSNAME)):
-            raise Exception ("Writeback is already running! kill it before starting this one")
-
-        self.name_owner_match = self.bus.add_signal_receiver (self.__name_owner_changed_cb,
-                                                              signal_name="NameOwnerChanged",
-                                                              path="/org/freedesktop/DBus",
-                                                              dbus_interface="org.freedesktop.DBus")
-        self.__start_tracker_writeback ()
-
-        # It should step out of this loop when the writeback is visible in DBus
-        self.timeout_id = glib.timeout_add_seconds (REASONABLE_TIMEOUT, self.__timeout_on_idle)
-        self.loop.run ()
-
-    def stop (self):
-        assert self.process
-        self.process.kill ()
-        self.bus._clean_up_signal_match (self.name_owner_match)
-        print "[writeback] stop."
-        
-
-    def __name_owner_changed_cb (self, name, old_owner, new_owner):
-        if name == cfg.WRITEBACK_BUSNAME:
-            if old_owner == '' and new_owner != '':
-                print "[writeback] appears in the bus"
-            elif old_owner != ''  and new_owner == '':
-                print "[writeback] disappears from the bus"
-            else:
-                print "[writeback] name change %s -> %s" % (old_owner, new_owner)
-            if (self.timeout_id != 0):
-                glib.source_remove (self.timeout_id)
-                self.timeout_id = 0
-            self.loop.quit ()
-
-    def __timeout_on_idle (self):
-        print "Timeout... asumming idle"
-        self.loop.quit ()
-        return False
-
-    def __start_tracker_writeback (self):
-        writeback_binary = os.path.join (cfg.EXEC_PREFIX, "tracker-writeback")
-        writeback = [writeback_binary]
-        # The env variables can be passed as parameters!
-        FNULL = open('/dev/null', 'w')
-        if options.is_manual_start ():
-            print "Start tracker-writeback manually"
-        else:
-            self.process = subprocess.Popen (writeback, stdout=FNULL, stderr=FNULL)
-
 
 class TrackerSystemAbstraction:
 
@@ -307,10 +44,11 @@ class TrackerSystemAbstraction:
 
         gsettings is a list of triplets (schema, key, value) that will be set/unset in gsetting
         """
+
         assert not gsettings or type(gsettings) is list 
 
         print "[Conf] Setting test environment..."
-        
+
         for var, directory in TEST_ENV_DIRS.iteritems ():
             print "export %s=%s" %(var, directory)
             self.__recreate_directory (directory)
@@ -351,6 +89,7 @@ class TrackerSystemAbstraction:
         if (os.environ.has_key ("TRACKER_DB_ONTOLOGIES_DIR")):
             del os.environ ["TRACKER_DB_ONTOLOGIES_DIR"]
 
+
     def tracker_store_testing_start (self, confdir=None, ontodir=None):
         """
         Stops any previous instance of the store, calls set_up_environment,
@@ -359,7 +98,7 @@ class TrackerSystemAbstraction:
         self.__stop_tracker_processes ()
         self.set_up_environment (confdir, ontodir)
 
-        self.store = TrackerStoreLifeCycle ()
+        self.store = helpers.StoreHelper ()
         self.store.start ()
 
     def tracker_store_start (self):
@@ -408,7 +147,6 @@ class TrackerSystemAbstraction:
         shutil.rmtree (db_location)
         os.mkdir (db_location)
 
-
     def tracker_store_testing_stop (self):
         """
         Stops a running tracker-store and unset all the XDG_*_HOME vars
@@ -427,10 +165,13 @@ class TrackerSystemAbstraction:
         self.set_up_environment (confdir, None)
 
         # Start also the store. DBus autoactivation ignores the env variables.
-        self.store = TrackerStoreLifeCycle ()
+        self.store = helpers.StoreHelper ()
         self.store.start ()
 
-        self.miner_fs = TrackerMinerFsLifeCycle ()
+        self.extractor = helpers.ExtractorHelper ()
+        self.extractor.start ()
+
+        self.miner_fs = helpers.MinerFsHelper ()
         self.miner_fs.start ()
 
     def tracker_miner_fs_wait_for_idle (self, timeout=REASONABLE_TIMEOUT):
@@ -454,7 +195,7 @@ class TrackerSystemAbstraction:
     def tracker_writeback_testing_start (self, confdir=None):
         # Start the miner-fs (and store) and then the writeback process
         self.tracker_miner_fs_testing_start (confdir)
-        self.writeback = TrackerWritebackLifeCycle ()
+        self.writeback = helpers.WritebackHelper ()
         self.writeback.start ()
 
     def tracker_writeback_testing_stop (self):
@@ -479,8 +220,6 @@ class TrackerSystemAbstraction:
         subprocess.call ([control_binary, "-t"], stdout=FNULL)
         time.sleep (1)
 
-
-
     def __recreate_directory (self, directory):
         if (os.path.exists (directory)):
             shutil.rmtree (directory)



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