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__)
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__)
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__)
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__)
def testRatingForNonexistentObjectAboutParis(self): """ Run GET and HEAD requests against a non-existent object about paris, check that both return NOT_FOUND. """ about = 'paris' tag = 'ntoll/rating' fakeQueryResolver = FakeQueryResolver(about, [], self) facadeClient = FakeFacadeClient(fakeQueryResolver=fakeQueryResolver) session = FakeSession() resource = AboutTagInstanceResource(facadeClient, session, about, tag) # Test GET. d = defer.Deferred() request = FakeRequest('GET', d) request.content = StringIO.StringIO() resource.render(request) yield d self.assertEqual(request.status, http.NOT_FOUND) # Test HEAD. d = defer.Deferred() request = FakeRequest('HEAD', d) request.content = StringIO.StringIO() resource.render(request) yield d self.assertEqual(request.status, http.NOT_FOUND)
def testPUTOnNonexistentObjectAboutAfrica(self): """ PUT a value for ntoll/keywords onto the object about africa, even though no such object exists. This should succeed with a CREATED status. We then do a GET to make sure we can retrieve the value. BTW, I use a set of strings as a value to increase code coverage of about.py We want /about to be identical in semantics to /objects/id and so this behavior mirrors that of /objects/id/tag/path which does not require that the object id exists in order to put a value onto it. """ about = 'africa' tag = 'ntoll/keywords' value = ['hot', 'dry', 'dusty'] fakeQueryResolver = FakeQueryResolver(about, [], 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) self.assertEqual(request.status, http.NO_CONTENT) yield d # Pull the object id out of the fake tags client and tell the fake # query resolver to now give a different answer for the query on # africa. keys = fakeTagsClient.values[_aboutPath].keys() self.assertEqual(len(keys), 1) # 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) receivedValue = json.loads(body) self.assertEqual(set(value), set(receivedValue))
def testRatingForAboutContainingDoubleQuotes(self): """ Run GET requests against a non-existent object about a string with embedded double quotes. Check that it returns NOT_FOUND. """ about = 'chicken "soup" taste' aboutQuoted = r'chicken \"soup\" taste' tag = 'ntoll/rating' fakeQueryResolver = FakeQueryResolver(aboutQuoted, [], self) facadeClient = FakeFacadeClient(fakeQueryResolver=fakeQueryResolver) session = FakeSession() resource = AboutTagInstanceResource(facadeClient, session, about, tag) d = defer.Deferred() request = FakeRequest('GET', d) request.content = StringIO.StringIO() resource.render(request) yield d self.assertEqual(request.status, http.NOT_FOUND)
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)
def testGETListValuesPreserveOrder(self): """ List values get via GET on /about preserve the same order of the original value. """ facadeClient = SimpleFakeFacade() session = FakeSession() # Tell our FakeFacade to preload some data for a given tag. facadeClient.values = { 'fe2f50c8-997f-4049-a180-9a37543d001d': { 'tag/test': ['x', 'y', 'z', 'a', 'b', 'c'], 'fluiddb/about': 'about tag'}} resource = AboutTagInstanceResource(facadeClient, session, 'about tag', 'tag/test') request = FakeRequest('GET', {}, {}, '') body = yield resource.deferred_render_GET(request) value = json.loads(body) self.assertEqual(['x', 'y', 'z', 'a', 'b', 'c'], value)
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)
def testGETListValuesPreserveOrder(self): """ List values get via GET on /about preserve the same order of the original value. """ facadeClient = SimpleFakeFacade() session = FakeSession() # Tell our FakeFacade to preload some data for a given tag. facadeClient.values = { 'fe2f50c8-997f-4049-a180-9a37543d001d': { 'tag/test': ['x', 'y', 'z', 'a', 'b', 'c'], 'fluiddb/about': 'about tag' } } resource = AboutTagInstanceResource(facadeClient, session, 'about tag', 'tag/test') request = FakeRequest('GET', {}, {}, '') body = yield resource.deferred_render_GET(request) value = json.loads(body) self.assertEqual(['x', 'y', 'z', 'a', 'b', 'c'], value)
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)
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)
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)
def assertXFluidDBHeaderForType(self, method, value, expectedTypeString): """ L{TagInstanceResource.render_HEAD} should put an X-FluidDB-Type header indicating the type of the value that it's returning. This tests checks float types. """ facadeClient = SimpleFakeFacade() session = FakeSession() # Tell our FakeFacade to preload some data for a given tag. facadeClient.values = { 'fe2f50c8-997f-4049-a180-9a37543d001d': { 'tag/test': value, 'fluiddb/about': 'about tag' } } resource = AboutTagInstanceResource(facadeClient, session, 'about tag', 'tag/test') request = FakeRequest(method, {}, {}, '') yield getattr(resource, 'render_' + method)(request) typeValue = request.getResponseHeader(buildHeader('Type')) self.assertEqual(expectedTypeString, typeValue)
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)
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: {}})
def testAboutTagInstanceResource(self): resource = AboutTagInstanceResource(FakeFacadeClient(), FakeSession(), about='foo', path='bar/baz') self._checkCORSPreFlightRequest(resource)
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: {}})