Example #1
0
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()
Example #2
0
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)
Example #3
0
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)