Example #1
0
class CachingTagValueAPI(object):
    """The public API to cached L{TagValue}-related logic in the model.

    @param user: The L{User} to perform operations on behalf of.
    """

    def __init__(self, user):
        self._api = TagValueAPI(user, factory=CachingAPIFactory())
        self._user = user

    def get(self, objectIDs, paths=None):
        """See L{TagValueAPI.get}."""
        return self._api.get(objectIDs, paths)

    def set(self, values):
        """See L{TagValueAPI.set}."""
        result = self._api.set(values)
        RecentObjectActivityCache().clear(values.keys())
        RecentUserActivityCache().clear([self._user.username])
        return result

    def delete(self, values):
        """See L{TagValueAPI.delete}."""
        if isgenerator(values):
            values = list(values)
        result = self._api.delete(values)
        objectIDs = [objectID for objectID, path in values]
        RecentObjectActivityCache().clear(objectIDs)
        RecentUserActivityCache().clear([self._user.username])
        return result
Example #2
0
    def testDeleteTagWithData(self):
        """
        L{FacadeTagMixin.deleteTag} removes L{TagValue}s associated with the
        deleted L{Tag}.
        """
        objectID = uuid4()
        TagAPI(self.user).create([(u'username/tag', u'A tag.')])
        tagValues = TagValueAPI(self.user)
        tagValues.set({objectID: {u'username/tag': 42}})
        self.store.commit()
        with login(u'username', uuid4(), self.transact) as session:
            yield self.facade.deleteTag(session, u'username/tag')

        self.store.rollback()
        self.assertEqual({}, tagValues.get(objectIDs=[objectID],
                                           paths=[u'username/tag']))
Example #3
0
 def testDeleteRemovesSystemTags(self):
     """
     L{UserAPI.delete} removes the C{fluiddb/users/*} tag values stored for
     deleted L{User}s.
     """
     self.users.create([(u'user', u'pass', u'User', u'*****@*****.**')])
     user = getUser(u'user')
     NamespaceAPI(user).delete([u'user/private'])
     [(objectID, _)] = self.users.delete([u'user'])
     tagValues = TagValueAPI(self.system.users[u'fluiddb'])
     result = tagValues.get(objectIDs=[objectID],
                            paths=[u'fluiddb/users/username',
                                   u'fluiddb/users/name',
                                   u'fluiddb/users/email',
                                   u'fluiddb/users/role'])
     self.assertEqual({}, result)
Example #4
0
 def testDeleteRemovesSystemTags(self):
     """
     L{UserAPI.delete} removes the C{fluiddb/users/*} tag values stored for
     deleted L{User}s.
     """
     self.users.create([(u'user', u'pass', u'User', u'*****@*****.**')])
     user = getUser(u'user')
     NamespaceAPI(user).delete([u'user/private'])
     [(objectID, _)] = self.users.delete([u'user'])
     tagValues = TagValueAPI(self.system.users[u'fluiddb'])
     result = tagValues.get(objectIDs=[objectID],
                            paths=[
                                u'fluiddb/users/username',
                                u'fluiddb/users/name',
                                u'fluiddb/users/email',
                                u'fluiddb/users/role'
                            ])
     self.assertEqual({}, result)
class DataImportHandlerTest(FluidinfoTestCase):

    resources = [('client', IndexResource()),
                 ('config', ConfigResource()),
                 ('store', DatabaseResource())]

    def setUp(self):
        super(DataImportHandlerTest, self).setUp()
        createSystemData()
        UserAPI().create([(u'user', u'secret', u'User', u'*****@*****.**')])
        self.user = getUser(u'user')
        self.objects = ObjectAPI(self.user)
        self.values = TagValueAPI(self.user)
        self.index = ObjectIndex(self.client)

    @inlineCallbacks
    def assertQuery(self, objectIDs, query):
        """Asserts if a query to fluidinfo returns the expected results.

        @param objectIDs: A sequence with the expected object IDs for the
            query.
        @param query: The fluidinfo query to check.
        """
        query = parseQuery(query)
        results = yield self.index.search(query)
        self.assertEqual(set(objectIDs), results)

    @inlineCallbacks
    def testImportObjectWithStringValue(self):
        """The Data Import Handler correctly imports C{string} values."""
        objectID = self.objects.create()
        self.values.set({objectID: {u'user/tag': u'string'}})
        runDataImportHandler(self.client.url)
        yield self.assertQuery([objectID], u'user/tag = "string"')
        yield self.assertQuery([objectID], u'has user/tag')

    @inlineCallbacks
    def testImportObjectWithStringValueInvalidXML(self):
        """
        The Data Import Handler correctly imports C{string} values, including
        those that contain invalid XML characters.
        """
        objectID = self.objects.create()
        self.values.set({objectID: {u'user/tag': u'foo \uFFFE'}})
        runDataImportHandler(self.client.url)
        yield self.assertQuery([objectID], u'user/tag = "foo \uFFFE"')
        yield self.assertQuery([objectID], u'has user/tag')

    @inlineCallbacks
    def testImportObjectWithEmptyStringValue(self):
        """The Data Import Handler correctly imports empty C{string} values."""
        objectID = self.objects.create()
        self.values.set({objectID: {u'user/tag': u''}})
        runDataImportHandler(self.client.url)
        yield self.assertQuery([objectID], u'user/tag = ""')
        yield self.assertQuery([objectID], u'has user/tag')

    @inlineCallbacks
    def testImportObjectWithQuotesValue(self):
        """
        The Data Import Handler correctly imports C{string} values with single
        quotes.
        """
        objectID = self.objects.create()
        self.values.set({objectID: {u'user/tag': u'hello\'world'}})
        runDataImportHandler(self.client.url)
        yield self.assertQuery([objectID], u'user/tag = "hello\'world"')
        yield self.assertQuery([objectID], u'has user/tag')

    @inlineCallbacks
    def testImportObjectWithDoubleQuotesValue(self):
        """
        The Data Import Handler correctly imports C{string} values with double
        quotes.
        """
        objectID = self.objects.create()
        self.values.set({objectID: {u'user/tag': u'hello\"world'}})
        runDataImportHandler(self.client.url)
        yield self.assertQuery([objectID], u'user/tag = "hello\\\"world"')
        yield self.assertQuery([objectID], u'has user/tag')

    @inlineCallbacks
    def testImportObjectWithCommaAndParens(self):
        """
        The Data Import Handler correctly imports C{string} values with comma
        and parens.
        """
        objectID = self.objects.create()
        self.values.set({objectID: {u'user/tag': u'),'}})
        runDataImportHandler(self.client.url)

        yield self.assertQuery([objectID], u'user/tag = "),"')
        yield self.assertQuery([objectID], u'has user/tag')

    @inlineCallbacks
    def testImportObjectWithStringValueWithSpecialCharacters(self):
        """
        The Data Import Handler correctly imports C{string} values with special
        unicode characters.
        """
        objectID = self.objects.create()
        self.values.set({objectID: {u'user/tag': u'\xe1\xe9\xed\xf3'}})
        runDataImportHandler(self.client.url)
        yield self.assertQuery([objectID], u'user/tag = "\xe1\xe9\xed\xf3"')
        yield self.assertQuery([objectID], u'has user/tag')

    @inlineCallbacks
    def testImportObjectWithListValue(self):
        """The Data Import Handler correctly imports C{list} values."""
        objectID = self.objects.create()
        self.values.set({objectID: {u'user/tag': [u'one', u'two', u'three']}})
        runDataImportHandler(self.client.url)
        yield self.assertQuery([objectID], u'user/tag contains "one" '
                                           u'and user/tag contains "two" '
                                           u'and user/tag contains "three"')
        yield self.assertQuery([objectID], u'has user/tag')

    @inlineCallbacks
    def testImportObjectWithListValueWithSpecialCharacters(self):
        """
        The Data Import Handler correctly imports C{list} values with special
        unicode characters.
        """
        objectID = self.objects.create()
        self.values.set({objectID: {u'user/tag': [u'one', u'\xe1\xe9']}})
        runDataImportHandler(self.client.url)
        yield self.assertQuery([objectID], u'user/tag contains "\xe1\xe9"')
        yield self.assertQuery([objectID], u'has user/tag')

    @inlineCallbacks
    def testImportObjectWithListValueWithEmptyString(self):
        """
        The Data Import Handler correctly imports C{list} values with an empty
        string in them.
        """
        objectID = self.objects.create()
        self.values.set({objectID: {u'user/tag': [u'']}})
        runDataImportHandler(self.client.url)
        yield self.assertQuery([objectID], u'user/tag contains ""')
        yield self.assertQuery([objectID], u'has user/tag')

    @inlineCallbacks
    def testImportObjectWithIntValue(self):
        """The Data Import Handler correctly imports C{int} values."""
        objectID = self.objects.create()
        self.values.set({objectID: {u'user/tag': 5}})
        runDataImportHandler(self.client.url)
        yield self.assertQuery([objectID], u'user/tag = 5')
        yield self.assertQuery([objectID], u'has user/tag')

    @inlineCallbacks
    def testImportObjectWithIntSixDigitValue(self):
        """The Data Import Handler correctly imports C{int} values."""
        objectID = self.objects.create()
        self.values.set({objectID: {u'user/tag': 123456}})
        runDataImportHandler(self.client.url)
        yield self.assertQuery([objectID], u'user/tag = 123456')
        yield self.assertQuery([objectID], u'has user/tag')

    @inlineCallbacks
    def testImportObjectWithFloatValue(self):
        """The Data Import Handler correctly imports C{float} values."""
        objectID = self.objects.create()
        self.values.set({objectID: {u'user/tag': 5.5}})
        runDataImportHandler(self.client.url)
        yield self.assertQuery([objectID], u'user/tag = 5.5')
        yield self.assertQuery([objectID], u'has user/tag')

    @inlineCallbacks
    def testImportObjectWithBoolValue(self):
        """The Data Import Handler correctly imports C{boolean} values."""
        objectID = self.objects.create()
        self.values.set({objectID: {u'user/tag': False}})
        runDataImportHandler(self.client.url)
        yield self.assertQuery([objectID], u'user/tag = false')
        yield self.assertQuery([objectID], u'has user/tag')

    @inlineCallbacks
    def testImportObjectWithNoneValue(self):
        """The Data Import Handler correctly imports C{null} values."""
        objectID = self.objects.create()
        self.values.set({objectID: {u'user/tag': None}})
        runDataImportHandler(self.client.url)
        yield self.assertQuery([objectID], u'has user/tag')

    @inlineCallbacks
    def testImportObjectWithBinaryValue(self):
        """The Data Import Handler correctly imports C{binary} values."""
        objectID = self.objects.create()
        self.values.set({objectID: {
            u'user/tag': {
                'mime-type': 'text/plain',
                'contents': 'file contents'}}})
        runDataImportHandler(self.client.url)
        yield self.assertQuery([objectID], u'has user/tag')

    @inlineCallbacks
    def testImportObjectWithBinaryValueDoesNotCreateOtherValues(self):
        """
        The Data Import Handler does not import binary tag values as other Solr
        fields. This is a test for issue #1447.
        """
        objectID = self.objects.create()
        self.values.set({objectID: {
            u'user/tag': {
                'mime-type': 'text/plain',
                'contents': 'file contents'}}})
        runDataImportHandler(self.client.url)
        yield self.assertQuery([objectID], u'has user/tag')
        yield self.assertQuery([], u'user/tag = 13')
        yield self.assertQuery([], u'user/tag = "size"')

    @inlineCallbacks
    def testImportObjectWithMultipleValues(self):
        """The Data Import Handler import documents with multiple values."""
        objectID = self.objects.create()
        self.values.set({objectID: {
            u'user/tag1': u'string',
            u'user/tag2': 5,
            u'user/tag3': 5.5,
            u'user/tag4': True,
            u'user/tag5': None,
            u'user/tag6': {
                'mime-type': 'text/plain',
                'contents': 'file contents'}}})
        runDataImportHandler(self.client.url)
        yield self.assertQuery([objectID],
                               'user/tag1 = "string" and user/tag2 = 5 '
                               'and user/tag3 = 5.5 and user/tag4 = true')

        yield self.assertQuery([objectID],
                               'has user/tag1 and has user/tag2 '
                               'and has user/tag3 and has user/tag4 '
                               'and has user/tag5 and has user/tag6')

    @inlineCallbacks
    def testImportMultipleObjects(self):
        """The Data Import Handler imports multiple objects."""
        objectID1 = self.objects.create()
        objectID2 = self.objects.create()
        objectID3 = self.objects.create()
        objectID4 = self.objects.create()
        self.values.set({objectID1: {u'user/tag1': u'string'},
                         objectID2: {u'user/tag1': u'string'},
                         objectID3: {u'user/tag1': 5},
                         objectID4: {u'user/tag2': True}})
        runDataImportHandler(self.client.url)

        yield self.assertQuery([objectID1, objectID2], 'user/tag1 = "string"')
        yield self.assertQuery([objectID1, objectID2, objectID3],
                               'has user/tag1')

    @inlineCallbacks
    def testImportDeletedObject(self):
        """The Data Import Handler removes all fields from deleted objects"""
        objectID1 = self.objects.create()
        objectID2 = self.objects.create()
        self.values.set({objectID1: {u'user/tag1': u'string'},
                         objectID2: {u'user/tag1': u'string'}})
        self.values.delete([(objectID1, u'user/tag1')])
        runDataImportHandler(self.client.url)
        yield self.assertQuery([objectID2], 'has user/tag1')
        yield self.assertQuery([objectID2], 'user/tag1 = "string"')

    @inlineCallbacks
    def testImportDeletedAndCreatedAgainObject(self):
        """
        The Data Import Handler correctly imports values deleted and created
        again.
        """
        objectID1 = self.objects.create()
        objectID2 = self.objects.create()
        self.values.set({objectID1: {u'user/tag1': u'string'},
                         objectID2: {u'user/tag1': u'string'}})
        self.values.delete([(objectID1, u'user/tag1')])
        self.values.set({objectID1: {u'user/tag1': u'string'}})
        runDataImportHandler(self.client.url)
        yield self.assertQuery([objectID1, objectID2], 'has user/tag1')
        yield self.assertQuery([objectID1, objectID2], 'user/tag1 = "string"')

    @inlineCallbacks
    def testDeltaImport(self):
        """
        When using a C{clean=false} option, the Data Import Handler only
        imports values modified since the last run.
        """
        objectID1 = self.objects.create()
        objectID2 = self.objects.create()

        self.values.set({objectID1: {
            u'user/tag1': u'string',
            u'user/tag2': 5,
            u'user/tag3': 5.5}})

        getDirtyObjects().remove()

        self.values.set({objectID2: {
            u'user/tag1': u'string',
            u'user/tag2': 5,
            u'user/tag3': 5.5}})

        runDataImportHandler(self.client.url, clean=False)

        yield self.assertQuery(
            [objectID2], 'has user/tag1 and has user/tag2 and has user/tag3 '
                         'and user/tag1="string" and user/tag2=5 and '
                         'user/tag3=5.5')

    @inlineCallbacks
    def testDeltaImportWithDeletedTag(self):
        """
        L{TagValue}s deleted via delete cascade triggered by a L{Tag} deletion
        should be deleted in the index too.
        """
        objectID = self.objects.create()
        self.values.set({objectID: {u'user/tag1': u'string',
                                    u'user/tag2': u'text'}})
        time.sleep(1)
        runDataImportHandler(self.client.url)
        tags = TagAPI(self.user)
        tags.delete([u'user/tag1'])
        self.store.commit()
        values = self.values.get([objectID], [u'user/tag1'])
        self.assertNotIn(u'user/tag1', values[objectID])
        runDataImportHandler(self.client.url, clean=False)
        yield self.assertQuery([], 'has user/tag1')
        yield self.assertQuery([], 'user/tag1 = "string"')