diff options
author | Sam Thursfield <sam@afuera.me.uk> | 2014-10-14 14:28:02 +0100 |
---|---|---|
committer | Sam Thursfield <sam@afuera.me.uk> | 2014-10-14 14:28:02 +0100 |
commit | c5232aaedec15f1c8637657a3536c492bc1aba02 (patch) | |
tree | 3ae8b92795fd5b5004266d8102f5cf91f36e25e0 | |
parent | 3eb4d28922902ae7ee46a7882d7d846428eebe9f (diff) | |
parent | 85666d5dc1e662be783707d4186f4b3019074cb9 (diff) | |
download | tracker-c5232aaedec15f1c8637657a3536c492bc1aba02.tar.gz |
Merge branch 'sam/functional-test-fixes'
-rw-r--r-- | src/tracker-writeback/tracker-writeback-file.c | 12 | ||||
-rwxr-xr-x | tests/functional-tests/300-miner-basic-ops.py | 39 | ||||
-rwxr-xr-x | tests/functional-tests/310-fts-indexing.py | 9 | ||||
-rwxr-xr-x | tests/functional-tests/500-writeback.py | 16 | ||||
-rwxr-xr-x | tests/functional-tests/501-writeback-details.py | 19 | ||||
-rwxr-xr-x | tests/functional-tests/600-applications-camera.py | 16 | ||||
-rwxr-xr-x | tests/functional-tests/601-applications-sync.py | 4 | ||||
-rw-r--r-- | tests/functional-tests/common/utils/extractor.py | 4 | ||||
-rw-r--r-- | tests/functional-tests/common/utils/helpers.py | 173 | ||||
-rw-r--r-- | tests/functional-tests/common/utils/minertest.py | 72 | ||||
-rw-r--r-- | tests/functional-tests/common/utils/system.py | 7 | ||||
-rw-r--r-- | tests/functional-tests/common/utils/writebacktest.py | 52 |
12 files changed, 221 insertions, 202 deletions
diff --git a/src/tracker-writeback/tracker-writeback-file.c b/src/tracker-writeback/tracker-writeback-file.c index f00d6685a..60fc250e5 100644 --- a/src/tracker-writeback/tracker-writeback-file.c +++ b/src/tracker-writeback/tracker-writeback-file.c @@ -257,18 +257,12 @@ tracker_writeback_file_update_metadata (TrackerWriteback *writeback, /* Delete the temporary file and preserve original */ g_file_delete (tmp_file, NULL, NULL); } else { - GError *m_error = NULL; - /* Move back the modified file to the original location */ + /* Move back the modified file to the original location. Correct UNIX + * mode has been set for tmp_file in create_temporary_file() already. + */ g_file_move (tmp_file, file, G_FILE_COPY_OVERWRITE, NULL, NULL, NULL, NULL); - /* Set file attributes on tmp_file using file_info of original file */ - g_file_set_attributes_from_info (tmp_file, file_info, 0, NULL, &m_error); - if (m_error) { - g_warning ("Can't restore permissions of original file for %s", - row[0]); - g_error_free (m_error); - } } g_object_unref (file_info); diff --git a/tests/functional-tests/300-miner-basic-ops.py b/tests/functional-tests/300-miner-basic-ops.py index c8875607f..97259976c 100755 --- a/tests/functional-tests/300-miner-basic-ops.py +++ b/tests/functional-tests/300-miner-basic-ops.py @@ -109,7 +109,8 @@ class MinerCrawlTest (CommonTrackerMinerTest): source = os.path.join (MINER_TMP_DIR, "test-no-monitored", "file0.txt") dest = os.path.join (MINER_TMP_DIR, "test-monitored", "file0.txt") shutil.copyfile (source, dest) - self.system.tracker_miner_fs_wait_for_idle () + + dest_id, dest_urn = self.system.store.await_resource_inserted ('nfo:TextDocument', uri(dest)) # verify if miner indexed this file. result = self.__get_text_documents () @@ -123,7 +124,7 @@ class MinerCrawlTest (CommonTrackerMinerTest): # Clean the new file so the test directory is as before log ("Remove and wait") os.remove (dest) - self.system.tracker_miner_fs_wait_for_idle () + self.system.store.await_resource_deleted (dest_id) def test_03_copy_from_monitored_to_unmonitored (self): """ @@ -155,7 +156,8 @@ class MinerCrawlTest (CommonTrackerMinerTest): source = os.path.join (MINER_TMP_DIR, "test-monitored", "file1.txt") dest = os.path.join (MINER_TMP_DIR, "test-monitored", "dir1", "dir2", "file-test04.txt") shutil.copyfile (source, dest) - self.system.tracker_miner_fs_wait_for_idle () + + dest_id, dest_urn = self.system.store.await_resource_inserted ('nfo:TextDocument', uri(dest)) result = self.__get_text_documents () self.assertEquals (len (result), 4) @@ -167,7 +169,7 @@ class MinerCrawlTest (CommonTrackerMinerTest): # Clean the file os.remove (dest) - self.system.tracker_miner_fs_wait_for_idle () + self.system.store.await_resource_deleted (dest_id) self.assertEquals (3, self.tracker.count_instances ("nfo:TextDocument")) @@ -178,7 +180,7 @@ class MinerCrawlTest (CommonTrackerMinerTest): source = os.path.join (MINER_TMP_DIR, "test-no-monitored", "file0.txt") dest = os.path.join (MINER_TMP_DIR, "test-monitored", "dir1", "file-test05.txt") shutil.move (source, dest) - self.system.tracker_miner_fs_wait_for_idle () + dest_id, dest_urn = self.system.store.await_resource_inserted ('nfo:TextDocument', uri(dest)) result = self.__get_text_documents () self.assertEquals (len (result), 4) @@ -190,7 +192,7 @@ class MinerCrawlTest (CommonTrackerMinerTest): # Clean the file os.remove (dest) - self.system.tracker_miner_fs_wait_for_idle () + self.system.store.await_resource_deleted (dest_id) self.assertEquals (3, self.tracker.count_instances ("nfo:TextDocument")) ## """ move operation and tracker-miner response test cases """ @@ -203,8 +205,9 @@ class MinerCrawlTest (CommonTrackerMinerTest): """ source = os.path.join (MINER_TMP_DIR, "test-monitored", "dir1", "file2.txt") dest = os.path.join (MINER_TMP_DIR, "test-no-monitored", "file2.txt") + source_id = self.system.store.get_resource_id (uri(dest)) shutil.move (source, dest) - self.system.tracker_miner_fs_wait_for_idle () + self.system.store.await_resource_deleted (source_id) result = self.__get_text_documents () self.assertEquals (len (result), 2) @@ -214,7 +217,7 @@ class MinerCrawlTest (CommonTrackerMinerTest): # Restore the file shutil.move (dest, source) - self.system.tracker_miner_fs_wait_for_idle () + self.system.store.await_resource_inserted ('nfo:TextDocument', uri(dest)) self.assertEquals (3, self.tracker.count_instances ("nfo:TextDocument")) @@ -230,7 +233,7 @@ class MinerCrawlTest (CommonTrackerMinerTest): self.assertEquals (source_dir_urn, parent_before) shutil.move (source, dest) - self.system.tracker_miner_fs_wait_for_idle () + self.system.store.await_resource_inserted ('nfo:TextDocument', uri(dest)) # Checking fix for NB#214413: After a move operation, nfo:belongsToContainer # should be changed to the new one @@ -248,7 +251,7 @@ class MinerCrawlTest (CommonTrackerMinerTest): # Restore the file shutil.move (dest, source) - self.system.tracker_miner_fs_wait_for_idle () + self.system.store.await_resource_inserted ('nfo:TextDocument', uri(source)) result = self.__get_text_documents () self.assertEquals (len (result), 3) @@ -261,8 +264,9 @@ class MinerCrawlTest (CommonTrackerMinerTest): Delete one of the files """ victim = os.path.join (MINER_TMP_DIR, "test-monitored", "dir1", "file2.txt") + victim_id = self.system.store.get_resource_id (uri(victim)) os.remove (victim) - self.system.tracker_miner_fs_wait_for_idle () + self.system.store.await_resource_deleted (victim_id) result = self.__get_text_documents () self.assertEquals (len (result), 2) @@ -274,15 +278,16 @@ class MinerCrawlTest (CommonTrackerMinerTest): f = open (victim, "w") f.write ("Don't panic, everything is fine") f.close () - self.system.tracker_miner_fs_wait_for_idle () + self.system.store.await_resource_inserted ('nfo:TextDocument', uri(victim)) def test_09_deletion_directory (self): """ Delete a directory """ victim = os.path.join (MINER_TMP_DIR, "test-monitored", "dir1") + victim_id = self.system.store.get_resource_id (uri(victim)) shutil.rmtree (victim) - self.system.tracker_miner_fs_wait_for_idle () + self.system.store.await_resource_deleted (victim_id) result = self.__get_text_documents () self.assertEquals (len (result), 1) @@ -290,21 +295,15 @@ class MinerCrawlTest (CommonTrackerMinerTest): self.assertIn ( uri ("test-monitored/file1.txt"), unpacked_result) # Restore the dirs - # Wait after each operation to be sure of the results os.makedirs (os.path.join (MINER_TMP_DIR, "test-monitored", "dir1")) - self.system.tracker_miner_fs_wait_for_idle () os.makedirs (os.path.join (MINER_TMP_DIR, "test-monitored", "dir1", "dir2")) - self.system.tracker_miner_fs_wait_for_idle () for f in ["test-monitored/dir1/file2.txt", "test-monitored/dir1/dir2/file3.txt"]: filename = os.path.join (MINER_TMP_DIR, f) writer = open (filename, "w") writer.write ("Don't panic, everything is fine") writer.close () - self.system.tracker_miner_fs_wait_for_idle () - - # Wait a bit more... some time one idle is not enough - self.system.tracker_miner_fs_wait_for_idle (3) + self.system.store.await_resource_inserted ('nfo:TextDocument', uri(f)) # Check everything is fine result = self.__get_text_documents () diff --git a/tests/functional-tests/310-fts-indexing.py b/tests/functional-tests/310-fts-indexing.py index 99db45d1c..33e2adf1b 100755 --- a/tests/functional-tests/310-fts-indexing.py +++ b/tests/functional-tests/310-fts-indexing.py @@ -48,8 +48,7 @@ class CommonMinerFTS (CommonTrackerMinerTest): os.remove (path (self.testfile)) self.tracker.await_resource_deleted (id) self.tracker.reset_graph_updates_tracking () - # Shouldn't we wait here for the miner to idle? (it works without it) - + def tearDown (self): #if os.path.exists (path (self.testfile)): # os.remove (path (self.testfile)) @@ -60,7 +59,8 @@ class CommonMinerFTS (CommonTrackerMinerTest): f.write (text) f.close () self.tracker.await_resource_inserted (rdf_class = 'nfo:Document', - url = uri (self.testfile)) + url = uri (self.testfile), + required_property = 'nie:plainTextContent') self.tracker.reset_graph_updates_tracking () def search_word (self, word): @@ -251,9 +251,6 @@ class MinerFTSFileOperationsTest (CommonMinerFTS): Move file from unmonitored location to monitored location and index should be updated """ - # Maybe the miner hasn't finished yet with the setUp deletion! - self.system.tracker_miner_fs_wait_for_idle () - TEXT = "airplane is beautiful" TEST_16_SOURCE = "test-no-monitored/fts-indexing-text-16.txt" TEST_16_DEST = "test-monitored/fts-indexing-text-16.txt" diff --git a/tests/functional-tests/500-writeback.py b/tests/functional-tests/500-writeback.py index cd144a7e1..cdd2b06ab 100755 --- a/tests/functional-tests/500-writeback.py +++ b/tests/functional-tests/500-writeback.py @@ -24,6 +24,7 @@ on the files. Note that these tests are highly platform dependant. import os, dbus import time +from common.utils.extractor import get_tracker_extract_output from common.utils.writebacktest import CommonTrackerWritebackTest as CommonTrackerWritebackTest import unittest2 as ut from common.utils.expectedFailure import expectedFailureBug @@ -69,6 +70,10 @@ class WritebackBasicDataTest (CommonTrackerWritebackTest): the @prop is used. """ + # FIXME: filename is actually a URI! :( + filename_real = filename[len('file://'):] + initial_mtime = os.stat(filename_real).st_mtime + TEST_VALUE = prop.replace (":","") + "test" SPARQL_TMPL = """ INSERT { ?u %s '%s' } @@ -76,11 +81,10 @@ class WritebackBasicDataTest (CommonTrackerWritebackTest): """ self.__clean_property (prop, filename) self.tracker.update (SPARQL_TMPL % (prop, TEST_VALUE, filename)) - - # There is no way to know when the operation is finished - time.sleep (REASONABLE_TIMEOUT) - - results = self.extractor.get_metadata (filename, mimetype) + + self.wait_for_file_change(filename_real, initial_mtime) + + results = get_tracker_extract_output (filename, mimetype) keyDict = expectedKey or prop self.assertIn (TEST_VALUE, results[keyDict]) self.__clean_property (prop, filename, False) @@ -112,7 +116,7 @@ class WritebackBasicDataTest (CommonTrackerWritebackTest): time.sleep (REASONABLE_TIMEOUT) - results = self.extractor.get_metadata (filename, mimetype) + results = get_tracker_extract_output (filename, mimetype) self.assertIn ("testTag", results ["nao:hasTag"]) diff --git a/tests/functional-tests/501-writeback-details.py b/tests/functional-tests/501-writeback-details.py index 62da5fc4e..856f69848 100755 --- a/tests/functional-tests/501-writeback-details.py +++ b/tests/functional-tests/501-writeback-details.py @@ -18,13 +18,16 @@ # Boston, MA 02110-1301, USA. # from common.utils.writebacktest import CommonTrackerWritebackTest as CommonTrackerWritebackTest +from common.utils.extractor import get_tracker_extract_output from common.utils.helpers import log import unittest2 as ut from common.utils.expectedFailure import expectedFailureBug +import os import time REASONABLE_TIMEOUT = 5 # Seconds we wait for tracker-writeback to do the work + class WritebackKeepDateTest (CommonTrackerWritebackTest): def setUp (self): @@ -62,7 +65,12 @@ class WritebackKeepDateTest (CommonTrackerWritebackTest): log ("Waiting 2 seconds to ensure there is a noticiable difference in the timestamp") time.sleep (2) - + + url = self.get_test_filename_jpeg () + + filename = url[len('file://'):] + initial_mtime = os.stat(filename).st_mtime + # This triggers the writeback mark_as_favorite = """ INSERT { @@ -70,13 +78,14 @@ class WritebackKeepDateTest (CommonTrackerWritebackTest): } WHERE { ?u nie:url <%s> . } - """ % (self.get_test_filename_jpeg ()) + """ % url self.tracker.update (mark_as_favorite) - log ("Setting favorite in <%s>" % (self.get_test_filename_jpeg ())) - time.sleep (REASONABLE_TIMEOUT) + log ("Setting favorite in <%s>" % url) + + self.wait_for_file_change (filename, initial_mtime) # Check the value is written in the file - metadata = self.extractor.get_metadata (self.get_test_filename_jpeg (), "") + metadata = get_tracker_extract_output (filename, "") self.assertIn (self.favorite, metadata ["nao:hasTag"], "Tag hasn't been written in the file") diff --git a/tests/functional-tests/600-applications-camera.py b/tests/functional-tests/600-applications-camera.py index 126ebd75d..f793665c5 100755 --- a/tests/functional-tests/600-applications-camera.py +++ b/tests/functional-tests/600-applications-camera.py @@ -85,13 +85,13 @@ class TrackerCameraPicturesApplicationTests (CommonTrackerApplicationTest): # Copy the image to the dest path self.slowcopy_file (origin_filepath, dest_filepath) assert os.path.exists (dest_filepath) - self.system.tracker_miner_fs_wait_for_idle (MINER_FS_IDLE_TIMEOUT) + dest_id, dest_urn = self.system.store.await_resource_inserted ('nmm:Photo', dest_fileuri) self.assertEquals (self.get_urn_count_by_url (dest_fileuri), 1) # Clean the new file so the test directory is as before log ("Remove and wait") os.remove (dest_filepath) - self.system.tracker_miner_fs_wait_for_idle (MINER_FS_IDLE_TIMEOUT) + self.system.store.await_resource_deleted (dest_id) self.assertEquals (self.get_urn_count_by_url (dest_fileuri), 0) @@ -171,13 +171,13 @@ class TrackerCameraPicturesApplicationTests (CommonTrackerApplicationTest): assert os.path.exists (dest_filepath) # FOURTH, ensure we have only 1 resource - self.system.tracker_miner_fs_wait_for_idle (MINER_FS_IDLE_TIMEOUT) + dest_id, dest_urn = self.system.store.await_resource_inserted ('nmm:Photo', dest_fileuri) self.assertEquals (self.get_urn_count_by_url (dest_fileuri), 1) # Clean the new file so the test directory is as before log ("Remove and wait") os.remove (dest_filepath) - self.system.tracker_miner_fs_wait_for_idle (MINER_FS_IDLE_TIMEOUT) + self.system.store.await_resource_deleted (dest_id) self.assertEquals (self.get_urn_count_by_url (dest_fileuri), 0) @@ -228,13 +228,13 @@ class TrackerCameraVideosApplicationTests (CommonTrackerApplicationTest): # Copy the image to the dest path self.slowcopy_file (origin_filepath, dest_filepath) assert os.path.exists (dest_filepath) - self.system.tracker_miner_fs_wait_for_idle (MINER_FS_IDLE_TIMEOUT) + dest_id, dest_urn = self.system.store.await_resource_inserted ('nmm:Video', dest_fileuri) self.assertEquals (self.get_urn_count_by_url (dest_fileuri), 1) # Clean the new file so the test directory is as before log ("Remove and wait") os.remove (dest_filepath) - self.system.tracker_miner_fs_wait_for_idle (MINER_FS_IDLE_TIMEOUT) + self.system.store.await_resource_deleted (dest_id) self.assertEquals (self.get_urn_count_by_url (dest_fileuri), 0) @@ -314,13 +314,13 @@ class TrackerCameraVideosApplicationTests (CommonTrackerApplicationTest): assert os.path.exists (dest_filepath) # FOURTH, ensure we have only 1 resource - self.system.tracker_miner_fs_wait_for_idle (MINER_FS_IDLE_TIMEOUT) + dest_id, dest_urn = self.system.store.await_resource_inserted ('nmm:Video', dest_fileuri) self.assertEquals (self.get_urn_count_by_url (dest_fileuri), 1) # Clean the new file so the test directory is as before log ("Remove and wait") os.remove (dest_filepath) - self.system.tracker_miner_fs_wait_for_idle (MINER_FS_IDLE_TIMEOUT) + self.system.store.await_resource_deleted (dest_id) self.assertEquals (self.get_urn_count_by_url (dest_fileuri), 0) if __name__ == "__main__": diff --git a/tests/functional-tests/601-applications-sync.py b/tests/functional-tests/601-applications-sync.py index 2dc753ca3..26dad9558 100755 --- a/tests/functional-tests/601-applications-sync.py +++ b/tests/functional-tests/601-applications-sync.py @@ -36,7 +36,6 @@ import unittest2 as ut from common.utils.applicationstest import CommonTrackerApplicationTest as CommonTrackerApplicationTest from common.utils.helpers import log -MINER_FS_IDLE_TIMEOUT = 30 class TrackerSyncApplicationTests (CommonTrackerApplicationTest): @@ -91,13 +90,12 @@ class TrackerSyncApplicationTests (CommonTrackerApplicationTest): # Copy the image to the dest path self.slowcopy_file (origin_filepath, dest_filepath) assert os.path.exists (dest_filepath) - self.system.tracker_miner_fs_wait_for_idle (MINER_FS_IDLE_TIMEOUT) + self.tracker.await_resource_inserted ('nmm:MusicPiece', url=dest_fileuri) self.assertEquals (self.get_urn_count_by_url (dest_fileuri), 1) # Clean the new file so the test directory is as before log ("Remove and wait") os.remove (dest_filepath) - self.system.tracker_miner_fs_wait_for_idle (MINER_FS_IDLE_TIMEOUT) self.assertEquals (self.get_urn_count_by_url (dest_fileuri), 0) if __name__ == "__main__": diff --git a/tests/functional-tests/common/utils/extractor.py b/tests/functional-tests/common/utils/extractor.py index 183a91352..8dd05604e 100644 --- a/tests/functional-tests/common/utils/extractor.py +++ b/tests/functional-tests/common/utils/extractor.py @@ -253,13 +253,15 @@ class ExtractorParser(object): return clean.strip () -def get_tracker_extract_output(filename): +def get_tracker_extract_output(filename, mime_type=None): """ Runs `tracker-extract --file` to extract metadata from a file. """ tracker_extract = os.path.join (cfg.EXEC_PREFIX, 'tracker-extract') command = [tracker_extract, '--file', filename] + if mime_type is not None: + command.extend(['--mime', mime_type]) try: log ('Running: %s' % ' '.join(command)) diff --git a/tests/functional-tests/common/utils/helpers.py b/tests/functional-tests/common/utils/helpers.py index 16afa82ce..494deba2e 100644 --- a/tests/functional-tests/common/utils/helpers.py +++ b/tests/functional-tests/common/utils/helpers.py @@ -282,30 +282,48 @@ class StoreHelper (Helper): """ Process notifications from tracker-store on resource changes. """ - matched = False + exit_loop = False + if inserts_list is not None: if self.inserts_match_function is not None: # The match function will remove matched entries from the list - (matched, inserts_list) = self.inserts_match_function (inserts_list) + (exit_loop, inserts_list) = self.inserts_match_function (inserts_list) self.inserts_list += inserts_list if deletes_list is not None: if self.deletes_match_function is not None: - (matched, deletes_list) = self.deletes_match_function (deletes_list) + (exit_loop, deletes_list) = self.deletes_match_function (deletes_list) self.deletes_list += deletes_list - def await_resource_inserted (self, rdf_class, url = None, title = None): + if exit_loop: + GLib.source_remove(self.graph_updated_timeout_id) + self.graph_updated_timeout_id = 0 + self.loop.quit () + + def _enable_await_timeout (self): + self.graph_updated_timeout_id = GLib.timeout_add_seconds (REASONABLE_TIMEOUT, + self._graph_updated_timeout_cb) + + def await_resource_inserted (self, rdf_class, url = None, title = None, required_property = None): """ Block until a resource matching the parameters becomes available """ assert (self.inserts_match_function == None) - def match_cb (inserts_list, in_main_loop = True): - matched = False - filtered_list = [] - known_subjects = set () + self.matched_resource_urn = None + self.matched_resource_id = None + + log ("Await new %s (%i existing inserts)" % (rdf_class, len (self.inserts_list))) - #print "Got inserts: ", inserts_list, "\n" + if required_property is not None: + required_property_id = self.get_resource_id_by_uri(required_property) + log ("Required property %s id %i" % (required_property, required_property_id)) + + known_subjects = set () + def find_resource_insertion (inserts_list): + matched_creation = (self.matched_resource_id is not None) + matched_required_property = False + remaining_events = [] # FIXME: this could be done in an easier way: build one query that filters # based on every subject id in inserts_list, and returns the id of the one @@ -313,7 +331,7 @@ class StoreHelper (Helper): for insert in inserts_list: id = insert[1] - if not matched and id not in known_subjects: + if not matched_creation and id not in known_subjects: known_subjects.add (id) where = " ?urn a %s " % rdf_class @@ -325,87 +343,85 @@ class StoreHelper (Helper): where += "; nie:title \"%s\"" % title query = "SELECT ?urn WHERE { %s FILTER (tracker:id(?urn) = %s)}" % (where, insert[1]) - #print "%s\n" % query result_set = self.query (query) - #print result_set, "\n\n" if len (result_set) > 0: - matched = True + matched_creation = True self.matched_resource_urn = result_set[0][0] self.matched_resource_id = insert[1] + log ("Matched creation of resource %s (%i)" % + (self.matched_resource_urn, + self.matched_resource_id)) + if required_property is not None: + log ("Waiting for property %s (%i) to be set" % + (required_property, required_property_id)) - if not matched or id != self.matched_resource_id: - filtered_list += [insert] + if required_property is not None and matched_creation and not matched_required_property: + if id == self.matched_resource_id and insert[2] == required_property_id: + matched_required_property = True + log ("Matched %s %s" % (self.matched_resource_urn, required_property)) - if matched and in_main_loop: - GLib.source_remove (self.graph_updated_timeout_id) - self.graph_updated_timeout_id = 0 - self.inserts_match_function = None - self.loop.quit () + if not matched_creation or id != self.matched_resource_id: + remaining_events += [insert] - return (matched, filtered_list) + matched = matched_creation if required_property is None else matched_required_property + return matched, remaining_events - - self.matched_resource_urn = None - self.matched_resource_id = None - - log ("Await new %s (%i existing inserts)" % (rdf_class, len (self.inserts_list))) + def match_cb (inserts_list): + matched, remaining_events = find_resource_insertion (inserts_list) + exit_loop = matched + return exit_loop, remaining_events # Check the list of previously received events for matches - (existing_match, self.inserts_list) = match_cb (self.inserts_list, False) + (existing_match, self.inserts_list) = find_resource_insertion (self.inserts_list) if not existing_match: - self.graph_updated_timeout_id = GLib.timeout_add_seconds (REASONABLE_TIMEOUT, - self._graph_updated_timeout_cb) + self._enable_await_timeout () self.inserts_match_function = match_cb - # Run the event loop until the correct notification arrives self.loop.run () + self.inserts_match_function = None if self.graph_updated_timed_out: raise Exception ("Timeout waiting for resource: class %s, URL %s, title %s" % (rdf_class, url, title)) return (self.matched_resource_id, self.matched_resource_urn) - def await_resource_deleted (self, id, fail_message = None): """ Block until we are notified of a resources deletion """ assert (self.deletes_match_function == None) - def match_cb (deletes_list, in_main_loop = True): - matched = False - filtered_list = [] + def find_resource_deletion (deletes_list): + log ("find_resource_deletion: looking for %i in %s" % (id, deletes_list)) - #print "Looking for %i in " % id, deletes_list, "\n" + matched = False + remaining_events = [] for delete in deletes_list: if delete[1] == id: matched = True else: - filtered_list += [delete] - - if matched and in_main_loop: - GLib.source_remove (self.graph_updated_timeout_id) - self.graph_updated_timeout_id = 0 - self.deletes_match_function = None + remaining_events += [delete] - self.loop.quit () + return matched, remaining_events - return (matched, filtered_list) + def match_cb (deletes_list): + matched, remaining_events = find_resource_deletion(deletes_list) + exit_loop = matched + return exit_loop, remaining_events log ("Await deletion of %i (%i existing)" % (id, len (self.deletes_list))) - (existing_match, self.deletes_list) = match_cb (self.deletes_list, False) + (existing_match, self.deletes_list) = find_resource_deletion (self.deletes_list) if not existing_match: - self.graph_updated_timeout_id = GLib.timeout_add_seconds (REASONABLE_TIMEOUT, - self._graph_updated_timeout_cb) + self._enable_await_timeout () self.deletes_match_function = match_cb - # Run the event loop until the correct notification arrives self.loop.run () + self.deletes_match_function = None if self.graph_updated_timed_out: if fail_message is not None: @@ -496,6 +512,32 @@ class StoreHelper (Helper): else: return -1 + def get_resource_id_by_uri(self, uri): + """ + Get the internal ID for a given resource, identified by URI. + """ + result = self.query( + 'SELECT tracker:id(%s) WHERE { }' % uri) + if len(result) == 1: + return int (result [0][0]) + elif len(result) == 0: + raise Exception ("No entry for resource %s" % uri) + else: + raise Exception ("Multiple entries for resource %s" % uri) + + # FIXME: rename to get_resource_id_by_nepomuk_url !! + def get_resource_id(self, url): + """ + Get the internal ID for a given resource, identified by URL. + """ + result = self.query( + 'SELECT tracker:id(?r) WHERE { ?r nie:url "%s" }' % url) + if len(result) == 1: + return int (result [0][0]) + elif len(result) == 0: + raise Exception ("No entry for resource %s" % url) + else: + raise Exception ("Multiple entries for resource %s" % url) def ask (self, ask_query): assert ask_query.strip ().startswith ("ASK") @@ -537,24 +579,9 @@ class MinerFsHelper (Helper): return False - def _minerfs_status_cb (self, status, progress, remaining_time): - 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 () - if self.timeout_id is not None: - 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, @@ -563,28 +590,6 @@ class MinerFsHelper (Helper): def stop (self): Helper.stop (self) - self.bus._clean_up_signal_match (self.status_match) - - def ignore (self, filelist): - self.miner_fs.IgnoreNextUpdate (filelist) - - def wait_for_idle (self, timeout=REASONABLE_TIMEOUT): - """ - Block until the miner has finished crawling and its status becomes "Idle" - """ - - 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 () - - if self.timeout_id is not None: - GLib.source_remove (self.timeout_id) - self.bus._clean_up_signal_match (self.status_match) - class ExtractorHelper (Helper): diff --git a/tests/functional-tests/common/utils/minertest.py b/tests/functional-tests/common/utils/minertest.py index 7111d8656..113eca937 100644 --- a/tests/functional-tests/common/utils/minertest.py +++ b/tests/functional-tests/common/utils/minertest.py @@ -19,13 +19,14 @@ # from common.utils import configuration as cfg from common.utils.system import TrackerSystemAbstraction -from common.utils.helpers import StoreHelper import unittest2 as ut from gi.repository import GLib import shutil import os +import warnings +from itertools import chain MINER_TMP_DIR = cfg.TEST_MONITORED_TMP_DIR @@ -66,47 +67,46 @@ class CommonTrackerMinerTest (ut.TestCase): # ~/test-no-monitored/ # /file0.txt # - - for d in ["test-monitored", - "test-monitored/dir1", - "test-monitored/dir1/dir2", - "test-no-monitored"]: - directory = os.path.join (MINER_TMP_DIR, d) - if (os.path.exists (directory)): - shutil.rmtree (directory) - os.makedirs (directory) - - for tf in ["test-monitored/file1.txt", - "test-monitored/dir1/file2.txt", - "test-monitored/dir1/dir2/file3.txt", - "test-no-monitored/file0.txt"]: - testfile = os.path.join (MINER_TMP_DIR, tf) - if (os.path.exists (testfile)): - os.remove (testfile) - f = open (testfile, 'w') - f.write (DEFAULT_TEXT) - f.close () - - + + monitored_files = [ + 'test-monitored/file1.txt', + 'test-monitored/dir1/file2.txt', + 'test-monitored/dir1/dir2/file3.txt' + ] + + unmonitored_files = [ + 'test-no-monitored/file0.txt' + ] + + def ensure_dir_exists(dirname): + if not os.path.exists(dirname): + os.makedirs(dirname) + + for tf in chain(monitored_files, unmonitored_files): + testfile = path(tf) + ensure_dir_exists(os.path.dirname(testfile)) + with open (testfile, 'w') as f: + f.write (DEFAULT_TEXT) + + for tf in monitored_files: + self.tracker.await_resource_inserted( + 'nfo:TextDocument', url=uri(tf)) + @classmethod def setUpClass (self): - #print "Starting the daemon in test mode" - self.__prepare_directories () - + for d in ['test-monitored', 'test-no-monitored']: + dirname = path(d) + if os.path.exists (dirname): + shutil.rmtree(dirname) + os.makedirs(dirname) + self.system = TrackerSystemAbstraction () - if (os.path.exists (os.getcwd() + "/test-configurations/miner-basic-ops")): - # Use local directory if available - confdir = os.getcwd() + "/test-configurations/miner-basic-ops" - else: - confdir = os.path.join (cfg.DATADIR, "tracker-tests", - "test-configurations", "miner-basic-ops") self.system.tracker_miner_fs_testing_start (CONF_OPTIONS) - self.system.tracker_miner_fs_wait_for_idle () self.tracker = self.system.store - + + self.__prepare_directories () + @classmethod def tearDownClass (self): - #print "Stopping the daemon in test mode (Doing nothing now)" self.system.tracker_miner_fs_testing_stop () - diff --git a/tests/functional-tests/common/utils/system.py b/tests/functional-tests/common/utils/system.py index 8759750a3..16540c7e4 100644 --- a/tests/functional-tests/common/utils/system.py +++ b/tests/functional-tests/common/utils/system.py @@ -178,13 +178,6 @@ class TrackerSystemAbstraction: self.miner_fs = helpers.MinerFsHelper () self.miner_fs.start () - def tracker_miner_fs_wait_for_idle (self, timeout=REASONABLE_TIMEOUT): - """ - Copy the files physically in the filesyste and wait for the miner to complete the work - """ - self.miner_fs.wait_for_idle (timeout) - - def tracker_miner_fs_testing_stop (self): """ Stops the miner-fs and store running and unset all the XDG_*_HOME vars diff --git a/tests/functional-tests/common/utils/writebacktest.py b/tests/functional-tests/common/utils/writebacktest.py index 927dad394..ce6f2c7f4 100644 --- a/tests/functional-tests/common/utils/writebacktest.py +++ b/tests/functional-tests/common/utils/writebacktest.py @@ -51,22 +51,11 @@ def uri (filename): class CommonTrackerWritebackTest (ut.TestCase): """ Superclass to share methods. Shouldn't be run by itself. - Start all processes including writeback, miner pointing to HOME/test-writeback-monitored + Start all processes including writeback, miner pointing to WRITEBACK_TMP_DIR """ @classmethod def __prepare_directories (self): - # - # ~/test-writeback-monitored/ - # - - for d in ["test-writeback-monitored"]: - directory = os.path.join (WRITEBACK_TMP_DIR, d) - if (os.path.exists (directory)): - shutil.rmtree (directory) - os.makedirs (directory) - - if (os.path.exists (os.getcwd() + "/test-writeback-data")): # Use local directory if available datadir = os.getcwd() + "/test-writeback-data" @@ -78,9 +67,8 @@ class CommonTrackerWritebackTest (ut.TestCase): origin = os.path.join (datadir, testfile) log ("Copying %s -> %s" % (origin, WRITEBACK_TMP_DIR)) shutil.copy (origin, WRITEBACK_TMP_DIR) - time.sleep (2) - + @classmethod def setUpClass (self): #print "Starting the daemon in test mode" @@ -89,6 +77,18 @@ class CommonTrackerWritebackTest (ut.TestCase): self.system = TrackerSystemAbstraction () self.system.tracker_writeback_testing_start (CONF_OPTIONS) + + def await_resource_extraction(url): + # Make sure a resource has been crawled by the FS miner and by + # tracker-extract. The extractor adds nie:contentCreated for + # image resources, so know once this property is set the + # extraction is complete. + self.system.store.await_resource_inserted('nfo:Image', url=url, required_property='nie:contentCreated') + + await_resource_extraction (self.get_test_filename_jpeg()) + await_resource_extraction (self.get_test_filename_tiff()) + await_resource_extraction (self.get_test_filename_png()) + # Returns when ready log ("Ready to go!") @@ -98,11 +98,29 @@ class CommonTrackerWritebackTest (ut.TestCase): self.system.tracker_writeback_testing_stop () - def get_test_filename_jpeg (self): + @staticmethod + def get_test_filename_jpeg (): return uri (TEST_FILE_JPEG) - def get_test_filename_tiff (self): + @staticmethod + def get_test_filename_tiff (): return uri (TEST_FILE_TIFF) - def get_test_filename_png (self): + @staticmethod + def get_test_filename_png (): return uri (TEST_FILE_PNG) + + def get_mtime (self, filename): + return os.stat(filename).st_mtime + + def wait_for_file_change (self, filename, initial_mtime): + start = time.time() + while time.time() < start + 5: + mtime = os.stat(filename).st_mtime + if mtime > initial_mtime: + return + time.sleep(0.2) + + raise Exception( + "Timeout waiting for %s to be updated (mtime has not changed)" % + filename) |