class CommonTrackerStoreTest(ut.TestCase): """ Common superclass for tests that just require a fresh store running """ @classmethod def setUpClass(self): self.system = TrackerSystemAbstraction() self.system.tracker_store_testing_start() self.tracker = self.system.store @classmethod def tearDownClass(self): self.system.finish()
class CommonTrackerMinerTest(ut.TestCase): def setUp(self): self.workdir = cfg.create_monitored_test_dir() self.indexed_dir = os.path.join(self.workdir, 'test-monitored') # It's important that this directory exists BEFORE we start Tracker: # it won't monitor an indexing root for changes if it doesn't exist, # it'll silently ignore it instead. See the tracker_crawler_start() # function. ensure_dir_exists(self.indexed_dir) self.system = TrackerSystemAbstraction( settings={ 'org.freedesktop.Tracker.Store': { 'graphupdated-delay': GLib.Variant('i', 100) } }) config = { cfg.DCONF_MINER_SCHEMA: { 'index-recursive-directories': GLib.Variant.new_strv([self.indexed_dir]), 'index-single-directories': GLib.Variant.new_strv([]), 'index-optical-discs': GLib.Variant.new_boolean(False), 'index-removable-devices': GLib.Variant.new_boolean(False), 'throttle': GLib.Variant.new_int32(5), } } try: self.system.tracker_miner_fs_testing_start(config) except RuntimeError as e: self.fail(e) self.tracker = self.system.store try: self.create_test_data() self.tracker.reset_graph_updates_tracking() except Exception as e: self.tearDown() raise def tearDown(self): self.system.finish() self.remove_test_data() cfg.remove_monitored_test_dir(self.workdir) def path(self, filename): return os.path.join(self.workdir, filename) def uri(self, filename): return "file://" + os.path.join(self.workdir, filename) def create_test_data(self): monitored_files = [ 'test-monitored/file1.txt', 'test-monitored/dir1/file2.txt', 'test-monitored/dir1/dir2/file3.txt' ] unmonitored_files = ['test-no-monitored/file0.txt'] for tf in chain(monitored_files, unmonitored_files): testfile = self.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_DOCUMENT, url=self.uri(tf)) def remove_test_data(self): try: shutil.rmtree(os.path.join(self.workdir, 'test-monitored')) shutil.rmtree(os.path.join(self.workdir, 'test-no-monitored')) except Exception as e: log("Failed to remove temporary data dir: %s" % e) def assertResourceExists(self, urn): if self.tracker.ask("ASK { <%s> a rdfs:Resource }" % urn) == False: self.fail("Resource <%s> does not exist" % urn) def assertResourceMissing(self, urn): if self.tracker.ask("ASK { <%s> a rdfs:Resource }" % urn) == True: self.fail("Resource <%s> should not exist" % urn)
class CommonTrackerWritebackTest(ut.TestCase): """ Superclass to share methods. Shouldn't be run by itself. Start all processes including writeback, miner pointing to WRITEBACK_TMP_DIR """ def setUp(self): self.workdir = cfg.create_monitored_test_dir() index_dirs = [self.workdir] CONF_OPTIONS = { cfg.DCONF_MINER_SCHEMA: { 'index-recursive-directories': GLib.Variant.new_strv(index_dirs), 'index-single-directories': GLib.Variant.new_strv([]), 'index-optical-discs': GLib.Variant.new_boolean(False), 'index-removable-devices': GLib.Variant.new_boolean(False), }, 'org.freedesktop.Tracker.Store': { 'graphupdated-delay': GLib.Variant.new_int32(100) } } self.system = TrackerSystemAbstraction() self.system.tracker_writeback_testing_start(CONF_OPTIONS) self.tracker = self.system.store self.extractor = self.system.extractor def tearDown(self): self.system.finish() for test_file in pathlib.Path(self.workdir).iterdir(): test_file.unlink() cfg.remove_monitored_test_dir(self.workdir) def datadir_path(self, filename): """Returns the full path to a writeback test file.""" datadir = os.path.join(os.path.dirname(__file__), '..', '..', 'test-writeback-data') return pathlib.Path(os.path.join(datadir, filename)) def prepare_test_file(self, path, expect_mime_type, expect_property): """Copies a file into the test working directory. The function waits until the file has been seen by the Tracker miner before returning. """ log("Copying %s -> %s" % (path, self.workdir)) shutil.copy(path, self.workdir) output_path = pathlib.Path( os.path.join(self.workdir, os.path.basename(path))) # 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( expect_mime_type, url=output_path.as_uri(), required_property=expect_property) return output_path def prepare_test_audio(self, filename): return self.prepare_test_file( filename, 'http://www.semanticdesktop.org/ontologies/2007/03/22/nfo#Audio', 'nfo:duration') def prepare_test_image(self, filename): return self.prepare_test_file( filename, 'http://www.semanticdesktop.org/ontologies/2007/03/22/nfo#Image', 'nfo:width') def uri(self, filename): return pathlib.Path(filename).as_uri() 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)
class CommonTrackerApplicationTest(ut.TestCase): def get_urn_count_by_url(self, url): select = """ SELECT ?u WHERE { ?u nie:url \"%s\" } """ % (url) return len(self.tracker.query(select)) def get_test_image(self): TEST_IMAGE = "test-image-1.jpg" return TEST_IMAGE def get_test_video(self): TEST_VIDEO = "test-video-1.mp4" return TEST_VIDEO def get_test_music(self): TEST_AUDIO = "test-music-1.mp3" return TEST_AUDIO def get_data_dir(self): return self.datadir def get_dest_dir(self): return self.workdir def slowcopy_file_fd(self, src, fdest, rate=SLOWCOPY_RATE): """ @rate: bytes per 100ms """ log("Copying slowly\n '%s' to\n '%s'" % (src, fdest.name)) fsrc = open(src, 'rb') buffer_ = fsrc.read(rate) while (buffer_ != b""): fdest.write(buffer_) time.sleep(0.1) buffer_ = fsrc.read(rate) fsrc.close() def slowcopy_file(self, src, dst, rate=SLOWCOPY_RATE): """ @rate: bytes per 100ms """ fdest = open(dst, 'wb') self.slowcopy_file_fd(src, fdest, rate) fdest.close() @classmethod def setUp(self): self.workdir = cfg.create_monitored_test_dir() index_dirs = [self.workdir] CONF_OPTIONS = { cfg.DCONF_MINER_SCHEMA: { 'index-recursive-directories': GLib.Variant.new_strv(index_dirs), 'index-single-directories': GLib.Variant.new_strv([]), 'index-optical-discs': GLib.Variant.new_boolean(False), 'index-removable-devices': GLib.Variant.new_boolean(False), } } # Use local directory if available. Installation otherwise. if os.path.exists(os.path.join(os.getcwd(), "test-apps-data")): self.datadir = os.path.join(os.getcwd(), "test-apps-data") else: self.datadir = os.path.join(cfg.DATADIR, "tracker-tests", "test-apps-data") self.system = TrackerSystemAbstraction() self.system.tracker_all_testing_start(CONF_OPTIONS) self.tracker = self.system.store @classmethod def tearDown(self): self.system.finish() cfg.remove_monitored_test_dir(self.workdir)
class ExtractorDecoratorTest(ut.TestCase): def setUp(self): self.datadir = cfg.create_monitored_test_dir() config = { cfg.DCONF_MINER_SCHEMA: { 'enable-writeback': GLib.Variant.new_boolean(False), 'index-recursive-directories': GLib.Variant.new_strv([]), 'index-single-directories': GLib.Variant.new_strv([self.datadir]), 'index-optical-discs': GLib.Variant.new_boolean(False), 'index-removable-devices': GLib.Variant.new_boolean(False), }, 'org.freedesktop.Tracker.Store': { 'graphupdated-delay': GLib.Variant('i', 100) } } self.system = TrackerSystemAbstraction(config) self.system.tracker_miner_fs_testing_start() def tearDown(self): self.system.finish() cfg.remove_monitored_test_dir(self.datadir) def test_reextraction(self): """Tests whether known files are still re-extracted on user request.""" miner_fs = self.system.miner_fs store = self.system.store # Insert a valid file and wait extraction of its metadata. file_path = os.path.join(self.datadir, os.path.basename(VALID_FILE)) shutil.copy(VALID_FILE, file_path) try: file_id, file_urn = store.await_resource_inserted( VALID_FILE_CLASS, title=VALID_FILE_TITLE) # Remove a key piece of metadata. # (Writeback must be disabled in the config so that the file # itself is not changed). store.update('DELETE { <%s> nie:title ?title }' ' WHERE { <%s> nie:title ?title }' % (file_urn, file_urn)) store.await_property_changed(VALID_FILE_CLASS, file_id, 'nie:title') assert not store.ask('ASK { <%s> nie:title ?title }' % file_urn) log("Sending re-index request") # Request re-indexing (same as `tracker index --file ...`) miner_fs.index_file('file://' + os.path.join(self.datadir, file_path)) # The extractor should reindex the file and re-add the metadata that we # deleted, so we should see the nie:title property change. store.await_property_changed(VALID_FILE_CLASS, file_id, 'nie:title') title_result = store.query( 'SELECT ?title { <%s> nie:title ?title }' % file_urn) assert len(title_result) == 1 self.assertEqual(title_result[0][0], VALID_FILE_TITLE) finally: os.remove(file_path)