Ejemplo n.º 1
0
    def test_multiple_routes(self):
        app = AzulChaliceApp('testing', spec={'foo': 'bar'})

        @app.route('/foo',
                   methods=['GET', 'PUT'],
                   path_spec={'a': 'b'},
                   method_spec={'c': 'd'})
        @app.route('/foo/too',
                   methods=['GET'],
                   path_spec={'e': 'f'},
                   method_spec={'g': 'h'})
        def route():
            pass  # no coverage

        expected_specs = {
            'foo': 'bar',
            'paths': {
                '/foo': {
                    'a': 'b',
                    'get': {
                        'c': 'd'
                    },
                    'put': {
                        'c': 'd'
                    }
                },
                '/foo/too': {
                    'e': 'f',
                    'get': {
                        'g': 'h'
                    }
                }
            }
        }
        self.assertEqual(app.specs, expected_specs)
Ejemplo n.º 2
0
    def test_unannotated(self):
        app = AzulChaliceApp('testing', spec={'foo': 'bar'})

        @app.route('/foo', methods=['GET', 'PUT'])
        def route():
            pass  # no coverage

        self.assertEqual(app.specs, {'foo': 'bar', 'paths': {}})
Ejemplo n.º 3
0
 def test_already_annotated_top_level_spec(self):
     with self.assertRaises(AssertionError):
         AzulChaliceApp('testing',
                        spec={'paths': {
                            '/': {
                                'already': 'annotated'
                            }
                        }})
Ejemplo n.º 4
0
    def test_just_path_spec(self):
        app = AzulChaliceApp('testing', spec={'foo': 'bar'})

        @app.route('/foo', methods=['GET', 'PUT'], path_spec={'a': 'b'})
        def route():
            pass  # no coverage

        expected_spec = {'foo': 'bar', 'paths': {'/foo': {'a': 'b'}}}
        self.assertEqual(app.specs, expected_spec)
Ejemplo n.º 5
0
 def test_top_level_spec(self):
     spec = {'foo': 'bar'}
     app = AzulChaliceApp('testing', spec=spec)
     self.assertEqual(app.specs, {
         'foo': 'bar',
         'paths': {}
     }, "Confirm 'paths' is added")
     spec['new key'] = 'new value'
     self.assertNotIn('new key', app.specs,
                      'Changing input object should not affect specs')
Ejemplo n.º 6
0
    def test_duplicate_method_specs(self):
        app = AzulChaliceApp('testing', spec={'foo': 'bar'})

        with self.assertRaises(AssertionError) as cm:

            @app.route('/foo', methods=['GET'], method_spec={'a': 'b'})
            @app.route('/foo', methods=['GET'], method_spec={'a': 'XXX'})
            def route():
                pass

        self.assertEqual(
            str(cm.exception),
            'Only specify method_spec once per route path and method')
Ejemplo n.º 7
0
    def test_duplicate_path_specs(self):
        app = AzulChaliceApp('testing', spec={'foo': 'bar'})

        @app.route('/foo', ['PUT'], path_spec={'a': 'XXX'})
        def route1():
            pass

        with self.assertRaises(AssertionError) as cm:

            @app.route('/foo', ['GET'], path_spec={'a': 'b'})
            def route2():
                pass

        self.assertEqual(str(cm.exception),
                         'Only specify path_spec once per route path')
Ejemplo n.º 8
0
    def test_fully_annotated_override(self):
        app = AzulChaliceApp('testing', spec={'foo': 'bar'})
        path_spec = {'a': 'b', 'get': {'c': 'd'}}

        with self.assertRaises(AssertionError) as cm:

            @app.route('/foo',
                       methods=['GET'],
                       path_spec=path_spec,
                       method_spec={'e': 'f'})
            def route():
                pass  # no coverage

        self.assertEqual(
            str(cm.exception),
            'Only specify method_spec once per route path and method')
Ejemplo n.º 9
0
    def test_shared_path_spec(self):
        """
        Assert that, when sharing the path_spec, routes don't overwrite each
        other's properties.
        """
        app = AzulChaliceApp('testing', spec={'foo': 'bar'})
        shared_path_spec = {
            'parameters': [
                params.query('foo', schema.optional({'type': 'string'})),
            ]
        }
        for i in range(2):

            @app.route(f'/swagger-test-{i}',
                       methods=['GET'],
                       cors=True,
                       path_spec=shared_path_spec,
                       method_spec={'summary': f'Swagger test {i}'})
            def swagger_test():
                pass

        method_specs = app.specs['paths'].values()
        self.assertNotEqual(*method_specs)
Ejemplo n.º 10
0
    def test(self):
        magic_message = 'Now you see me'
        traceback_header = 'Traceback (most recent call last):'

        for debug in 0, 1, 2:
            with mock.patch.dict(os.environ, AZUL_DEBUG=str(debug)):
                with self.subTest(debug=debug):
                    log_level = azul_log_level()
                    app = AzulChaliceApp(__name__, unit_test=True)

                    @app.route('/')
                    def fail():
                        raise ValueError(magic_message)

                    server_thread = ChaliceServerThread(
                        app, ChaliceConfig(), 'localhost', 0)
                    server_thread.start()
                    try:
                        host, port = server_thread.address
                        with self.assertLogs(app.log,
                                             level=log_level) as app_log:
                            with self.assertLogs(azul.log,
                                                 level=log_level) as azul_log:
                                response = requests.get(
                                    f"http://{host}:{port}/")
                    finally:
                        server_thread.kill_thread()
                        server_thread.join(timeout=10)
                        if server_thread.is_alive():
                            self.fail('Thread is still alive after joining')

                    self.assertEqual(response.status_code, 500)

                    # The request is always logged
                    self.assertEqual(len(azul_log.output), 2)
                    request_log = "INFO:azul.chalice:Received GET request to '/' without parameters."
                    self.assertEqual(azul_log.output[0], request_log)

                    # The exception is always logged
                    self.assertEqual(len(app_log.output), 1)
                    err_log = 'ERROR:test_app_logging:Caught exception for <function TestAppLogging.test.<locals>.fail'
                    self.assertTrue(app_log.output[0].startswith(err_log))
                    self.assertIn(magic_message, app_log.output[0])
                    self.assertIn(traceback_header, app_log.output[0])

                    if debug:
                        # In debug mode, the response includes the traceback …
                        response = response.content.decode()
                        self.assertTrue(response.startswith(traceback_header))
                        self.assertIn(magic_message, response)
                        # … and the response is logged.
                        self.assertEqual(
                            azul_log.output[1],
                            'DEBUG:azul.chalice:Returning 500 response with headers {"Content-Type": "text/plain"}. '
                            'See next line for the first 1024 characters of the body.\n'
                            + response)
                    else:
                        # Otherwise, a generic error response is returned …
                        self.assertEqual(
                            response.json(), {
                                'Code': 'InternalServerError',
                                'Message': 'An internal server error occurred.'
                            })
                        # … and a generic error message is logged.
                        self.assertEqual(
                            azul_log.output[1],
                            'INFO:azul.chalice:Returning 500 response. To log headers and body, set AZUL_DEBUG to 1.'
                        )
Ejemplo n.º 11
0
 def app(self, spec):
     return AzulChaliceApp('testing', '/app.py', spec=spec)
Ejemplo n.º 12
0
Archivo: app.py Proyecto: NoopDog/azul
from azul import (
    config, )
from azul.chalice import AzulChaliceApp

# This whole file only exists so that we can use Chalice to create the layer
# package and is removed from the final result.

app = AzulChaliceApp(app_name=config.qualified_resource_name('dependencies'),
                     unit_test=False)


@app.route('/')
def foo():
    pass
Ejemplo n.º 13
0
    def test(self):
        magic_message = 'Now you see me'
        traceback_header = 'Traceback (most recent call last):'

        for debug in 0, 1, 2:
            with mock.patch.dict(os.environ, AZUL_DEBUG=str(debug)):
                with self.subTest(debug=debug):
                    log_level = azul_log_level()
                    app = AzulChaliceApp(__name__, '/app.py', unit_test=True)
                    path = '/fail/path'

                    @app.route(path)
                    def fail():
                        raise ValueError(magic_message)

                    server_thread = ChaliceServerThread(
                        app, ChaliceConfig(), 'localhost', 0)
                    server_thread.start()
                    try:
                        host, port = server_thread.address
                        with self.assertLogs(app.log,
                                             level=log_level) as app_log:
                            with self.assertLogs(azul.log,
                                                 level=log_level) as azul_log:
                                response = requests.get(
                                    f'http://{host}:{port}{path}')
                    finally:
                        server_thread.kill_thread()
                        server_thread.join(timeout=10)
                        if server_thread.is_alive():
                            self.fail('Thread is still alive after joining')

                    self.assertEqual(response.status_code, 500)

                    # The request is always logged
                    self.assertEqual(len(azul_log.output), 3)
                    headers = {
                        'host': f'{host}:{port}',
                        'user-agent': 'python-requests/2.26.0',
                        'accept-encoding': 'gzip, deflate, br',
                        'accept': '*/*',
                        'connection': 'keep-alive'
                    }
                    self.assertEqual(
                        azul_log.output[0],
                        f'INFO:azul.chalice:Received GET request for {path!r}, '
                        f'with query null and headers {json.dumps(headers)}.')
                    self.assertEqual(
                        azul_log.output[1],
                        'INFO:azul.chalice:Did not authenticate request.')

                    # The exception is always logged
                    self.assertEqual(len(app_log.output), 1)
                    err_log = f'ERROR:test_app_logging:Caught exception for path {path}'
                    self.assertTrue(app_log.output[0].startswith(err_log))
                    self.assertIn(magic_message, app_log.output[0])
                    self.assertIn(traceback_header, app_log.output[0])

                    if debug:
                        # In debug mode, the response includes the traceback …
                        response = response.content.decode()
                        self.assertTrue(response.startswith(traceback_header))
                        self.assertIn(magic_message, response)
                        # … and the response is logged.
                        self.assertEqual(
                            azul_log.output[2],
                            'DEBUG:azul.chalice:Returning 500 response with headers {"Content-Type": "text/plain"}. '
                            'See next line for the first 1024 characters of the body.\n'
                            + response)
                    else:
                        # Otherwise, a generic error response is returned …
                        self.assertEqual(
                            response.json(), {
                                'Code': 'InternalServerError',
                                'Message': 'An internal server error occurred.'
                            })
                        # … and a generic error message is logged.
                        self.assertEqual(
                            azul_log.output[2],
                            'INFO:azul.chalice:Returning 500 response. To log headers and body, set AZUL_DEBUG to 1.'
                        )
Ejemplo n.º 14
0
from azul import (
    config, )
from azul.chalice import (
    AzulChaliceApp, )

# This whole file only exists so that we can use Chalice to create the layer
# package and is removed from the final result.

app = AzulChaliceApp(app_name=config.qualified_resource_name('dependencies'),
                     app_module_path=__file__,
                     unit_test=False)


@app.route('/')
def foo():
    pass