Пример #1
0
    def createObject(self, session, about):
        """
        Pretend to create an object. If an about value is passed, check
        with our query resolver to see if the about value is known. If not
        (or if no about value was passed) return a random new object id.
        If we get an about value that the query resolver doesn't know
        about, we adjust our query resolver and tags client so that next
        time they do. This is to simulate PUT correctly, which creates the
        object with the about value in the case it doesn't already exist.

        @param session: a L{FakeSession} instance.
        @param about: A C{str} value for the about tag.

        @return: A C{Deferred} that fires with the object id of the new
                 object.
        """
        if about:
            results = yield self.resolveQuery(
                None, '%s = "%s"' % (_aboutPath, about))
            if results:
                objectId = results.pop()
            else:
                objectId = util.generateObjectId()
                # Make sure the query resolver now knows how to correctly
                # resolve this about value.
                self.fakeQueryResolver.updateResults([objectId])
                # And add an instance of the about tag to the object.
                self.setTagInstance(session, _aboutPath, object, about)
        else:
            objectId = util.generateObjectId()
        defer.returnValue(objectId)
Пример #2
0
    def createObject(self, session, about):
        """
        Pretend to create an object. If an about value is passed, check
        with our query resolver to see if the about value is known. If not
        (or if no about value was passed) return a random new object id.
        If we get an about value that the query resolver doesn't know
        about, we adjust our query resolver and tags client so that next
        time they do. This is to simulate PUT correctly, which creates the
        object with the about value in the case it doesn't already exist.

        @param session: a L{FakeSession} instance.
        @param about: A C{str} value for the about tag.

        @return: A C{Deferred} that fires with the object id of the new
                 object.
        """
        if about:
            results = yield self.resolveQuery(
                None, '%s = "%s"' % (_aboutPath, about))
            if results:
                objectId = results.pop()
            else:
                objectId = util.generateObjectId()
                # Make sure the query resolver now knows how to correctly
                # resolve this about value.
                self.fakeQueryResolver.updateResults([objectId])
                # And add an instance of the about tag to the object.
                self.setTagInstance(session, _aboutPath, object, about)
        else:
            objectId = util.generateObjectId()
        defer.returnValue(objectId)
Пример #3
0
    def testPUTWithNoContentTypeButWithPayload(self):
        """
        Check that if we attempt a PUT with a payload but don't send a
        Content-Type, we get a BAD_REQUEST response and a
        NoContentTypeHeader response error-class header.
        """
        about = 'africa'
        tag = 'ntoll/binary'
        payload = 'random payload'
        objectIdAboutAfrica = util.generateObjectId()
        fakeQueryResolver = FakeQueryResolver(
            about, [objectIdAboutAfrica], self)
        fakeTagsClient = FakeTagsClient()
        facadeClient = FakeFacadeClient(fakeTagsClient=fakeTagsClient,
                                        fakeQueryResolver=fakeQueryResolver)
        session = FakeSession()
        resource = AboutTagInstanceResource(facadeClient, session, about, tag)

        # Test PUT.
        headers = {
            'Content-Length': [str(len(payload))],
        }
        d = defer.Deferred()
        request = FakeRequest('PUT', d, headers)
        request.content = StringIO.StringIO(payload)
        resource.render(request)
        yield d
        self.assertEqual(request.status, http.BAD_REQUEST)
        self.assertEqual(
            request.getResponseHeader(buildHeader('Error-Class')),
            error.NoContentTypeHeader.__name__)
Пример #4
0
    def testPUTWithNoContentTypeButWithPayload(self):
        """
        Check that if we attempt a PUT with a payload but don't send a
        Content-Type, we get a BAD_REQUEST response and a
        NoContentTypeHeader response error-class header.
        """
        about = 'africa'
        tag = 'ntoll/binary'
        payload = 'random payload'
        objectIdAboutAfrica = util.generateObjectId()
        fakeQueryResolver = FakeQueryResolver(about, [objectIdAboutAfrica],
                                              self)
        fakeTagsClient = FakeTagsClient()
        facadeClient = FakeFacadeClient(fakeTagsClient=fakeTagsClient,
                                        fakeQueryResolver=fakeQueryResolver)
        session = FakeSession()
        resource = AboutTagInstanceResource(facadeClient, session, about, tag)

        # Test PUT.
        headers = {
            'Content-Length': [str(len(payload))],
        }
        d = defer.Deferred()
        request = FakeRequest('PUT', d, headers)
        request.content = StringIO.StringIO(payload)
        resource.render(request)
        yield d
        self.assertEqual(request.status, http.BAD_REQUEST)
        self.assertEqual(request.getResponseHeader(buildHeader('Error-Class')),
                         error.NoContentTypeHeader.__name__)
Пример #5
0
    def testPUTSetOfStringsNotAllStrings(self):
        """
        PUT a set of strings (that are in fact not all strings) value for
        ntoll/rating onto the object about africa. This should result in a
        BAD_REQUEST status and an UnsupportedJSONType error class.
        """
        about = 'africa'
        tag = 'ntoll/rating'
        tagset = ['good', 'bad', 6]
        objectIdAboutAfrica = util.generateObjectId()
        fakeQueryResolver = FakeQueryResolver(
            about, [objectIdAboutAfrica], self)
        fakeTagsClient = FakeTagsClient()
        facadeClient = FakeFacadeClient(fakeTagsClient=fakeTagsClient,
                                        fakeQueryResolver=fakeQueryResolver)
        session = FakeSession()
        resource = AboutTagInstanceResource(facadeClient, session, about, tag)

        # Test PUT.
        payload = json.dumps(tagset)
        headers = {
            'Content-Length': [str(len(payload))],
            'Content-Type': [contentTypeForPrimitiveJSON],
        }
        d = defer.Deferred()
        request = FakeRequest('PUT', d, headers)
        request.content = StringIO.StringIO(payload)
        resource.render(request)
        yield d
        self.assertEqual(request.status, http.BAD_REQUEST)
        self.assertEqual(
            request.getResponseHeader(buildHeader('Error-Class')),
            error.UnsupportedJSONType.__name__)
Пример #6
0
    def testPUTSetOfStringsNotAllStrings(self):
        """
        PUT a set of strings (that are in fact not all strings) value for
        ntoll/rating onto the object about africa. This should result in a
        BAD_REQUEST status and an UnsupportedJSONType error class.
        """
        about = 'africa'
        tag = 'ntoll/rating'
        tagset = ['good', 'bad', 6]
        objectIdAboutAfrica = util.generateObjectId()
        fakeQueryResolver = FakeQueryResolver(about, [objectIdAboutAfrica],
                                              self)
        fakeTagsClient = FakeTagsClient()
        facadeClient = FakeFacadeClient(fakeTagsClient=fakeTagsClient,
                                        fakeQueryResolver=fakeQueryResolver)
        session = FakeSession()
        resource = AboutTagInstanceResource(facadeClient, session, about, tag)

        # Test PUT.
        payload = json.dumps(tagset)
        headers = {
            'Content-Length': [str(len(payload))],
            'Content-Type': [contentTypeForPrimitiveJSON],
        }
        d = defer.Deferred()
        request = FakeRequest('PUT', d, headers)
        request.content = StringIO.StringIO(payload)
        resource.render(request)
        yield d
        self.assertEqual(request.status, http.BAD_REQUEST)
        self.assertEqual(request.getResponseHeader(buildHeader('Error-Class')),
                         error.UnsupportedJSONType.__name__)
Пример #7
0
    def testPUTGETBinaryValueOnObjectAboutAfrica(self):
        """
        PUT a binary value for ntoll/rating onto the object about
        africa. Then do two GET requests:

          - A GET with no Accept header (which means we accept anything)
            and check the result is what we set.
          - Do a GET with an Accept header that prevents FluidDB from
            delivering, and check we get a NOT_ACCEPTABLE status.
        """
        about = 'africa'
        tag = 'ntoll/binary'
        value = '\x00\x01'
        mimetype = 'ntoll/personalbinary'
        objectIdAboutAfrica = util.generateObjectId()
        fakeQueryResolver = FakeQueryResolver(
            about, [objectIdAboutAfrica], self)
        fakeTagsClient = FakeTagsClient()
        facadeClient = FakeFacadeClient(fakeTagsClient=fakeTagsClient,
                                        fakeQueryResolver=fakeQueryResolver)
        session = FakeSession()
        resource = AboutTagInstanceResource(facadeClient, session, about, tag)

        # Test PUT.
        payload = value
        headers = {
            'Content-Length': [str(len(payload))],
            'Content-Type': [mimetype],
        }
        d = defer.Deferred()
        request = FakeRequest('PUT', d, headers)
        request.content = StringIO.StringIO(payload)
        resource.render(request)
        yield d
        self.assertEqual(request.status, http.NO_CONTENT)

        # Test GET.
        d = defer.Deferred()
        request = FakeRequest('GET', d)
        request.content = StringIO.StringIO()
        resource.render(request)
        body = yield d
        self.assertEqual(request.status, http.OK)
        self.assertEqual(request.getResponseHeader('Content-Type'),
                         mimetype)
        self.assertEqual(body, value)

        # Test GET when no acceptable Accept header value.
        headers = {'Accept': ['italian/lira, chewing/gum']}
        request = FakeRequest('GET', None, headers)
        request.content = StringIO.StringIO()
        resource.render(request)
        self.assertEqual(request.status, http.NOT_ACCEPTABLE)
Пример #8
0
    def testPUTGETBinaryValueOnObjectAboutAfrica(self):
        """
        PUT a binary value for ntoll/rating onto the object about
        africa. Then do two GET requests:

          - A GET with no Accept header (which means we accept anything)
            and check the result is what we set.
          - Do a GET with an Accept header that prevents FluidDB from
            delivering, and check we get a NOT_ACCEPTABLE status.
        """
        about = 'africa'
        tag = 'ntoll/binary'
        value = '\x00\x01'
        mimetype = 'ntoll/personalbinary'
        objectIdAboutAfrica = util.generateObjectId()
        fakeQueryResolver = FakeQueryResolver(about, [objectIdAboutAfrica],
                                              self)
        fakeTagsClient = FakeTagsClient()
        facadeClient = FakeFacadeClient(fakeTagsClient=fakeTagsClient,
                                        fakeQueryResolver=fakeQueryResolver)
        session = FakeSession()
        resource = AboutTagInstanceResource(facadeClient, session, about, tag)

        # Test PUT.
        payload = value
        headers = {
            'Content-Length': [str(len(payload))],
            'Content-Type': [mimetype],
        }
        d = defer.Deferred()
        request = FakeRequest('PUT', d, headers)
        request.content = StringIO.StringIO(payload)
        resource.render(request)
        yield d
        self.assertEqual(request.status, http.NO_CONTENT)

        # Test GET.
        d = defer.Deferred()
        request = FakeRequest('GET', d)
        request.content = StringIO.StringIO()
        resource.render(request)
        body = yield d
        self.assertEqual(request.status, http.OK)
        self.assertEqual(request.getResponseHeader('Content-Type'), mimetype)
        self.assertEqual(body, value)

        # Test GET when no acceptable Accept header value.
        headers = {'Accept': ['italian/lira, chewing/gum']}
        request = FakeRequest('GET', None, headers)
        request.content = StringIO.StringIO()
        resource.render(request)
        self.assertEqual(request.status, http.NOT_ACCEPTABLE)
Пример #9
0
 def testPOSTObjectAboutChickenSoup(self):
     """
     Test that a POST to /about/chicken%20soup results in a CREATED
     status and that we get back the id of the object that already
     existed (as will be supplied by the fake query resolver).
     """
     about = 'chicken soup'
     objectId = util.generateObjectId()
     fakeQueryResolver = FakeQueryResolver(about, [objectId], self)
     facadeClient = FakeFacadeClient(fakeQueryResolver=fakeQueryResolver)
     session = FakeSession()
     resource = AboutObjectResource(facadeClient, session, about)
     d = defer.Deferred()
     request = FakeRequest('POST', d)
     request.content = StringIO.StringIO()
     resource.render(request)
     body = yield d
     self.assertEqual(request.status, http.CREATED)
     responseDict = json.loads(body)
     self.assertEqual(responseDict['id'], objectId)
Пример #10
0
 def testGETAboutWithDoubleQuotes(self):
     '''
     Test that a GET to /about/chicken%20"soup"%20taste results in an OK
     status and that we get back the id of the object that already
     existed (as will be supplied by the fake query resolver).
     '''
     about = 'chicken "soup" taste'
     aboutQuoted = r'chicken \"soup\" taste'
     objectId = util.generateObjectId()
     fakeQueryResolver = FakeQueryResolver(aboutQuoted, [objectId], self)
     facadeClient = FakeFacadeClient(fakeQueryResolver=fakeQueryResolver)
     session = FakeSession()
     resource = AboutObjectResource(facadeClient, session, about)
     d = defer.Deferred()
     request = FakeRequest('GET', d)
     request.args = {objects.showAboutArg: ['False']}
     request.content = StringIO.StringIO()
     resource.render(request)
     yield d
     self.assertEqual(request.status, http.OK)
Пример #11
0
 def testGETAboutWithDoubleQuotes(self):
     '''
     Test that a GET to /about/chicken%20"soup"%20taste results in an OK
     status and that we get back the id of the object that already
     existed (as will be supplied by the fake query resolver).
     '''
     about = 'chicken "soup" taste'
     aboutQuoted = r'chicken \"soup\" taste'
     objectId = util.generateObjectId()
     fakeQueryResolver = FakeQueryResolver(aboutQuoted, [objectId], self)
     facadeClient = FakeFacadeClient(fakeQueryResolver=fakeQueryResolver)
     session = FakeSession()
     resource = AboutObjectResource(facadeClient, session, about)
     d = defer.Deferred()
     request = FakeRequest('GET', d)
     request.args = {objects.showAboutArg: ['False']}
     request.content = StringIO.StringIO()
     resource.render(request)
     yield d
     self.assertEqual(request.status, http.OK)
Пример #12
0
 def testPOSTObjectAboutChickenSoup(self):
     """
     Test that a POST to /about/chicken%20soup results in a CREATED
     status and that we get back the id of the object that already
     existed (as will be supplied by the fake query resolver).
     """
     about = 'chicken soup'
     objectId = util.generateObjectId()
     fakeQueryResolver = FakeQueryResolver(about, [objectId], self)
     facadeClient = FakeFacadeClient(fakeQueryResolver=fakeQueryResolver)
     session = FakeSession()
     resource = AboutObjectResource(facadeClient, session, about)
     d = defer.Deferred()
     request = FakeRequest('POST', d)
     request.content = StringIO.StringIO()
     resource.render(request)
     body = yield d
     self.assertEqual(request.status, http.CREATED)
     responseDict = json.loads(body)
     self.assertEqual(responseDict['id'], objectId)
Пример #13
0
 def testGETObjectAboutBarcelona(self):
     """
     Test that a GET of /about/barcelona results in an OK status and
     that we get back the id of the object that already existed (as will
     be supplied by the fake query resolver), and that it has no tags on
     it.
     """
     about = 'barcelona'
     objectId = util.generateObjectId()
     fakeQueryResolver = FakeQueryResolver(about, [objectId], self)
     facadeClient = FakeFacadeClient(fakeQueryResolver=fakeQueryResolver)
     session = FakeSession()
     resource = AboutObjectResource(facadeClient, session, about)
     d = defer.Deferred()
     request = FakeRequest('GET', d)
     request.args = {objects.showAboutArg: ['False']}
     request.content = StringIO.StringIO()
     resource.render(request)
     body = yield d
     self.assertEqual(request.status, http.OK)
     responseDict = json.loads(body)
     self.assertEqual(responseDict[objects.tagPathsArg], [])
     self.assertEqual(responseDict['id'], objectId)
Пример #14
0
 def testGETObjectAboutBarcelona(self):
     """
     Test that a GET of /about/barcelona results in an OK status and
     that we get back the id of the object that already existed (as will
     be supplied by the fake query resolver), and that it has no tags on
     it.
     """
     about = 'barcelona'
     objectId = util.generateObjectId()
     fakeQueryResolver = FakeQueryResolver(about, [objectId], self)
     facadeClient = FakeFacadeClient(fakeQueryResolver=fakeQueryResolver)
     session = FakeSession()
     resource = AboutObjectResource(facadeClient, session, about)
     d = defer.Deferred()
     request = FakeRequest('GET', d)
     request.args = {objects.showAboutArg: ['False']}
     request.content = StringIO.StringIO()
     resource.render(request)
     body = yield d
     self.assertEqual(request.status, http.OK)
     responseDict = json.loads(body)
     self.assertEqual(responseDict[objects.tagPathsArg], [])
     self.assertEqual(responseDict['id'], objectId)
Пример #15
0
    def testPUTGETNonBinaryWithNoAcceptableType(self):
        """
        PUT a primitive (non-binary) value for ntoll/rating onto the object
        about africa. Then do a GET with an Accept header that prevents
        FluidDB from delivering, and check we get a NOT_ACCEPTABLE status.
        """
        about = 'africa'
        tag = 'ntoll/binary'
        value = 5
        objectIdAboutAfrica = util.generateObjectId()
        fakeQueryResolver = FakeQueryResolver(about, [objectIdAboutAfrica],
                                              self)
        fakeTagsClient = FakeTagsClient()
        facadeClient = FakeFacadeClient(fakeTagsClient=fakeTagsClient,
                                        fakeQueryResolver=fakeQueryResolver)
        session = FakeSession()
        resource = AboutTagInstanceResource(facadeClient, session, about, tag)

        # Test PUT.
        payload = json.dumps(value)
        headers = {
            'Content-Length': [str(len(payload))],
            'Content-Type': [contentTypeForPrimitiveJSON],
        }
        d = defer.Deferred()
        request = FakeRequest('PUT', d, headers)
        request.content = StringIO.StringIO(payload)
        resource.render(request)
        yield d
        self.assertEqual(request.status, http.NO_CONTENT)

        # Test GET when no acceptable Accept header value.
        headers = {'Accept': ['italian/lira, chewing/gum']}
        request = FakeRequest('GET', None, headers)
        request.content = StringIO.StringIO()
        resource.render(request)
        self.assertEqual(request.status, http.NOT_ACCEPTABLE)
Пример #16
0
    def testPUTGETNonBinaryWithNoAcceptableType(self):
        """
        PUT a primitive (non-binary) value for ntoll/rating onto the object
        about africa. Then do a GET with an Accept header that prevents
        FluidDB from delivering, and check we get a NOT_ACCEPTABLE status.
        """
        about = 'africa'
        tag = 'ntoll/binary'
        value = 5
        objectIdAboutAfrica = util.generateObjectId()
        fakeQueryResolver = FakeQueryResolver(
            about, [objectIdAboutAfrica], self)
        fakeTagsClient = FakeTagsClient()
        facadeClient = FakeFacadeClient(fakeTagsClient=fakeTagsClient,
                                        fakeQueryResolver=fakeQueryResolver)
        session = FakeSession()
        resource = AboutTagInstanceResource(facadeClient, session, about, tag)

        # Test PUT.
        payload = json.dumps(value)
        headers = {
            'Content-Length': [str(len(payload))],
            'Content-Type': [contentTypeForPrimitiveJSON],
        }
        d = defer.Deferred()
        request = FakeRequest('PUT', d, headers)
        request.content = StringIO.StringIO(payload)
        resource.render(request)
        yield d
        self.assertEqual(request.status, http.NO_CONTENT)

        # Test GET when no acceptable Accept header value.
        headers = {'Accept': ['italian/lira, chewing/gum']}
        request = FakeRequest('GET', None, headers)
        request.content = StringIO.StringIO()
        resource.render(request)
        self.assertEqual(request.status, http.NOT_ACCEPTABLE)
Пример #17
0
    def testPUTWithNoContentTypeNoPayload(self):
        """
        Check that if we attempt a PUT with no payload and no Content-Type,
        we get an (ok) NO_CONTENT status (this is putting a None as the
        value).
        """
        about = 'africa'
        tag = 'ntoll/binary'
        objectIdAboutAfrica = util.generateObjectId()
        fakeQueryResolver = FakeQueryResolver(about, [objectIdAboutAfrica],
                                              self)
        fakeTagsClient = FakeTagsClient()
        facadeClient = FakeFacadeClient(fakeTagsClient=fakeTagsClient,
                                        fakeQueryResolver=fakeQueryResolver)
        session = FakeSession()
        resource = AboutTagInstanceResource(facadeClient, session, about, tag)

        # Test PUT.
        d = defer.Deferred()
        request = FakeRequest('PUT', d)
        request.content = StringIO.StringIO()
        resource.render(request)
        yield d
        self.assertEqual(request.status, http.NO_CONTENT)
Пример #18
0
    def testPUTWithNoContentTypeNoPayload(self):
        """
        Check that if we attempt a PUT with no payload and no Content-Type,
        we get an (ok) NO_CONTENT status (this is putting a None as the
        value).
        """
        about = 'africa'
        tag = 'ntoll/binary'
        objectIdAboutAfrica = util.generateObjectId()
        fakeQueryResolver = FakeQueryResolver(
            about, [objectIdAboutAfrica], self)
        fakeTagsClient = FakeTagsClient()
        facadeClient = FakeFacadeClient(fakeTagsClient=fakeTagsClient,
                                        fakeQueryResolver=fakeQueryResolver)
        session = FakeSession()
        resource = AboutTagInstanceResource(facadeClient, session, about, tag)

        # Test PUT.
        d = defer.Deferred()
        request = FakeRequest('PUT', d)
        request.content = StringIO.StringIO()
        resource.render(request)
        yield d
        self.assertEqual(request.status, http.NO_CONTENT)
Пример #19
0
    def testRatingForObjectAboutBarcelona(self):
        """
        Run a series of tests on the ntoll/rating tag on the object about
        barcelona:

          - the tag should initially not be present.
          - we should successfully be able to do a PUT.
          - we should then be able to do a GET, HEAD, and DELETE in that order.
          - a final GET should then indicate the tag is gone.
        """
        about = 'barcelona'
        tag = 'ntoll/rating'
        rating = 6
        objectIdAboutBarcelona = util.generateObjectId()

        fakeQueryResolver = FakeQueryResolver(
            about, [objectIdAboutBarcelona], self)
        fakeTagsClient = FakeTagsClient()
        facadeClient = FakeFacadeClient(fakeTagsClient=fakeTagsClient,
                                        fakeQueryResolver=fakeQueryResolver)
        session = FakeSession()
        resource = AboutTagInstanceResource(facadeClient, session, about, tag)

        # Test GET when there is no instance on the object.
        d = defer.Deferred()
        request = FakeRequest('GET', d)
        request.content = StringIO.StringIO()
        resource.render(request)
        yield d
        self.assertEqual(request.status, http.NOT_FOUND)

        # Test PUT.
        payload = json.dumps(rating)
        headers = {
            'Content-Length': [str(len(payload))],
            'Content-Type': [contentTypeForPrimitiveJSON],
        }
        d = defer.Deferred()
        request = FakeRequest('PUT', d, headers)
        request.content = StringIO.StringIO(payload)
        resource.render(request)
        yield d
        self.assertEqual(request.status, http.NO_CONTENT)
        self.assertEqual(
            guessValue(fakeTagsClient.values[tag][objectIdAboutBarcelona]),
            rating)

        # Check that the right path, objectId, and value was passed to the
        # fake tags client.
        self.assertEqual(fakeTagsClient.values, {
            tag: {objectIdAboutBarcelona: createThriftValue(rating)},
        })

        # Test GET.
        d = defer.Deferred()
        request = FakeRequest('GET', d)
        request.content = StringIO.StringIO()
        resource.render(request)
        body = yield d
        self.assertEqual(request.status, http.OK)
        self.assertEqual(request.getResponseHeader('Content-Type'),
                         contentTypeForPrimitiveJSON)
        receivedRating = json.loads(body)
        self.assertEqual(receivedRating, rating)

        # Test HEAD
        d = defer.Deferred()
        request = FakeRequest('HEAD', d)
        request.content = StringIO.StringIO()
        resource.render(request)
        body = yield d
        self.assertEqual(request.status, http.OK)
        self.assertEqual(body, '')

        # Test DELETE
        d = defer.Deferred()
        request = FakeRequest('DELETE', d)
        request.content = StringIO.StringIO()
        resource.render(request)
        body = yield d
        self.assertEqual(request.status, http.NO_CONTENT)

        # Test GET when, finally, there is no instance on the object.
        d = defer.Deferred()
        request = FakeRequest('GET', d)
        request.content = StringIO.StringIO()
        resource.render(request)
        yield d
        self.assertEqual(request.status, http.NOT_FOUND)

        # Check that the value really was deleted.
        self.assertEqual(fakeTagsClient.values, {tag: {}})
Пример #20
0
    def testRatingForObjectAboutBarcelona(self):
        """
        Run a series of tests on the ntoll/rating tag on the object about
        barcelona:

          - the tag should initially not be present.
          - we should successfully be able to do a PUT.
          - we should then be able to do a GET, HEAD, and DELETE in that order.
          - a final GET should then indicate the tag is gone.
        """
        about = 'barcelona'
        tag = 'ntoll/rating'
        rating = 6
        objectIdAboutBarcelona = util.generateObjectId()

        fakeQueryResolver = FakeQueryResolver(about, [objectIdAboutBarcelona],
                                              self)
        fakeTagsClient = FakeTagsClient()
        facadeClient = FakeFacadeClient(fakeTagsClient=fakeTagsClient,
                                        fakeQueryResolver=fakeQueryResolver)
        session = FakeSession()
        resource = AboutTagInstanceResource(facadeClient, session, about, tag)

        # Test GET when there is no instance on the object.
        d = defer.Deferred()
        request = FakeRequest('GET', d)
        request.content = StringIO.StringIO()
        resource.render(request)
        yield d
        self.assertEqual(request.status, http.NOT_FOUND)

        # Test PUT.
        payload = json.dumps(rating)
        headers = {
            'Content-Length': [str(len(payload))],
            'Content-Type': [contentTypeForPrimitiveJSON],
        }
        d = defer.Deferred()
        request = FakeRequest('PUT', d, headers)
        request.content = StringIO.StringIO(payload)
        resource.render(request)
        yield d
        self.assertEqual(request.status, http.NO_CONTENT)
        self.assertEqual(
            guessValue(fakeTagsClient.values[tag][objectIdAboutBarcelona]),
            rating)

        # Check that the right path, objectId, and value was passed to the
        # fake tags client.
        self.assertEqual(fakeTagsClient.values, {
            tag: {
                objectIdAboutBarcelona: createThriftValue(rating)
            },
        })

        # Test GET.
        d = defer.Deferred()
        request = FakeRequest('GET', d)
        request.content = StringIO.StringIO()
        resource.render(request)
        body = yield d
        self.assertEqual(request.status, http.OK)
        self.assertEqual(request.getResponseHeader('Content-Type'),
                         contentTypeForPrimitiveJSON)
        receivedRating = json.loads(body)
        self.assertEqual(receivedRating, rating)

        # Test HEAD
        d = defer.Deferred()
        request = FakeRequest('HEAD', d)
        request.content = StringIO.StringIO()
        resource.render(request)
        body = yield d
        self.assertEqual(request.status, http.OK)
        self.assertEqual(body, '')

        # Test DELETE
        d = defer.Deferred()
        request = FakeRequest('DELETE', d)
        request.content = StringIO.StringIO()
        resource.render(request)
        body = yield d
        self.assertEqual(request.status, http.NO_CONTENT)

        # Test GET when, finally, there is no instance on the object.
        d = defer.Deferred()
        request = FakeRequest('GET', d)
        request.content = StringIO.StringIO()
        resource.render(request)
        yield d
        self.assertEqual(request.status, http.NOT_FOUND)

        # Check that the value really was deleted.
        self.assertEqual(fakeTagsClient.values, {tag: {}})