class ChunkedStreamingTestCase(TestSuite): def setUp(self): def generate_data(): yield b'1' * (10 * 1024) yield b'2' * 1024 self.data = b''.join(generate_data()) self.server = Vibora() @self.server.route('/') async def home(): return StreamingResponse(generate_data) async def test_streaming_client_reading_content__expects_successful(self): async with self.server.test_client() as client: response = await client.get('/', stream=True) await response.read_content() self.assertEqual(response.content, self.data) async def test_streaming_client_reading_stream__expects_successful(self): async with self.server.test_client() as client: response = await client.get('/', stream=True) received_data = bytearray() async for chunk in response.stream(): received_data.extend(chunk) self.assertEqual(received_data, self.data) async def test_streaming_client_very_small_reads__expects_successful(self): client = self.server.test_client() response = await client.get('/', stream=True) received_data = bytearray() async for chunk in response.stream(chunk_size=1): self.assertTrue(len(chunk) == 1) received_data.extend(chunk) self.assertEqual(received_data, self.data)
class BlueprintsTestCase(TestSuite): def setUp(self): self.app = Vibora(router_strategy=RouterStrategy.STRICT) async def test_simple_add_blueprint__expects_added(self): b1 = Blueprint() @b1.route("/") async def home(): return Response(b"123") self.app.add_blueprint(b1) async with self.app.test_client() as client: response = await client.request("/") self.assertEqual(response.content, b"123") async def test_simple_add_blueprint_with_prefix_expects_added(self): b1 = Blueprint() @b1.route("/") async def home(): return Response(b"123") self.app.add_blueprint(b1, prefixes={"home": "/home"}) async with self.app.test_client() as client: response = await client.request("/home/") self.assertEqual(response.content, b"123") async def test_simple_add_nested_blueprints(self): b1 = Blueprint() b2 = Blueprint() @b2.route("/123") async def home(): return Response(b"123") b1.add_blueprint(b2) self.app.add_blueprint(b1) async with self.app.test_client() as client: response = await client.request("/123") self.assertEqual(response.content, b"123") async def test_simple_add_nested_blueprints_with_prefixes(self): b1 = Blueprint() b2 = Blueprint() @b2.route("/123") async def home(): return Response(b"123") b1.add_blueprint(b2, prefixes={"a": "/a", "b": "/b"}) self.app.add_blueprint(b1, prefixes={"a": "/a", "b": "/b"}) async with self.app.test_client() as client: response = await client.request("/a/a/123") self.assertEqual(response.content, b"123") response = await self.app.test_client().request("/b/b/123") self.assertEqual(response.content, b"123")
class BlueprintsTestCase(TestSuite): def setUp(self): self.app = Vibora(router_strategy=RouterStrategy.STRICT) async def test_simple_add_blueprint__expects_added(self): b1 = Blueprint() @b1.route('/') async def home(): return Response(b'123') self.app.add_blueprint(b1) async with self.app.test_client() as client: response = await client.request('/') self.assertEqual(response.content, b'123') async def test_simple_add_blueprint_with_prefix_expects_added(self): b1 = Blueprint() @b1.route('/') async def home(): return Response(b'123') self.app.add_blueprint(b1, prefixes={'home': '/home'}) async with self.app.test_client() as client: response = await client.request('/home/') self.assertEqual(response.content, b'123') async def test_simple_add_nested_blueprints(self): b1 = Blueprint() b2 = Blueprint() @b2.route('/123') async def home(): return Response(b'123') b1.add_blueprint(b2) self.app.add_blueprint(b1) async with self.app.test_client() as client: response = await client.request('/123') self.assertEqual(response.content, b'123') async def test_simple_add_nested_blueprints_with_prefixes(self): b1 = Blueprint() b2 = Blueprint() @b2.route('/123') async def home(): return Response(b'123') b1.add_blueprint(b2, prefixes={'a': '/a', 'b': '/b'}) self.app.add_blueprint(b1, prefixes={'a': '/a', 'b': '/b'}) async with self.app.test_client() as client: response = await client.request('/a/a/123') self.assertEqual(response.content, b'123') response = await self.app.test_client().request('/b/b/123') self.assertEqual(response.content, b'123')
async def test_files_upload_expects_correctly_parsed(self): app = Vibora() @app.route("/", methods=["POST"]) async def home(request: Request): form = await request.form() return JsonResponse( { "a": (await form["a"].read()).decode(), "b": (await form["b"].read()).decode(), "c": (await form["c"].read()).decode(), "d": form["d"], } ) async with app.test_client() as client: response = await client.post( "/", form={ "a": FileUpload(content=b"a"), "b": FileUpload(content=b"b"), "c": FileUpload(content=b"c"), "d": 1, }, ) self.assertEqual(response.status_code, 200) self.assertDictEqual(response.json(), {"a": "a", "b": "b", "c": "c", "d": "1"})
async def test_simple_streaming_with_chunk_timeout(self): app = Vibora(server_limits=ServerLimits(write_buffer=1)) async def stream(): for _ in range(0, 5): await asyncio.sleep(0) yield b'1' * 1024 * 1024 * 100 @app.route('/') async def home(): return StreamingResponse(stream, chunk_timeout=3, complete_timeout=999) with app.test_client() as client: response = await client.get('/', stream=True) try: first = True chunk_size = 1 * 1024 * 1024 async for chunk in response.stream(chunk_size=chunk_size): if first: await asyncio.sleep(5) first = False self.assertTrue(len(chunk) <= chunk_size) self.fail( 'Vibora should have closed the connection because of a chunk timeout.' ) except asyncio.IncompleteReadError: pass
async def test_files_upload_expects_correctly_parsed(self): app = Vibora() @app.route('/', methods=['POST']) async def home(request: Request): form = await request.form() return JsonResponse({ 'a': await form['a'].read(), 'b': await form['b'].read(), 'c': await form['c'].read(), 'd': form['d'], }) with app.test_client() as client: response = await client.post( '/', form={ 'a': FileUpload(content=b'a'), 'b': FileUpload(content=b'b'), 'c': FileUpload(content=b'c'), 'd': 1, }, ) self.assertEqual(response.status_code, 200) self.assertDictEqual(response.json(), { 'a': 'a', 'b': 'b', 'c': 'c', 'd': '1' })
async def test_files_attribute_expects_correctly_parsed(self): app = Vibora() @app.route('/', methods=['POST']) async def home(request: Request): uploaded_files = {} for file in await request.files(): uploaded_files[file.filename] = await file.read() return JsonResponse(uploaded_files) with app.test_client() as client: response = await client.post( '/', form={ 'a': FileUpload(content=b'a', name='a'), 'b': FileUpload(content=b'b', name='b'), 'c': FileUpload(content=b'c', name='c'), 'd': 1, }, ) self.assertEqual(response.status_code, 200) self.assertDictEqual(response.json(), { 'a': 'a', 'b': 'b', 'c': 'c' })
async def test_custom_cache_engine_skipping_hooks(self): class AsyncEngine(CacheEngine): def get(self, request: Request): return self.cache.get(request.url) def store(self, request: Request, response): self.cache[request.url] = response app = Vibora() manager = Manager() calls = manager.list() def before_end(): calls.append('called_before_endpoint') app.add_hook(Hook(Events.BEFORE_ENDPOINT, before_end)) @app.route('/', cache=AsyncEngine(skip_hooks=True)) async def home(): return JsonResponse({'now': time.time()}) client = app.test_client() response1 = await client.get('/') response2 = await client.get('/') self.assertEqual(len(calls), 1) self.assertEqual(response1.content, response2.content) client.close()
async def test_headers_bigger_than_expected_expects_rejected_request(self): app = Vibora(server_limits=ServerLimits(max_headers_size=1)) @app.route('/', methods=['GET']) async def home(): return Response(b'Wrong. Request should halted earlier.') with app.test_client() as client: response = await client.get('/') self.assertEqual(response.status_code, 400)
class CloneStrategyTestCase(TestSuite): def setUp(self): self.app = Vibora(router_strategy=RouterStrategy.CLONE) async def test_simple_get_route_expects_found(self): @self.app.route('/test') async def home(): return Response(b'123') client = self.app.test_client() self.assertEqual(200, (await client.request('/test')).status_code) async def test_simple_get_route_wrong_method_expects_not_allowed(self): @self.app.route('/test', methods=['POST']) async def home(): return Response(b'123') client = self.app.test_client() self.assertEqual(405, (await client.request('/test')).status_code) async def test_simple_get_route_wrong_path_expects_not_found(self): @self.app.route('/test', methods=['POST']) async def home(): return Response(b'123') client = self.app.test_client() self.assertEqual(404, (await client.request('/asd')).status_code) async def test_missing_slash_expects_found(self): @self.app.route('/test/', methods=['GET']) async def home(): return Response(b'123') client = self.app.test_client() self.assertEqual(200, (await client.request('/test')).status_code) async def test_additional_slash_expects_found(self): @self.app.route('/test', methods=['GET']) async def home(): return Response(b'123') client = self.app.test_client() self.assertEqual(200, (await client.request('/test/')).status_code)
async def test_simple_post__expects_correctly_interpreted(): app = Vibora() @app.route("/", methods=["POST"]) async def home(request: Request): return JsonResponse((await request.form())) async with app.test_client() as client: response = await client.post("/", form={"a": 1, "b": 2}) assert response.json() == {"a": "1", "b": "2"}
async def test_body_smaller_than_limit_expects_200(self): app = Vibora(route_limits=RouteLimits(max_body_size=2)) @app.route('/', methods=['POST']) async def home(request: Request): await request.stream.read() return Response(b'Correct. Request should not be blocked.') with app.test_client() as client: response = await client.post('/', body=b'1') self.assertEqual(response.status_code, 200)
async def test_file_upload_with_another_values(self): app = Vibora() @app.route('/', methods=['POST']) async def home(request: Request): form = (await request.form()) return JsonResponse({'a': form['a'], 'b': await form['b'].read()}) with app.test_client() as client: response = await client.post('/', form={'a': 1, 'b': FileUpload(content=b'uploaded_file')}) self.assertDictEqual(response.json(), {'a': '1', 'b': 'uploaded_file'})
async def test_simple_case_expects_timeout_response(self): app = Vibora() @app.route("/", limits=RouteLimits(timeout=2)) async def home(): await asyncio.sleep(10) return Response(b"Wrong. This request should timeout.") async with app.test_client() as client: response = await client.get("/", timeout=4) self.assertEqual(response.status_code, 500)
async def test_body_bigger_than_expected_expects_rejected(self): app = Vibora(route_limits=RouteLimits(max_body_size=1)) @app.route('/', methods=['POST']) async def home(request: Request): await request.stream.read() return Response(b'Wrong. Request should halted earlier.') with app.test_client() as client: response = await client.post('/', body=b'12') self.assertEqual(response.status_code, 413)
async def test_simple_post__expects_correctly_interpreted(self): app = Vibora() @app.route('/', methods=['POST']) async def home(request: Request): return JsonResponse((await request.form())) async with app.test_client() as client: response = await client.post('/', form={'a': 1, 'b': 2}) self.assertDictEqual(response.json(), {'a': '1', 'b': '2'})
async def test_headers_smaller_than_limit_expects_200(self): app = Vibora(server_limits=ServerLimits(max_headers_size=1 * 1024 * 1024)) @app.route('/', methods=['GET']) async def home(): return Response(b'Correct. Request should pass without problems.') with app.test_client() as client: response = await client.get('/') self.assertEqual(response.status_code, 200)
async def test_custom_body_limit_per_route_expects_successful(self): app = Vibora(route_limits=RouteLimits(max_body_size=1)) @app.route('/', methods=['POST'], limits=RouteLimits(max_body_size=2)) async def home(request: Request): await request.stream.read() return Response(b'Correct. Request should pass without problems.') with app.test_client() as client: response = await client.post('/', body=b'11') self.assertEqual(response.status_code, 200)
async def test_simple_form_expects_correctly_parsed(self): app = Vibora() @app.route('/', methods=['POST']) async def home(request: Request): form = await request.form() return JsonResponse(form) with app.test_client() as client: response = await client.post('/', form={'a': 1, 'b': 2}) self.assertEqual(response.status_code, 200) self.assertDictEqual(response.json(), {'a': '1', 'b': '2'})
async def test_default_expects_static_cache(self): app = Vibora() @app.route('/', cache=False) async def home(): return JsonResponse({'now': time.time()}) async with app.test_client() as client: response1 = await client.get('/') response2 = await client.get('/') self.assertNotEqual(response1.content, response2.content)
async def test_extra_headers__expects_correctly_evaluated(self): app = Vibora() @app.route('/') async def get_headers(request: Request): return JsonResponse(request.headers.dump()) client = app.test_client() token = str(uuid.uuid4()) response = await client.get('/', headers={'x-access-token': token}) response = json.loads(response.content) self.assertEqual(response.get('x-access-token'), token)
async def test_simple_form_expects_correctly_parsed(self): app = Vibora() @app.route("/", methods=["POST"]) async def home(request: Request): form = await request.form() return JsonResponse(form) async with app.test_client() as client: response = await client.post("/", form={"a": 1, "b": 2}) self.assertEqual(response.status_code, 200) self.assertDictEqual(response.json(), {"a": "1", "b": "2"})
class RedirectStrategyTestCase(TestSuite): def setUp(self): self.app = Vibora(router_strategy=RouterStrategy.REDIRECT) async def test_missing_slash_expects_redirect(self): @self.app.route('/asd', methods=['GET']) async def home(): return Response(b'123') client = self.app.test_client(follow_redirects=False) self.assertEqual((await client.request('/asd/')).status_code, 301) async def test_missing_slash_with_default_post_route_expects_not_found( self): @self.app.route('/asd', methods=['POST']) async def home(): return Response(b'123') client = self.app.test_client() self.assertEqual((await client.request('/asd/')).status_code, 404) async def test_wrong_method_expects_405_response(self): @self.app.route('/asd/', methods=['GET']) async def home(): return Response(b'') client = self.app.test_client() self.assertEqual( (await client.request('/asd', method='POST')).status_code, 405) async def test_additional_slash_expects_redirected(self): @self.app.route('/asd/', methods=['GET']) async def home(): return Response(b'') client = self.app.test_client(follow_redirects=False) response = await client.request('/asd', method='GET') self.assertEqual(response.status_code, 301) self.assertEqual('/asd/', response.headers['location'])
async def test_custom_body_limit_more_restrictive_per_route_expects_successful(self): app = Vibora( route_limits=RouteLimits(max_body_size=100) ) @app.route('/', methods=['POST'], limits=RouteLimits(max_body_size=1)) async def home(request: Request): await request.stream.read() return Response(b'Wrong. Request must be blocked because this route is more restrictive.') with app.test_client() as client: response = await client.post('/', body=b'11') self.assertEqual(response.status_code, 413)
async def test_static_cache_not_skipping_hooks(self): app = Vibora() @app.route('/', cache=Static(skip_hooks=False)) async def home(): return JsonResponse({'now': time.time()}) client = app.test_client() response1 = await client.get('/') response2 = await client.get('/') self.assertEqual(response1.content, response2.content) client.close()
async def test_single_component_in_route(self): class Config: def __init__(self): self.name = b"test" app = Vibora() app.components.add(Config()) @app.route("/") async def home(config: Config): return Response(config.name) async with app.test_client() as client: response = await client.get("/") self.assertEqual(response.content, app.components[Config].name)
async def test_non_timeout_case_expects_successful_response(self): app = Vibora() @app.route('/', limits=RouteLimits(timeout=1)) async def home(): return Response(b'Correct.') async with app.test_client() as client: response = await client.get('/', timeout=4) self.assertEqual(response.status_code, 200) # We wait to see if the server correctly removed the timeout watcher # otherwise an exception will raise. await asyncio.sleep(2)
async def test_override_request_try_parent_one(self): class Request2(Request): @property def test(self): return "test" app = Vibora() app.request_class = Request2 @app.route("/") async def home(request: Request): return Response(request.url) async with app.test_client() as client: response = await client.get("/") self.assertEqual(response.content, b"/")
async def test_override_request_expects_successful(self): class Request2(Request): @property def test(self): return "test" app = Vibora() app.request_class = Request2 @app.route("/") async def home(request: Request2): return Response(request.test.encode()) async with app.test_client() as client: response = await client.get("/") self.assertEqual(response.content, b"test")
async def test_sync_iterator_expects_successful_response(self): app = Vibora() def generator(): yield b'1' yield b'2' yield b'3' @app.route('/', limits=RouteLimits(timeout=5)) async def home(): return StreamingResponse(generator) async with app.test_client() as client: response = await client.get('/') self.assertEqual(response.content, b'123')
async def test_render_in_vibora_app(self): """ check render usage in Vibora app """ app = Vibora(__name__) app.registry = aioprometheus.Registry() app.events_counter = aioprometheus.Counter("events", "Number of events.") app.registry.register(app.events_counter) @app.route("/") async def index(request: Request): app.events_counter.inc({"path": "/"}) return Response(b"hello") @app.route("/metrics") async def handle_metrics(request: Request): """ Negotiate a response format by inspecting the ACCEPTS headers and selecting the most efficient format. Render metrics in the registry into the chosen format and return a response. """ content, http_headers = aioprometheus.render( app.registry, [request.headers.get("accept")] ) return Response(content, headers=http_headers) # NOTE: Vibora client.get HTTP headers handling seem to expect case-sensitive. # Must use Accept and not accept or ACCEPT! Where as response handling of # requests doesn't seem to care. # Until Vibora #139 is resolved we must use "Accept". # The test client also starts the web service client = app.test_client() # Access root to increment metric counter response = await client.get("/") self.assertEqual(response.status_code, 200) # Get default format response = await client.get("/metrics", headers={"Accept": "*/*"}) self.assertEqual(response.status_code, 200) self.assertIn( aioprometheus.formats.TEXT_CONTENT_TYPE, [response.headers.get("Content-Type")], ) # Get text format response = await client.get("/metrics", headers={"Accept": "text/plain;"}) self.assertEqual(response.status_code, 200) self.assertIn( aioprometheus.formats.TEXT_CONTENT_TYPE, [response.headers.get("content-type")], ) # # Get binary format response = await client.get( "/metrics", headers={"Accept": aioprometheus.formats.BINARY_CONTENT_TYPE} ) self.assertEqual(response.status_code, 200) self.assertIn( aioprometheus.formats.BINARY_CONTENT_TYPE, [response.headers.get("content-type")], )