Example #1
0
    def test_custom_datalayer(self):
        class MyTestDataLayer(DataLayer):
            def init_app(self, app):
                pass

        self.app = Eve(data=MyTestDataLayer, settings=self.settings_file)
        self.assertEqual(type(self.app.data), MyTestDataLayer)
 def test_allow_unknown_with_soft_delete(self):
     my_settings = {
         'ALLOW_UNKNOWN': True,
         'SOFT_DELETE': True,
         'DOMAIN': {'contacts': {}}
     }
     try:
         self.app = Eve(settings=my_settings)
     except TypeError:
         self.fail("ALLOW_UNKNOWN and SOFT_DELETE enabled should not cause "
                   "a crash.")
Example #3
0
 def test_allow_unknown_with_soft_delete(self):
     my_settings = {
         "ALLOW_UNKNOWN": True,
         "SOFT_DELETE": True,
         "DOMAIN": {"contacts": {}},
     }
     try:
         self.app = Eve(settings=my_settings)
     except TypeError:
         self.fail(
             "ALLOW_UNKNOWN and SOFT_DELETE enabled should not cause " "a crash."
         )
Example #4
0
 def test_mongodb_settings(self):
     # Create custom app with mongodb settings.
     settings = {
         'DOMAIN': {
             'contacts': {}
         },
         'MONGO_OPTIONS': {
             'connect': False
         }
     }
     app = Eve(settings=settings)
     # Check if settings are set.
     self.assertEqual(app.config['MONGO_OPTIONS']['connect'],
                      app.config['MONGO_CONNECT'])
     # Prepare a specific schema with mongo specific settings.
     settings = {
         'schema': {
             'name': {
                 'type': 'string'
             },
         },
         'MONGO_OPTIONS': {
             'connect': False
         }
     }
     self.app.register_resource('mongodb_settings', settings)
     # check that settings are set.
     resource_settings = self.app.config['DOMAIN']['mongodb_settings']
     self.assertEqual(resource_settings['MONGO_OPTIONS'],
                      settings['MONGO_OPTIONS'])
     # check that settings are set.
     self.assertEqual(resource_settings['MONGO_OPTIONS']['connect'],
                      settings['MONGO_OPTIONS']['connect'])
Example #5
0
 def test_mongodb_settings(self):
     # Create custom app with mongodb settings.
     settings = {
         "DOMAIN": {
             "contacts": {}
         },
         "MONGO_OPTIONS": {
             "connect": False
         }
     }
     app = Eve(settings=settings)
     # Check if settings are set.
     self.assertEqual(app.config["MONGO_OPTIONS"]["connect"],
                      app.config["MONGO_CONNECT"])
     # Prepare a specific schema with mongo specific settings.
     settings = {
         "schema": {
             "name": {
                 "type": "string"
             }
         },
         "MONGO_OPTIONS": {
             "connect": False
         },
     }
     self.app.register_resource("mongodb_settings", settings)
     # check that settings are set.
     resource_settings = self.app.config["DOMAIN"]["mongodb_settings"]
     self.assertEqual(resource_settings["MONGO_OPTIONS"],
                      settings["MONGO_OPTIONS"])
     # check that settings are set.
     self.assertEqual(
         resource_settings["MONGO_OPTIONS"]["connect"],
         settings["MONGO_OPTIONS"]["connect"],
     )
Example #6
0
 def test_custom_datalayer(self):
     class MyTestDataLayer(DataLayer):
         def init_app(self, app):
             pass
         pass
     self.app = Eve(data=MyTestDataLayer, settings=self.settings_file)
     self.assertEqual(type(self.app.data), MyTestDataLayer)
Example #7
0
File: config.py Project: sunbit/eve
 def test_allow_unknown_with_soft_delete(self):
     my_settings = {
         "ALLOW_UNKNOWN": True,
         "SOFT_DELETE": True,
         "DOMAIN": {"contacts": {}},
     }
     try:
         self.app = Eve(settings=my_settings)
     except TypeError:
         self.fail(
             "ALLOW_UNKNOWN and SOFT_DELETE enabled should not cause " "a crash."
         )
Example #8
0
 def test_custom_kwargs(self):
     self.app = Eve("unittest",
                    static_folder="/",
                    settings=self.settings_file)
     self.assertEqual(self.app.static_folder, "/")
Example #9
0
#!/usr/local/bin/python2.7
# -*-coding:UTF-8-sig -*-
from eve.flaskapp import Eve
from eve_sqlalchemy import SQL

from base import Base

app = Eve(auth=None, settings='config/eve-config.py', data=SQL)
db = app.data.driver
Base.metadata.bind = db.engine
db.Model = Base
db.create_all()

if __name__ == '__main__':
    app.run(host="0.0.0.0",port=5000,debug=True)
    
 def test_custom_kwargs(self):
     self.app = Eve('unittest', static_folder='/',
                    settings=self.settings_file)
     self.assertEqual(self.app.static_folder, '/')
Example #11
0
 def test_custom_import_name(self):
     self.app = Eve("custom_import_name", settings="eve/tests/test_settings.py")
     self.assertEqual(self.app.import_name, "custom_import_name")
Example #12
0
 def test_settings_as_dict(self):
     my_settings = {"API_VERSION": "override!", "DOMAIN": {"contacts": {}}}
     self.app = Eve(settings=my_settings)
     self.assertEqual(self.app.config["API_VERSION"], "override!")
     # did not reset other defaults
     self.assertEqual(self.app.config["MONGO_WRITE_CONCERN"], {"w": 1})
Example #13
0
File: config.py Project: Tefnet/eve
class TestConfig(TestBase):
    def test_default_import_name(self):
        self.assertEqual(self.app.import_name, eve.__package__)

    def test_custom_import_name(self):
        self.app = Eve('custom_import_name',
                       settings='eve/tests/test_settings.py')
        self.assertEqual(self.app.import_name, 'custom_import_name')

    def test_custom_kwargs(self):
        self.app = Eve('custom_import_name',
                       static_folder='/',
                       settings='eve/tests/test_settings.py')
        self.assertEqual(self.app.static_folder, '/')

    def test_regexconverter(self):
        regex_converter = self.app.url_map.converters.get('regex')
        self.assertEqual(regex_converter, RegexConverter)

    def test_default_validator(self):
        self.assertEqual(self.app.validator, Validator)

    def test_default_datalayer(self):
        self.assertEqual(type(self.app.data), Mongo)

    def test_default_settings(self):
        self.assertEqual(self.app.settings, self.settings_file)

    def test_unexisting_pyfile_config(self):
        self.assertRaises(IOError, Eve, settings='an_unexisting_pyfile.py')

    def test_unexisting_env_config(self):
        env = os.environ
        try:
            os.environ = {'EVE_SETTINGS': 'an_unexisting_pyfile.py'}
            self.assertRaises(IOError, Eve)
        finally:
            os.environ = env

    def test_custom_validator(self):
        class MyTestValidator(Validator):
            pass

        self.app = Eve(validator=MyTestValidator, settings=self.settings_file)
        self.assertEqual(self.app.validator, MyTestValidator)

    def test_custom_datalayer(self):
        class MyTestDataLayer(DataLayer):
            def init_app(self, app):
                pass

            pass

        self.app = Eve(data=MyTestDataLayer, settings=self.settings_file)
        self.assertEqual(type(self.app.data), MyTestDataLayer)

    def test_validate_domain_struct(self):
        del self.app.config['DOMAIN']
        self.assertValidateConfigFailure('missing')

        self.app.config['DOMAIN'] = []
        self.assertValidateConfigFailure('must be a dict')

        self.app.config['DOMAIN'] = {}
        self.assertValidateConfigFailure('must contain at least one')

    def test_validate_resource_methods(self):
        self.app.config['RESOURCE_METHODS'] = ['PUT', 'GET', 'DELETE', 'POST']
        self.assertValidateConfigFailure('PUT')

    def test_validate_item_methods(self):
        self.app.config['ITEM_METHODS'] = ['PUT', 'GET', 'POST', 'DELETE']
        self.assertValidateConfigFailure('PUT, POST')

    def test_validate_schema_methods(self):
        test = {
            'methods': ['PUT', 'GET', 'DELETE', 'POST'],
        }
        self.app.config['DOMAIN']['test_resource'] = test
        self.assertValidateConfigFailure('PUT')

    def test_validate_schema_item_methods(self):
        test = {
            'methods': ['GET'],
            'item_methods': ['PUT'],
        }
        self.app.config['DOMAIN']['test_resource'] = test
        self.assertValidateConfigFailure('PUT')

    def test_validate_datecreated_in_schema(self):
        self.assertUnallowedField(eve.DATE_CREATED)

    def test_validate_lastupdated_in_schema(self):
        self.assertUnallowedField(eve.LAST_UPDATED)

    def test_validate_idfield_in_schema(self):
        self.assertUnallowedField(eve.ID_FIELD)

    def assertUnallowedField(self, field):
        self.domain.clear()
        schema = {field: {'type': 'datetime'}}
        self.domain['resource'] = {'schema': schema}
        self.app.set_defaults()
        self.assertValidateSchemaFailure('resource', schema, field)

    def test_validate_schema(self):
        # lack of 'collection' key for 'data_collection' rule
        schema = self.domain['invoices']['schema']
        del (schema['person']['data_relation']['collection'])
        self.assertValidateSchemaFailure('invoices', schema, 'collection')

    def test_set_schema_defaults(self):
        # default data_relation field value
        schema = self.domain['invoices']['schema']
        data_relation = schema['person']['data_relation']
        self.assertTrue('field' in data_relation)
        self.assertEqual(data_relation['field'], self.app.config['ID_FIELD'])

    def test_set_defaults(self):
        self.domain.clear()
        resource = 'plurals'
        self.domain[resource] = {}

        self.app.set_defaults()

        settings = self.domain[resource]
        self.assertEqual(settings['url'], resource)
        self.assertEqual(settings['methods'],
                         self.app.config['RESOURCE_METHODS'])
        self.assertEqual(settings['public_methods'],
                         self.app.config['PUBLIC_METHODS'])
        self.assertEqual(settings['allowed_roles'],
                         self.app.config['ALLOWED_ROLES'])
        self.assertEqual(settings['cache_control'],
                         self.app.config['CACHE_CONTROL'])
        self.assertEqual(settings['cache_expires'],
                         self.app.config['CACHE_EXPIRES'])
        self.assertEqual(settings['item_methods'],
                         self.app.config['ITEM_METHODS'])
        self.assertEqual(settings['public_item_methods'],
                         self.app.config['PUBLIC_ITEM_METHODS'])
        self.assertEqual(settings['allowed_item_roles'],
                         self.app.config['ALLOWED_ITEM_ROLES'])
        self.assertEqual(settings['item_lookup'],
                         self.app.config['ITEM_LOOKUP'])
        self.assertEqual(settings['item_lookup_field'],
                         self.app.config['ITEM_LOOKUP_FIELD'])
        self.assertEqual(settings['item_url'], self.app.config['ITEM_URL'])
        self.assertEqual(settings['item_title'],
                         resource.rstrip('s').capitalize())
        self.assertEqual(settings['filters'], self.app.config['FILTERS'])
        self.assertEqual(settings['sorting'], self.app.config['SORTING'])
        self.assertEqual(settings['pagination'], self.app.config['PAGINATION'])
        self.assertEqual(settings['auth_username_field'],
                         self.app.config['AUTH_USERNAME_FIELD'])

        self.assertNotEqual(settings['schema'], None)
        self.assertEqual(type(settings['schema']), dict)
        self.assertEqual(len(settings['schema']), 0)
        self.assertEqual(settings['datasource'], {
            'source': resource,
            'filter': None
        })

    def test_validate_roles(self):
        for resource in self.domain:
            self.assertValidateRoles(resource, 'allowed_roles')
            self.assertValidateRoles(resource, 'allowed_item_roles')

    def assertValidateRoles(self, resource, directive):
        self.domain[resource][directive] = 'admin'
        self.assertValidateConfigFailure(directive)
        self.domain[resource][directive] = []
        self.assertValidateConfigFailure(directive)
        self.domain[resource][directive] = ['admin', 'dev']
        self.assertValidateConfigSuccess()
        self.domain[resource][directive] = None
        self.assertValidateConfigSuccess()

    def assertValidateConfigSuccess(self):
        try:
            self.app.validate_domain_struct()
            self.app.validate_config()
        except ConfigException, e:
            self.fail('ConfigException not expected: %s' % e)
Example #14
0
class TestConfig(TestBase):

    def test_default_import_name(self):
        self.assertEqual(self.app.import_name, eve.__package__)

    def test_custom_import_name(self):
        self.app = Eve('custom_import_name',
                       settings='eve/tests/test_settings.py')
        self.assertEqual(self.app.import_name, 'custom_import_name')

    def test_custom_kwargs(self):
        self.app = Eve('custom_import_name', static_folder='/',
                       settings='eve/tests/test_settings.py')
        self.assertEqual(self.app.static_folder, '/')

    def test_regexconverter(self):
        regex_converter = self.app.url_map.converters.get('regex')
        self.assertEqual(regex_converter, RegexConverter)

    def test_default_validator(self):
        self.assertEqual(self.app.validator, Validator)

    def test_default_datalayer(self):
        self.assertEqual(type(self.app.data), Mongo)

    def test_default_settings(self):
        self.assertEqual(self.app.settings, self.settings_file)

    def test_unexisting_pyfile_config(self):
        self.assertRaises(IOError, Eve, settings='an_unexisting_pyfile.py')

    def test_unexisting_env_config(self):
        env = os.environ
        try:
            os.environ = {'EVE_SETTINGS': 'an_unexisting_pyfile.py'}
            self.assertRaises(IOError, Eve)
        finally:
            os.environ = env

    def test_custom_validator(self):
        class MyTestValidator(Validator):
            pass
        self.app = Eve(validator=MyTestValidator,
                       settings=self.settings_file)
        self.assertEqual(self.app.validator, MyTestValidator)

    def test_custom_datalayer(self):
        class MyTestDataLayer(DataLayer):
            def init_app(self, app):
                pass
            pass
        self.app = Eve(data=MyTestDataLayer, settings=self.settings_file)
        self.assertEqual(type(self.app.data), MyTestDataLayer)

    def test_validate_domain_struct(self):
        del self.app.config['DOMAIN']
        self.assertValidateConfigFailure('missing')

        self.app.config['DOMAIN'] = []
        self.assertValidateConfigFailure('must be a dict')

        self.app.config['DOMAIN'] = {}
        self.assertValidateConfigFailure('must contain at least one')

    def test_validate_resource_methods(self):
        self.app.config['RESOURCE_METHODS'] = ['PUT', 'GET', 'DELETE', 'POST']
        self.assertValidateConfigFailure('PUT')

    def test_validate_item_methods(self):
        self.app.config['ITEM_METHODS'] = ['PUT', 'GET', 'POST', 'DELETE']
        self.assertValidateConfigFailure('PUT, POST')

    def test_validate_schema_methods(self):
        test = {
            'methods': ['PUT', 'GET', 'DELETE', 'POST'],
        }
        self.app.config['DOMAIN']['test_resource'] = test
        self.assertValidateConfigFailure('PUT')

    def test_validate_schema_item_methods(self):
        test = {
            'methods': ['GET'],
            'item_methods': ['PUT'],
        }
        self.app.config['DOMAIN']['test_resource'] = test
        self.assertValidateConfigFailure('PUT')

    def test_validate_datecreated_in_schema(self):
        self.assertUnallowedField(eve.DATE_CREATED)

    def test_validate_lastupdated_in_schema(self):
        self.assertUnallowedField(eve.LAST_UPDATED)

    def test_validate_idfield_in_schema(self):
        self.assertUnallowedField(eve.ID_FIELD)

    def assertUnallowedField(self, field):
        self.domain.clear()
        self.domain['resource'] = {
            'schema': {
                field: {'type': 'datetime'}
            }
        }
        self.app.set_defaults()
        self.assertValidateConfigFailure('automatically')

    def test_set_defaults(self):
        self.domain.clear()
        resource = 'plurals'
        self.domain[resource] = {}

        self.app.set_defaults()

        settings = self.domain[resource]
        self.assertEqual(settings['url'], resource)
        self.assertEqual(settings['methods'],
                         self.app.config['RESOURCE_METHODS'])
        self.assertEqual(settings['public_methods'],
                         self.app.config['PUBLIC_METHODS'])
        self.assertEqual(settings['allowed_roles'],
                         self.app.config['ALLOWED_ROLES'])
        self.assertEqual(settings['cache_control'],
                         self.app.config['CACHE_CONTROL'])
        self.assertEqual(settings['cache_expires'],
                         self.app.config['CACHE_EXPIRES'])
        self.assertEqual(settings['item_methods'],
                         self.app.config['ITEM_METHODS'])
        self.assertEqual(settings['public_item_methods'],
                         self.app.config['PUBLIC_ITEM_METHODS'])
        self.assertEqual(settings['allowed_item_roles'],
                         self.app.config['ALLOWED_ITEM_ROLES'])
        self.assertEqual(settings['item_lookup'],
                         self.app.config['ITEM_LOOKUP'])
        self.assertEqual(settings['item_lookup_field'],
                         self.app.config['ITEM_LOOKUP_FIELD'])
        self.assertEqual(settings['item_url'],
                         self.app.config['ITEM_URL'])
        self.assertEqual(settings['item_title'],
                         resource.rstrip('s').capitalize())
        self.assertEqual(settings['item_cache_control'],
                         self.app.config['ITEM_CACHE_CONTROL'])
        self.assertNotEqual(settings['schema'], None)
        self.assertEqual(type(settings['schema']), dict)
        self.assertEqual(len(settings['schema']), 0)
        self.assertEqual(settings['datasource'],
                         {'source': resource, 'filter': None})

    def test_validate_roles(self):
        for resource in self.domain:
            self.assertValidateRoles(resource, 'allowed_roles')
            self.assertValidateRoles(resource, 'allowed_item_roles')

    def assertValidateRoles(self, resource, directive):
        self.domain[resource][directive] = 'admin'
        self.assertValidateConfigFailure(directive)
        self.domain[resource][directive] = []
        self.assertValidateConfigFailure(directive)
        self.domain[resource][directive] = ['admin', 'dev']
        self.assertValidateConfigSuccess()
        self.domain[resource][directive] = None
        self.assertValidateConfigSuccess()

    def assertValidateConfigSuccess(self):
        try:
            self.app.validate_domain_struct()
            self.app.validate_config()
        except ConfigException, e:
            self.fail('ConfigException not expected: %s' % e)
Example #15
0
 def test_custom_kwargs(self):
     self.app = Eve("custom_import_name", static_folder="/", settings="eve/tests/test_settings.py")
     self.assertEqual(self.app.static_folder, "/")
Example #16
0
File: config.py Project: sunbit/eve
 def test_existing_env_config(self):
     env = os.environ
     os.environ = {"EVE_SETTINGS": "test_settings_env.py"}
     self.app = Eve()
     self.assertTrue("env_domain" in self.app.config["DOMAIN"])
     os.environ = env
Example #17
0
File: config.py Project: sunbit/eve
class TestConfig(TestBase):
    def test_allow_unknown_with_soft_delete(self):
        my_settings = {
            "ALLOW_UNKNOWN": True,
            "SOFT_DELETE": True,
            "DOMAIN": {"contacts": {}},
        }
        try:
            self.app = Eve(settings=my_settings)
        except TypeError:
            self.fail(
                "ALLOW_UNKNOWN and SOFT_DELETE enabled should not cause " "a crash."
            )

    def test_default_import_name(self):
        self.assertEqual(self.app.import_name, eve.__package__)

    def test_custom_import_name(self):
        self.app = Eve("unittest", settings=self.settings_file)
        self.assertEqual(self.app.import_name, "unittest")

    def test_custom_kwargs(self):
        self.app = Eve("unittest", static_folder="/", settings=self.settings_file)
        self.assertEqual(self.app.static_folder, "/")

    def test_regexconverter(self):
        regex_converter = self.app.url_map.converters.get("regex")
        self.assertEqual(regex_converter, RegexConverter)

    def test_default_validator(self):
        self.assertEqual(self.app.validator, Validator)

    def test_default_datalayer(self):
        self.assertEqual(type(self.app.data), Mongo)

    def test_default_settings(self):
        self.assertEqual(self.app.settings, self.settings_file)

        # TODO add tests for other global default values
        self.assertEqual(self.app.config["RATE_LIMIT_GET"], None)
        self.assertEqual(self.app.config["RATE_LIMIT_POST"], None)
        self.assertEqual(self.app.config["RATE_LIMIT_PATCH"], None)
        self.assertEqual(self.app.config["RATE_LIMIT_DELETE"], None)

        self.assertEqual(self.app.config["MONGO_HOST"], "localhost")
        self.assertEqual(self.app.config["MONGO_PORT"], 27017)
        self.assertEqual(self.app.config["MONGO_QUERY_BLACKLIST"], ["$where", "$regex"])
        self.assertEqual(self.app.config["MONGO_WRITE_CONCERN"], {"w": 1})
        self.assertEqual(self.app.config["ISSUES"], "_issues")

        self.assertEqual(self.app.config["OPLOG"], False)
        self.assertEqual(self.app.config["OPLOG_NAME"], "oplog")
        self.assertEqual(self.app.config["OPLOG_ENDPOINT"], None)
        self.assertEqual(self.app.config["OPLOG_AUDIT"], True)
        self.assertEqual(
            self.app.config["OPLOG_METHODS"], ["DELETE", "POST", "PATCH", "PUT"]
        )
        self.assertEqual(
            self.app.config["OPLOG_CHANGE_METHODS"], ["DELETE", "PATCH", "PUT"]
        )
        self.assertEqual(self.app.config["QUERY_WHERE"], "where")
        self.assertEqual(self.app.config["QUERY_PROJECTION"], "projection")
        self.assertEqual(self.app.config["QUERY_SORT"], "sort")
        self.assertEqual(self.app.config["QUERY_PAGE"], "page")
        self.assertEqual(self.app.config["QUERY_MAX_RESULTS"], "max_results")
        self.assertEqual(self.app.config["QUERY_EMBEDDED"], "embedded")
        self.assertEqual(self.app.config["QUERY_AGGREGATION"], "aggregate")

        self.assertEqual(self.app.config["JSON_SORT_KEYS"], False)
        self.assertEqual(self.app.config["SOFT_DELETE"], False)
        self.assertEqual(self.app.config["DELETED"], "_deleted")
        self.assertEqual(self.app.config["SHOW_DELETED_PARAM"], "show_deleted")
        self.assertEqual(
            self.app.config["STANDARD_ERRORS"],
            [400, 401, 404, 405, 406, 409, 410, 412, 422, 428, 429],
        )
        self.assertEqual(self.app.config["UPSERT_ON_PUT"], True)
        self.assertEqual(
            self.app.config["JSON_REQUEST_CONTENT_TYPES"], ["application/json"]
        )
        self.assertEqual(self.app.config["NORMALIZE_DOTTED_FIELDS"], True)

    def test_settings_as_dict(self):
        my_settings = {"API_VERSION": "override!", "DOMAIN": {"contacts": {}}}
        self.app = Eve(settings=my_settings)
        self.assertEqual(self.app.config["API_VERSION"], "override!")
        # did not reset other defaults
        self.assertEqual(self.app.config["MONGO_WRITE_CONCERN"], {"w": 1})

    def test_existing_env_config(self):
        env = os.environ
        os.environ = {"EVE_SETTINGS": "test_settings_env.py"}
        self.app = Eve()
        self.assertTrue("env_domain" in self.app.config["DOMAIN"])
        os.environ = env

    def test_unexisting_env_config(self):
        env = os.environ
        try:
            os.environ = {"EVE_SETTINGS": "an_unexisting_pyfile.py"}
            self.assertRaises(IOError, Eve)
        finally:
            os.environ = env

    def test_custom_validator(self):
        class MyTestValidator(Validator):
            pass

        self.app = Eve(validator=MyTestValidator, settings=self.settings_file)
        self.assertEqual(self.app.validator, MyTestValidator)

    def test_custom_datalayer(self):
        class MyTestDataLayer(DataLayer):
            def init_app(self, app):
                pass

        self.app = Eve(data=MyTestDataLayer, settings=self.settings_file)
        self.assertEqual(type(self.app.data), MyTestDataLayer)

    def test_validate_domain_struct(self):
        del self.app.config["DOMAIN"]
        self.assertValidateConfigFailure("missing")

        self.app.config["DOMAIN"] = []
        self.assertValidateConfigFailure("must be a dict")

        self.app.config["DOMAIN"] = {}
        self.assertValidateConfigSuccess()

    def test_validate_resource_methods(self):
        self.app.config["RESOURCE_METHODS"] = ["PUT", "GET", "DELETE", "POST"]
        self.assertValidateConfigFailure("PUT")

    def test_validate_item_methods(self):
        self.app.config["ITEM_METHODS"] = ["PUT", "GET", "POST", "DELETE"]
        self.assertValidateConfigFailure(["POST", "PUT"])

    def test_validate_schema_methods(self):
        test = {"resource_methods": ["PUT", "GET", "DELETE", "POST"]}
        self.app.config["DOMAIN"]["test_resource"] = test
        self.assertValidateConfigFailure("PUT")

    def test_validate_schema_item_methods(self):
        test = {"resource_methods": ["GET"], "item_methods": ["POST"]}
        self.app.config["DOMAIN"]["test_resource"] = test
        self.assertValidateConfigFailure("PUT")

    def test_validate_datecreated_in_schema(self):
        self.assertUnallowedField(eve.DATE_CREATED)

    def test_validate_lastupdated_in_schema(self):
        self.assertUnallowedField(eve.LAST_UPDATED)

    def assertUnallowedField(self, field, field_type="datetime"):
        self.domain.clear()
        schema = {field: {"type": field_type}}
        self.domain["resource"] = {"schema": schema}
        self.app.set_defaults()
        self.assertValidateSchemaFailure("resource", schema, field)

    def test_validate_schema(self):
        # lack of 'collection' key for 'data_collection' rule
        schema = self.domain["invoices"]["schema"]
        del schema["person"]["data_relation"]["resource"]
        self.assertValidateSchemaFailure("invoices", schema, "resource")

    def test_validate_invalid_field_names(self):
        schema = self.domain["invoices"]["schema"]
        schema["te$t"] = {"type": "string"}
        self.assertValidateSchemaFailure("invoices", schema, "te$t")
        del schema["te$t"]

        schema["te.t"] = {"type": "string"}
        self.assertValidateSchemaFailure("invoices", schema, "te.t")
        del schema["te.t"]

        schema["test_a_dict_schema"] = {
            "type": "dict",
            "schema": {"te$t": {"type": "string"}},
        }
        self.assertValidateSchemaFailure("invoices", schema, "te$t")

        schema["test_a_dict_schema"]["schema"] = {"te.t": {"type": "string"}}
        self.assertValidateSchemaFailure("invoices", schema, "te.t")

    def test_set_schema_defaults(self):
        # default data_relation field value
        schema = self.domain["invoices"]["schema"]
        data_relation = schema["person"]["data_relation"]
        self.assertTrue("field" in data_relation)
        self.assertEqual(data_relation["field"], self.domain["contacts"]["id_field"])
        id_field = self.domain["invoices"]["id_field"]
        self.assertTrue(id_field in schema)
        self.assertEqual(schema[id_field], {"type": "objectid"})

    def test_set_defaults(self):
        self.domain.clear()
        resource = "plurals"
        self.domain[resource] = {}
        self.app.set_defaults()
        self._test_defaults_for_resource(resource)
        settings = self.domain[resource]
        self.assertEqual(len(settings["schema"]), 1)

    def _test_defaults_for_resource(self, resource):
        settings = self.domain[resource]
        self.assertEqual(settings["url"], resource)
        self.assertEqual(
            settings["internal_resource"], self.app.config["INTERNAL_RESOURCE"]
        )
        self.assertEqual(
            settings["resource_methods"], self.app.config["RESOURCE_METHODS"]
        )
        self.assertEqual(settings["public_methods"], self.app.config["PUBLIC_METHODS"])
        self.assertEqual(settings["allowed_roles"], self.app.config["ALLOWED_ROLES"])
        self.assertEqual(
            settings["allowed_read_roles"], self.app.config["ALLOWED_READ_ROLES"]
        )
        self.assertEqual(
            settings["allowed_write_roles"], self.app.config["ALLOWED_WRITE_ROLES"]
        )
        self.assertEqual(settings["cache_control"], self.app.config["CACHE_CONTROL"])
        self.assertEqual(settings["cache_expires"], self.app.config["CACHE_EXPIRES"])
        self.assertEqual(settings["item_methods"], self.app.config["ITEM_METHODS"])
        self.assertEqual(
            settings["public_item_methods"], self.app.config["PUBLIC_ITEM_METHODS"]
        )
        self.assertEqual(
            settings["allowed_item_roles"], self.app.config["ALLOWED_ITEM_ROLES"]
        )
        self.assertEqual(
            settings["allowed_item_read_roles"],
            self.app.config["ALLOWED_ITEM_READ_ROLES"],
        )
        self.assertEqual(
            settings["allowed_item_write_roles"],
            self.app.config["ALLOWED_ITEM_WRITE_ROLES"],
        )
        self.assertEqual(settings["item_lookup"], self.app.config["ITEM_LOOKUP"])
        self.assertEqual(
            settings["item_lookup_field"], self.app.config["ITEM_LOOKUP_FIELD"]
        )
        self.assertEqual(settings["item_url"], self.app.config["ITEM_URL"])
        self.assertEqual(settings["item_title"], resource.rstrip("s").capitalize())
        self.assertEqual(
            settings["allowed_filters"], self.app.config["ALLOWED_FILTERS"]
        )
        self.assertEqual(settings["projection"], self.app.config["PROJECTION"])
        self.assertEqual(settings["versioning"], self.app.config["VERSIONING"])
        self.assertEqual(settings["soft_delete"], self.app.config["SOFT_DELETE"])
        self.assertEqual(settings["sorting"], self.app.config["SORTING"])
        self.assertEqual(settings["embedding"], self.app.config["EMBEDDING"])
        self.assertEqual(settings["pagination"], self.app.config["PAGINATION"])
        self.assertEqual(settings["auth_field"], self.app.config["AUTH_FIELD"])
        self.assertEqual(settings["allow_unknown"], self.app.config["ALLOW_UNKNOWN"])
        self.assertEqual(
            settings["extra_response_fields"], self.app.config["EXTRA_RESPONSE_FIELDS"]
        )
        self.assertEqual(
            settings["mongo_write_concern"], self.app.config["MONGO_WRITE_CONCERN"]
        )
        self.assertEqual(settings["resource_title"], settings["url"])

        self.assertNotEqual(settings["schema"], None)
        self.assertEqual(type(settings["schema"]), dict)
        self.assertEqual(settings["etag_ignore_fields"], None)

    def test_datasource(self):
        self._test_datasource_for_resource("invoices")

    def _test_datasource_for_resource(self, resource):
        datasource = self.domain[resource]["datasource"]
        schema = self.domain[resource]["schema"]
        compare = [key for key in datasource["projection"] if key in schema]
        compare.extend(
            [
                self.domain[resource]["id_field"],
                self.app.config["LAST_UPDATED"],
                self.app.config["DATE_CREATED"],
                self.app.config["ETAG"],
            ]
        )

        self.assertEqual(
            datasource["projection"], dict((field, 1) for (field) in compare)
        )
        self.assertEqual(datasource["source"], resource)
        self.assertEqual(datasource["filter"], None)

        self.assertEqual(datasource["aggregation"], None)

    def test_validate_roles(self):
        for resource in self.domain:
            self.assertValidateRoles(resource, "allowed_roles")
            self.assertValidateRoles(resource, "allowed_read_roles")
            self.assertValidateRoles(resource, "allowed_write_roles")
            self.assertValidateRoles(resource, "allowed_item_roles")
            self.assertValidateRoles(resource, "allowed_item_read_roles")
            self.assertValidateRoles(resource, "allowed_item_write_roles")

    def assertValidateRoles(self, resource, directive):
        prev = self.domain[resource][directive]
        self.domain[resource][directive] = "admin"
        self.assertValidateConfigFailure(directive)
        self.domain[resource][directive] = []
        self.assertValidateConfigSuccess()
        self.domain[resource][directive] = ["admin", "dev"]
        self.assertValidateConfigSuccess()
        self.domain[resource][directive] = None
        self.assertValidateConfigFailure(directive)
        self.domain[resource][directive] = prev

    def assertValidateConfigSuccess(self):
        try:
            self.app.validate_domain_struct()
            self.app.validate_config()
        except ConfigException as e:
            self.fail("ConfigException not expected: %s" % e)

    def assertValidateConfigFailure(self, expected):
        try:
            self.app.validate_domain_struct()
            self.app.validate_config()
        except ConfigException as e:
            if isinstance(expected, str):
                expected = [expected]
            for exp in expected:
                self.assertTrue(exp.lower() in str(e).lower())
        else:
            self.fail("ConfigException expected but not raised.")

    def assertValidateSchemaFailure(self, resource, schema, expected):
        try:
            self.app.validate_schema(resource, schema)
        except SchemaException as e:
            self.assertTrue(expected.lower() in str(e).lower())
        else:
            self.fail("SchemaException expected but not raised.")

    def test_url_helpers(self):
        self.assertNotEqual(self.app.config.get("URLS"), None)
        self.assertEqual(type(self.app.config["URLS"]), dict)

        self.assertNotEqual(self.app.config.get("SOURCES"), None)
        self.assertEqual(type(self.app.config["SOURCES"]), dict)

        del self.domain["internal_transactions"]
        for resource, settings in self.domain.items():
            self.assertEqual(
                settings["datasource"], self.app.config["SOURCES"][resource]
            )

    def test_pretty_resource_urls(self):
        """ test that regexes are stripped out of urls and #466 is fixed. """
        resource_url = self.app.config["URLS"]["peopleinvoices"]
        pretty_url = "users/<person>/invoices"
        self.assertEqual(resource_url, pretty_url)
        resource_url = self.app.config["URLS"]["peoplesearches"]
        pretty_url = "users/<person>/saved_searches"
        self.assertEqual(resource_url, pretty_url)

    def test_url_rules(self):
        map_adapter = self.app.url_map.bind("")

        del self.domain["peopleinvoices"]
        del self.domain["peoplerequiredinvoices"]
        del self.domain["peoplesearches"]
        del self.domain["internal_transactions"]
        del self.domain["child_products"]
        for _, settings in self.domain.items():
            for method in settings["resource_methods"]:
                self.assertTrue(map_adapter.test("/%s/" % settings["url"], method))

            # TODO test item endpoints as well. gonna be tricky since
            # we have to reverse regexes here. will be fun.

    def test_register_resource(self):
        resource = "resource"
        settings = {
            "schema": {
                "title": {"type": "string", "default": "Mr."},
                "price": {"type": "integer", "default": 100},
            }
        }
        self.app.register_resource(resource, settings)
        self._test_defaults_for_resource(resource)
        self._test_datasource_for_resource(resource)
        self.test_validate_roles()

    def test_auth_field_as_idfield(self):
        resource = "resource"
        settings = {"auth_field": self.app.config["ID_FIELD"]}
        self.assertRaises(
            ConfigException, self.app.register_resource, resource, settings
        )

    def test_auth_field_as_custom_idfield(self):
        resource = "resource"
        settings = {
            "schema": {"id": {"type": "string"}},
            "id_field": "id",
            "auth_field": "id",
        }
        self.assertRaises(
            ConfigException, self.app.register_resource, resource, settings
        )

    def test_oplog_config(self):

        # if OPLOG_ENDPOINT is eanbled the endoint is included with the domain
        self.app.config["OPLOG_ENDPOINT"] = "oplog"
        self.app._init_oplog()
        self.assertOplog("oplog", "oplog")
        del self.domain["oplog"]

        # OPLOG can be also with a custom name (which will be used
        # as the collection/table name on the db)
        oplog = "custom"
        self.app.config["OPLOG_NAME"] = oplog
        self.app._init_oplog()
        self.assertOplog(oplog, "oplog")
        del self.domain[oplog]

        # oplog can be defined as a regular API endpoint, with a couple caveats
        self.domain["oplog"] = {
            "resource_methods": ["POST", "DELETE"],  # not allowed
            "resource_items": ["PATCH", "PUT"],  # not allowed
            "url": "custom_url",
            "datasource": {"source": "customsource"},
        }
        self.app.config["OPLOG_NAME"] = "oplog"
        settings = self.domain["oplog"]
        self.app._init_oplog()

        # endpoint is always read-only
        self.assertEqual(settings["resource_methods"], ["GET"])
        self.assertEqual(settings["item_methods"], ["GET"])
        # other settings are customizable
        self.assertEqual(settings["url"], "custom_url")
        self.assertEqual(settings["datasource"]["source"], "customsource")

    def assertOplog(self, key, endpoint):
        self.assertTrue(key in self.domain)

        settings = self.domain[key]
        self.assertEqual(settings["resource_methods"], ["GET"])
        self.assertEqual(settings["item_methods"], ["GET"])
        self.assertEqual(settings["url"], endpoint)
        self.assertEqual(settings["datasource"]["source"], key)

    def test_create_indexes(self):
        # prepare a specific schema with mongo indexes declared
        # along with the schema.
        settings = {
            "schema": {
                "name": {"type": "string"},
                "other_field": {"type": "string"},
                "lat_long": {"type": "list"},
            },
            "versioning": True,
            "mongo_indexes": {
                "name": [("name", 1)],
                "composed": [("name", 1), ("other_field", 1)],
                "arguments": ([("lat_long", "2d")], {"sparse": True}),
            },
        }
        self.app.register_resource("mongodb_features", settings)

        # check that the indexes are there as a part of the resource
        # settings
        self.assertEqual(
            self.app.config["DOMAIN"]["mongodb_features"]["mongo_indexes"],
            settings["mongo_indexes"],
        )

        # check that the indexes were created
        from pymongo import MongoClient

        db_name = self.app.config["MONGO_DBNAME"]

        db = MongoClient()[db_name]
        for coll in [db["mongodb_features"], db["mongodb_features_versions"]]:
            indexes = coll.index_information()

            # at least there is an index for the _id field plus the indexes
            # created by the resource of this test
            self.assertTrue(len(indexes) > len(settings["mongo_indexes"]))

            # check each one, fields involved and arguments given
            for key, value in settings["mongo_indexes"].items():
                if isinstance(value, tuple):
                    fields, args = value
                else:
                    fields = value
                    args = None

                self.assertTrue(key in indexes)
                self.assertEqual(indexes[key]["key"], fields)

                for arg in args or ():
                    self.assertTrue(arg in indexes[key])
                    self.assertEqual(args[arg], indexes[key][arg])

    def test_custom_error_handlers(self):
        """ Test that the standard, custom error handler is registered for
        supported error codes.
        """
        codes = self.app.config["STANDARD_ERRORS"]

        # http://flask.pocoo.org/docs/0.10/api/#flask.Flask.error_handler_spec
        handlers = self.app.error_handler_spec[None]

        challenge = lambda code: self.assertTrue(code in handlers)  # noqa
        map(challenge, codes)

    def test_mongodb_settings(self):
        # Create custom app with mongodb settings.
        settings = {"DOMAIN": {"contacts": {}}, "MONGO_OPTIONS": {"connect": False}}
        app = Eve(settings=settings)
        # Check if settings are set.
        self.assertEqual(
            app.config["MONGO_OPTIONS"]["connect"], app.config["MONGO_CONNECT"]
        )
        # Prepare a specific schema with mongo specific settings.
        settings = {
            "schema": {"name": {"type": "string"}},
            "MONGO_OPTIONS": {"connect": False},
        }
        self.app.register_resource("mongodb_settings", settings)
        # check that settings are set.
        resource_settings = self.app.config["DOMAIN"]["mongodb_settings"]
        self.assertEqual(resource_settings["MONGO_OPTIONS"], settings["MONGO_OPTIONS"])
        # check that settings are set.
        self.assertEqual(
            resource_settings["MONGO_OPTIONS"]["connect"],
            settings["MONGO_OPTIONS"]["connect"],
        )
Example #18
0
class TestConfig(TestBase):
    def test_default_import_name(self):
        self.assertEqual(self.app.import_name, eve.__package__)

    def test_custom_import_name(self):
        self.app = Eve('unittest', settings=self.settings_file)
        self.assertEqual(self.app.import_name, 'unittest')

    def test_custom_kwargs(self):
        self.app = Eve('unittest', static_folder='/',
                       settings=self.settings_file)
        self.assertEqual(self.app.static_folder, '/')

    def test_regexconverter(self):
        regex_converter = self.app.url_map.converters.get('regex')
        self.assertEqual(regex_converter, RegexConverter)

    def test_default_validator(self):
        self.assertEqual(self.app.validator, Validator)

    def test_default_datalayer(self):
        self.assertEqual(type(self.app.data), Mongo)

    def test_default_settings(self):
        self.assertEqual(self.app.settings, self.settings_file)

        # TODO add tests for other global default values
        self.assertEqual(self.app.config['RATE_LIMIT_GET'], None)
        self.assertEqual(self.app.config['RATE_LIMIT_POST'], None)
        self.assertEqual(self.app.config['RATE_LIMIT_PATCH'], None)
        self.assertEqual(self.app.config['RATE_LIMIT_DELETE'], None)

        self.assertEqual(self.app.config['MONGO_HOST'], 'localhost')
        self.assertEqual(self.app.config['MONGO_PORT'], 27017)
        self.assertEqual(self.app.config['MONGO_QUERY_BLACKLIST'], ['$where',
                                                                    '$regex'])
        self.assertEqual(self.app.config['MONGO_WRITE_CONCERN'], {'w': 1})
        self.assertEqual(self.app.config['ISSUES'], '_issues')

        self.assertEqual(self.app.config['OPLOG'], False)
        self.assertEqual(self.app.config['OPLOG_NAME'], 'oplog')
        self.assertEqual(self.app.config['OPLOG_ENDPOINT'], None)
        self.assertEqual(self.app.config['OPLOG_AUDIT'], True)
        self.assertEqual(self.app.config['OPLOG_METHODS'], ['DELETE',
                                                            'POST',
                                                            'PATCH',
                                                            'PUT'])

        self.assertEqual(self.app.config['QUERY_WHERE'], 'where')
        self.assertEqual(self.app.config['QUERY_PROJECTION'], 'projection')
        self.assertEqual(self.app.config['QUERY_SORT'], 'sort')
        self.assertEqual(self.app.config['QUERY_PAGE'], 'page')
        self.assertEqual(self.app.config['QUERY_MAX_RESULTS'], 'max_results')
        self.assertEqual(self.app.config['QUERY_EMBEDDED'], 'embedded')

        self.assertEqual(self.app.config['JSON_SORT_KEYS'], False)

    def test_settings_as_dict(self):
        my_settings = {'API_VERSION': 'override!', 'DOMAIN': {'contacts': {}}}
        self.app = Eve(settings=my_settings)
        self.assertEqual(self.app.config['API_VERSION'], 'override!')
        # did not reset other defaults
        self.assertEqual(self.app.config['MONGO_WRITE_CONCERN'], {'w': 1})

    def test_unexisting_env_config(self):
        env = os.environ
        try:
            os.environ = {'EVE_SETTINGS': 'an_unexisting_pyfile.py'}
            self.assertRaises(IOError, Eve)
        finally:
            os.environ = env

    def test_custom_validator(self):
        class MyTestValidator(Validator):
            pass
        self.app = Eve(validator=MyTestValidator,
                       settings=self.settings_file)
        self.assertEqual(self.app.validator, MyTestValidator)

    def test_custom_datalayer(self):
        class MyTestDataLayer(DataLayer):
            def init_app(self, app):
                pass
        self.app = Eve(data=MyTestDataLayer, settings=self.settings_file)
        self.assertEqual(type(self.app.data), MyTestDataLayer)

    def test_validate_domain_struct(self):
        del self.app.config['DOMAIN']
        self.assertValidateConfigFailure('missing')

        self.app.config['DOMAIN'] = []
        self.assertValidateConfigFailure('must be a dict')

        self.app.config['DOMAIN'] = {}
        self.assertValidateConfigSuccess()

    def test_validate_resource_methods(self):
        self.app.config['RESOURCE_METHODS'] = ['PUT', 'GET', 'DELETE', 'POST']
        self.assertValidateConfigFailure('PUT')

    def test_validate_item_methods(self):
        self.app.config['ITEM_METHODS'] = ['PUT', 'GET', 'POST', 'DELETE']
        self.assertValidateConfigFailure(['POST', 'PUT'])

    def test_validate_schema_methods(self):
        test = {
            'resource_methods': ['PUT', 'GET', 'DELETE', 'POST'],
        }
        self.app.config['DOMAIN']['test_resource'] = test
        self.assertValidateConfigFailure('PUT')

    def test_validate_schema_item_methods(self):
        test = {
            'resource_methods': ['GET'],
            'item_methods': ['POST'],
        }
        self.app.config['DOMAIN']['test_resource'] = test
        self.assertValidateConfigFailure('PUT')

    def test_validate_datecreated_in_schema(self):
        self.assertUnallowedField(eve.DATE_CREATED)

    def test_validate_lastupdated_in_schema(self):
        self.assertUnallowedField(eve.LAST_UPDATED)

    def test_validate_idfield_in_schema(self):
        self.assertUnallowedField(eve.ID_FIELD, 'objectid')

    def assertUnallowedField(self, field, field_type='datetime'):
        self.domain.clear()
        schema = {field: {'type': field_type}}
        self.domain['resource'] = {'schema': schema}
        self.app.set_defaults()
        self.assertValidateSchemaFailure('resource', schema, field)

    def test_validate_schema(self):
        # lack of 'collection' key for 'data_collection' rule
        schema = self.domain['invoices']['schema']
        del(schema['person']['data_relation']['resource'])
        self.assertValidateSchemaFailure('invoices', schema, 'resource')

    def test_set_schema_defaults(self):
        # default data_relation field value
        schema = self.domain['invoices']['schema']
        data_relation = schema['person']['data_relation']
        self.assertTrue('field' in data_relation)
        self.assertEqual(data_relation['field'], self.app.config['ID_FIELD'])

    def test_set_defaults(self):
        self.domain.clear()
        resource = 'plurals'
        self.domain[resource] = {}
        self.app.set_defaults()
        self._test_defaults_for_resource(resource)
        settings = self.domain[resource]
        self.assertEqual(len(settings['schema']), 0)

    def _test_defaults_for_resource(self, resource):
        settings = self.domain[resource]
        self.assertEqual(settings['url'], resource)
        self.assertEqual(settings['internal_resource'],
                         self.app.config['INTERNAL_RESOURCE'])
        self.assertEqual(settings['resource_methods'],
                         self.app.config['RESOURCE_METHODS'])
        self.assertEqual(settings['public_methods'],
                         self.app.config['PUBLIC_METHODS'])
        self.assertEqual(settings['allowed_roles'],
                         self.app.config['ALLOWED_ROLES'])
        self.assertEqual(settings['allowed_read_roles'],
                         self.app.config['ALLOWED_READ_ROLES'])
        self.assertEqual(settings['allowed_write_roles'],
                         self.app.config['ALLOWED_WRITE_ROLES'])
        self.assertEqual(settings['cache_control'],
                         self.app.config['CACHE_CONTROL'])
        self.assertEqual(settings['cache_expires'],
                         self.app.config['CACHE_EXPIRES'])
        self.assertEqual(settings['item_methods'],
                         self.app.config['ITEM_METHODS'])
        self.assertEqual(settings['public_item_methods'],
                         self.app.config['PUBLIC_ITEM_METHODS'])
        self.assertEqual(settings['allowed_item_roles'],
                         self.app.config['ALLOWED_ITEM_ROLES'])
        self.assertEqual(settings['allowed_item_read_roles'],
                         self.app.config['ALLOWED_ITEM_READ_ROLES'])
        self.assertEqual(settings['allowed_item_write_roles'],
                         self.app.config['ALLOWED_ITEM_WRITE_ROLES'])
        self.assertEqual(settings['item_lookup'],
                         self.app.config['ITEM_LOOKUP'])
        self.assertEqual(settings['item_lookup_field'],
                         self.app.config['ITEM_LOOKUP_FIELD'])
        self.assertEqual(settings['item_url'],
                         self.app.config['ITEM_URL'])
        self.assertEqual(settings['item_title'],
                         resource.rstrip('s').capitalize())
        self.assertEqual(settings['allowed_filters'],
                         self.app.config['ALLOWED_FILTERS'])
        self.assertEqual(settings['projection'], self.app.config['PROJECTION'])
        self.assertEqual(settings['versioning'], self.app.config['VERSIONING'])
        self.assertEqual(settings['sorting'], self.app.config['SORTING'])
        self.assertEqual(settings['embedding'], self.app.config['EMBEDDING'])
        self.assertEqual(settings['pagination'], self.app.config['PAGINATION'])
        self.assertEqual(settings['auth_field'],
                         self.app.config['AUTH_FIELD'])
        self.assertEqual(settings['allow_unknown'],
                         self.app.config['ALLOW_UNKNOWN'])
        self.assertEqual(settings['extra_response_fields'],
                         self.app.config['EXTRA_RESPONSE_FIELDS'])
        self.assertEqual(settings['mongo_write_concern'],
                         self.app.config['MONGO_WRITE_CONCERN'])
        self.assertEqual(settings['resource_title'], settings['url'])

        self.assertNotEqual(settings['schema'], None)
        self.assertEqual(type(settings['schema']), dict)

    def test_datasource(self):
        self._test_datasource_for_resource('invoices')

    def _test_datasource_for_resource(self, resource):
        datasource = self.domain[resource]['datasource']
        schema = self.domain[resource]['schema']
        compare = [key for key in datasource['projection'] if key in schema]
        compare.extend([self.app.config['ID_FIELD'],
                        self.app.config['LAST_UPDATED'],
                        self.app.config['DATE_CREATED'],
                        self.app.config['ETAG']])

        self.assertEqual(datasource['projection'],
                         dict((field, 1) for (field) in compare))
        self.assertEqual(datasource['source'], resource)
        self.assertEqual(datasource['filter'], None)

    def test_validate_roles(self):
        for resource in self.domain:
            self.assertValidateRoles(resource, 'allowed_roles')
            self.assertValidateRoles(resource, 'allowed_read_roles')
            self.assertValidateRoles(resource, 'allowed_write_roles')
            self.assertValidateRoles(resource, 'allowed_item_roles')
            self.assertValidateRoles(resource, 'allowed_item_read_roles')
            self.assertValidateRoles(resource, 'allowed_item_write_roles')

    def assertValidateRoles(self, resource, directive):
        prev = self.domain[resource][directive]
        self.domain[resource][directive] = 'admin'
        self.assertValidateConfigFailure(directive)
        self.domain[resource][directive] = []
        self.assertValidateConfigSuccess()
        self.domain[resource][directive] = ['admin', 'dev']
        self.assertValidateConfigSuccess()
        self.domain[resource][directive] = None
        self.assertValidateConfigFailure(directive)
        self.domain[resource][directive] = prev

    def assertValidateConfigSuccess(self):
        try:
            self.app.validate_domain_struct()
            self.app.validate_config()
        except ConfigException as e:
            self.fail('ConfigException not expected: %s' % e)

    def assertValidateConfigFailure(self, expected):
        try:
            self.app.validate_domain_struct()
            self.app.validate_config()
        except ConfigException as e:
            if isinstance(expected, str):
                expected = [expected]
            for exp in expected:
                self.assertTrue(exp.lower() in str(e).lower())
        else:
            self.fail("ConfigException expected but not raised.")

    def assertValidateSchemaFailure(self, resource, schema, expected):
        try:
            self.app.validate_schema(resource, schema)
        except SchemaException as e:
            self.assertTrue(expected.lower() in str(e).lower())
        else:
            self.fail("SchemaException expected but not raised.")

    def test_schema_defaults(self):
        self.domain.clear()
        self.domain['resource'] = {
            'schema': {
                'title': {
                    'type': 'string',
                    'default': 'Mr.',
                },
                'price': {
                    'type': 'integer',
                    'default': 100
                },
            }
        }
        self.app.set_defaults()
        settings = self.domain['resource']
        self.assertEqual({'title': 'Mr.', 'price': 100}, settings['defaults'])

    def test_url_helpers(self):
        self.assertNotEqual(self.app.config.get('URLS'), None)
        self.assertEqual(type(self.app.config['URLS']), dict)

        self.assertNotEqual(self.app.config.get('SOURCES'), None)
        self.assertEqual(type(self.app.config['SOURCES']), dict)

        del(self.domain['internal_transactions'])
        for resource, settings in self.domain.items():
            self.assertEqual(settings['datasource'],
                             self.app.config['SOURCES'][resource])

    def test_pretty_resource_urls(self):
        """ test that regexes are stripped out of urls and #466 is fixed. """
        resource_url = self.app.config['URLS']['peopleinvoices']
        pretty_url = 'users/<person>/invoices'
        self.assertEqual(resource_url, pretty_url)
        resource_url = self.app.config['URLS']['peoplesearches']
        pretty_url = 'users/<person>/saved_searches'
        self.assertEqual(resource_url, pretty_url)

    def test_url_rules(self):
        map_adapter = self.app.url_map.bind('')

        del(self.domain['peopleinvoices'])
        del(self.domain['peoplesearches'])
        del(self.domain['internal_transactions'])
        for _, settings in self.domain.items():
            for method in settings['resource_methods']:
                self.assertTrue(map_adapter.test('/%s/' % settings['url'],
                                                 method))

            # TODO test item endpoints as well. gonna be tricky since
            # we have to reverse regexes here. will be fun.

    def test_register_resource(self):
        resource = 'resource'
        settings = {
            'schema': {
                'title': {
                    'type': 'string',
                    'default': 'Mr.',
                },
                'price': {
                    'type': 'integer',
                    'default': 100
                },
            }
        }
        self.app.register_resource(resource, settings)
        self._test_defaults_for_resource(resource)
        self._test_datasource_for_resource(resource)
        self.test_validate_roles()

    def test_auth_field_as_idfield(self):
        resource = 'resource'
        settings = {
            'auth_field': self.app.config['ID_FIELD'],
        }
        self.assertRaises(ConfigException, self.app.register_resource,
                          resource, settings)

    def test_oplog_config(self):

        # OPLOG_ENDPOINT is disabled by default so we don't have the endpoint
        # in our domain
        self.assertFalse('oplog' in self.domain)

        # if OPLOG_ENDPOINT is eanbled the endoint is included with the domain
        self.app.config['OPLOG_ENDPOINT'] = 'oplog'
        self.app._init_oplog()
        self.assertOplog('oplog', 'oplog')
        del(self.domain['oplog'])

        # OPLOG can be also with a custom name (which will be used
        # as the collection/table name on the db)
        oplog = 'custom'
        self.app.config['OPLOG_NAME'] = oplog
        self.app._init_oplog()
        self.assertOplog(oplog, 'oplog')
        del(self.domain[oplog])

        # oplog can be defined as a regular API endpoint, with a couple caveats
        self.domain['oplog'] = {
            'resource_methods': ['POST', 'DELETE'],     # not allowed
            'resource_items': ['PATCH', 'PUT'],         # not allowed
            'url': 'custom_url',
            'datasource': {'source': 'customsource'}
        }
        self.app.config['OPLOG_NAME'] = 'oplog'
        settings = self.domain['oplog']
        self.app._init_oplog()

        # endpoint is always read-only
        self.assertEqual(settings['resource_methods'], ['GET'])
        self.assertEqual(settings['item_methods'], ['GET'])
        # other settings are customizable
        self.assertEqual(settings['url'], 'custom_url')
        self.assertEqual(settings['datasource']['source'], 'customsource')

    def assertOplog(self, key, endpoint):
        self.assertTrue(key in self.domain)

        settings = self.domain[key]
        self.assertEqual(settings['resource_methods'], ['GET'])
        self.assertEqual(settings['item_methods'], ['GET'])
        self.assertEqual(settings['url'], endpoint)
        self.assertEqual(settings['datasource']['source'], key)
Example #19
0
File: config.py Project: Tefnet/eve
 def test_custom_kwargs(self):
     self.app = Eve('custom_import_name',
                    static_folder='/',
                    settings='eve/tests/test_settings.py')
     self.assertEqual(self.app.static_folder, '/')
Example #20
0
File: config.py Project: Tefnet/eve
 def test_custom_import_name(self):
     self.app = Eve('custom_import_name',
                    settings='eve/tests/test_settings.py')
     self.assertEqual(self.app.import_name, 'custom_import_name')
Example #21
0
 def test_existing_env_config(self):
     env = os.environ
     os.environ = {"EVE_SETTINGS": "test_settings_env.py"}
     self.app = Eve()
     self.assertTrue("env_domain" in self.app.config["DOMAIN"])
     os.environ = env
Example #22
0
class TestConfig(TestBase):
    def test_regexconverter(self):
        regex_converter = self.app.url_map.converters.get('regex')
        self.assertEqual(regex_converter, RegexConverter)

    def test_default_validator(self):
        self.assertEqual(self.app.validator, Validator)

    def test_default_datalayer(self):
        self.assertEqual(type(self.app.data), Mongo)

    def test_default_settings(self):
        self.assertEqual(self.app.settings, self.settings_file)

    def test_unexisting_pyfile_config(self):
        self.assertRaises(IOError, Eve, settings='an_unexisting_pyfile.py')

    def test_unexisting_env_config(self):
        env = os.environ
        try:
            os.environ = {'EVE_SETTINGS': 'an_unexisting_pyfile.py'}
            self.assertRaises(IOError, Eve)
        finally:
            os.environ = env

    def test_custom_validator(self):
        class MyTestValidator(Validator):
            pass

        self.app = Eve(validator=MyTestValidator, settings=self.settings_file)
        self.assertEqual(self.app.validator, MyTestValidator)

    def test_custom_datalayer(self):
        class MyTestDataLayer(DataLayer):
            def init_app(self, app):
                pass

            pass

        self.app = Eve(data=MyTestDataLayer, settings=self.settings_file)
        self.assertEqual(type(self.app.data), MyTestDataLayer)

    def test_validate_domain_struct(self):
        del self.app.config['DOMAIN']
        self.assertValidateConfig('missing')

        self.app.config['DOMAIN'] = []
        self.assertValidateConfig('must be a dict')

        self.app.config['DOMAIN'] = {}
        self.assertValidateConfig('must contain at least one')

    def test_validate_resource_methods(self):
        self.app.config['RESOURCE_METHODS'] = ['PUT', 'GET', 'DELETE', 'POST']
        self.assertValidateConfig('PUT')

    def test_validate_item_methods(self):
        self.app.config['ITEM_METHODS'] = ['PUT', 'GET', 'POST', 'DELETE']
        self.assertValidateConfig('PUT, POST')

    def test_validate_schema_methods(self):
        test = {
            'methods': ['PUT', 'GET', 'DELETE', 'POST'],
        }
        self.app.config['DOMAIN']['test_resource'] = test
        self.assertValidateConfig('PUT')

    def test_validate_schema_item_methods(self):
        test = {
            'methods': ['GET'],
            'item_methods': ['PUT'],
        }
        self.app.config['DOMAIN']['test_resource'] = test
        self.assertValidateConfig('PUT')

    def test_validate_datecreated_in_schema(self):
        self.assertUnallowedField(eve.DATE_CREATED)

    def test_validate_lastupdated_in_schema(self):
        self.assertUnallowedField(eve.LAST_UPDATED)

    def test_validate_idfield_in_schema(self):
        self.assertUnallowedField(eve.ID_FIELD)

    def assertUnallowedField(self, field):
        self.domain.clear()
        self.domain['resource'] = {'schema': {field: {'type': 'datetime'}}}
        self.app.set_defaults()
        self.assertValidateConfig('automatically')

    def assertValidateConfig(self, expected):
        try:
            self.app.validate_domain_struct()
            self.app.validate_config()
        except ConfigException, e:
            self.assertTrue(expected.lower() in str(e).lower())
        else:
Example #23
0
class TestConfig(TestBase):
    def test_allow_unknown_with_soft_delete(self):
        my_settings = {
            "ALLOW_UNKNOWN": True,
            "SOFT_DELETE": True,
            "DOMAIN": {"contacts": {}},
        }
        try:
            self.app = Eve(settings=my_settings)
        except TypeError:
            self.fail(
                "ALLOW_UNKNOWN and SOFT_DELETE enabled should not cause " "a crash."
            )

    def test_default_import_name(self):
        self.assertEqual(self.app.import_name, eve.__package__)

    def test_custom_import_name(self):
        self.app = Eve("unittest", settings=self.settings_file)
        self.assertEqual(self.app.import_name, "unittest")

    def test_custom_kwargs(self):
        self.app = Eve("unittest", static_folder="static/", settings=self.settings_file)
        self.assertTrue(self.app.static_folder.endswith("static"))

    def test_regexconverter(self):
        regex_converter = self.app.url_map.converters.get("regex")
        self.assertEqual(regex_converter, RegexConverter)

    def test_default_validator(self):
        self.assertEqual(self.app.validator, Validator)

    def test_default_datalayer(self):
        self.assertEqual(type(self.app.data), Mongo)

    def test_default_settings(self):
        self.assertEqual(self.app.settings, self.settings_file)

        # TODO add tests for other global default values
        self.assertEqual(self.app.config["RATE_LIMIT_GET"], None)
        self.assertEqual(self.app.config["RATE_LIMIT_POST"], None)
        self.assertEqual(self.app.config["RATE_LIMIT_PATCH"], None)
        self.assertEqual(self.app.config["RATE_LIMIT_DELETE"], None)

        self.assertEqual(self.app.config["MONGO_HOST"], MONGO_HOST)
        self.assertEqual(self.app.config["MONGO_PORT"], MONGO_PORT)
        self.assertEqual(self.app.config["MONGO_QUERY_BLACKLIST"], ["$where", "$regex"])
        self.assertEqual(self.app.config["MONGO_QUERY_WHITELIST"], [])
        self.assertEqual(self.app.config["MONGO_WRITE_CONCERN"], {"w": 1})
        self.assertEqual(self.app.config["ISSUES"], "_issues")

        self.assertEqual(self.app.config["OPLOG"], False)
        self.assertEqual(self.app.config["OPLOG_NAME"], "oplog")
        self.assertEqual(self.app.config["OPLOG_ENDPOINT"], None)
        self.assertEqual(self.app.config["OPLOG_AUDIT"], True)
        self.assertEqual(
            self.app.config["OPLOG_METHODS"], ["DELETE", "POST", "PATCH", "PUT"]
        )
        self.assertEqual(
            self.app.config["OPLOG_CHANGE_METHODS"], ["DELETE", "PATCH", "PUT"]
        )
        self.assertEqual(self.app.config["QUERY_WHERE"], "where")
        self.assertEqual(self.app.config["QUERY_PROJECTION"], "projection")
        self.assertEqual(self.app.config["QUERY_SORT"], "sort")
        self.assertEqual(self.app.config["QUERY_PAGE"], "page")
        self.assertEqual(self.app.config["QUERY_MAX_RESULTS"], "max_results")
        self.assertEqual(self.app.config["QUERY_EMBEDDED"], "embedded")
        self.assertEqual(self.app.config["QUERY_AGGREGATION"], "aggregate")

        self.assertEqual(self.app.config["JSON_SORT_KEYS"], False)
        self.assertEqual(self.app.config["SOFT_DELETE"], False)
        self.assertEqual(self.app.config["DELETED"], "_deleted")
        self.assertEqual(self.app.config["SHOW_DELETED_PARAM"], "show_deleted")
        self.assertEqual(
            self.app.config["STANDARD_ERRORS"],
            [400, 401, 403, 404, 405, 406, 409, 410, 412, 422, 428, 429],
        )
        self.assertEqual(self.app.config["UPSERT_ON_PUT"], True)
        self.assertEqual(
            self.app.config["JSON_REQUEST_CONTENT_TYPES"], ["application/json"]
        )
        self.assertEqual(self.app.config["NORMALIZE_DOTTED_FIELDS"], True)

    def test_settings_as_dict(self):
        my_settings = {"API_VERSION": "override!", "DOMAIN": {"contacts": {}}}
        self.app = Eve(settings=my_settings)
        self.assertEqual(self.app.config["API_VERSION"], "override!")
        # did not reset other defaults
        self.assertEqual(self.app.config["MONGO_WRITE_CONCERN"], {"w": 1})

    def test_existing_env_config(self):
        env = os.environ
        os.environ = {"EVE_SETTINGS": "test_settings_env.py"}
        self.app = Eve()
        self.assertTrue("env_domain" in self.app.config["DOMAIN"])
        os.environ = env

    def test_unexisting_env_config(self):
        env = os.environ
        try:
            os.environ = {"EVE_SETTINGS": "an_unexisting_pyfile.py"}
            self.assertRaises(IOError, Eve)
        finally:
            os.environ = env

    def test_custom_validator(self):
        class MyTestValidator(Validator):
            pass

        self.app = Eve(validator=MyTestValidator, settings=self.settings_file)
        self.assertEqual(self.app.validator, MyTestValidator)

    def test_custom_datalayer(self):
        class MyTestDataLayer(DataLayer):
            def init_app(self, app):
                pass

        self.app = Eve(data=MyTestDataLayer, settings=self.settings_file)
        self.assertEqual(type(self.app.data), MyTestDataLayer)

    def test_validate_domain_struct(self):
        del self.app.config["DOMAIN"]
        self.assertValidateConfigFailure("missing")

        self.app.config["DOMAIN"] = []
        self.assertValidateConfigFailure("must be a dict")

        self.app.config["DOMAIN"] = {}
        self.assertValidateConfigSuccess()

    def test_validate_resource_methods(self):
        self.app.config["RESOURCE_METHODS"] = ["PUT", "GET", "DELETE", "POST"]
        self.assertValidateConfigFailure("PUT")

    def test_validate_item_methods(self):
        self.app.config["ITEM_METHODS"] = ["PUT", "GET", "POST", "DELETE"]
        self.assertValidateConfigFailure(["POST", "PUT"])

    def test_validate_schema_methods(self):
        test = {"resource_methods": ["PUT", "GET", "DELETE", "POST"]}
        self.app.config["DOMAIN"]["test_resource"] = test
        self.assertValidateConfigFailure("PUT")

    def test_validate_schema_item_methods(self):
        test = {"resource_methods": ["GET"], "item_methods": ["POST"]}
        self.app.config["DOMAIN"]["test_resource"] = test
        self.assertValidateConfigFailure("PUT")

    def test_validate_datecreated_in_schema(self):
        self.assertUnallowedField(eve.DATE_CREATED)

    def test_validate_lastupdated_in_schema(self):
        self.assertUnallowedField(eve.LAST_UPDATED)

    def assertUnallowedField(self, field, field_type="datetime"):
        self.domain.clear()
        schema = {field: {"type": field_type}}
        self.domain["resource"] = {"schema": schema}
        self.app.set_defaults()
        self.assertValidateSchemaFailure("resource", schema, field)

    def test_validate_schema(self):
        # lack of 'collection' key for 'data_collection' rule
        schema = self.domain["invoices"]["schema"]
        del schema["person"]["data_relation"]["resource"]
        self.assertValidateSchemaFailure("invoices", schema, "resource")

    def test_validate_invalid_field_names(self):
        schema = self.domain["invoices"]["schema"]
        schema["te$t"] = {"type": "string"}
        self.assertValidateSchemaFailure("invoices", schema, "te$t")
        del schema["te$t"]

        schema["te.t"] = {"type": "string"}
        self.assertValidateSchemaFailure("invoices", schema, "te.t")
        del schema["te.t"]

        schema["test_a_dict_schema"] = {
            "type": "dict",
            "schema": {"te$t": {"type": "string"}},
        }
        self.assertValidateSchemaFailure("invoices", schema, "te$t")

        schema["test_a_dict_schema"]["schema"] = {"te.t": {"type": "string"}}
        self.assertValidateSchemaFailure("invoices", schema, "te.t")

    def test_set_schema_defaults(self):
        # default data_relation field value
        schema = self.domain["invoices"]["schema"]
        data_relation = schema["person"]["data_relation"]
        self.assertTrue("field" in data_relation)
        self.assertEqual(data_relation["field"], self.domain["contacts"]["id_field"])
        id_field = self.domain["invoices"]["id_field"]
        self.assertTrue(id_field in schema)
        self.assertEqual(schema[id_field], {"type": "objectid"})

    def test_set_defaults(self):
        self.domain.clear()
        resource = "plurals"
        self.domain[resource] = {}
        self.app.set_defaults()
        self._test_defaults_for_resource(resource)
        settings = self.domain[resource]
        self.assertEqual(len(settings["schema"]), 1)

    def _test_defaults_for_resource(self, resource):
        settings = self.domain[resource]
        self.assertEqual(settings["url"], resource)
        self.assertEqual(
            settings["internal_resource"], self.app.config["INTERNAL_RESOURCE"]
        )
        self.assertEqual(
            settings["resource_methods"], self.app.config["RESOURCE_METHODS"]
        )
        self.assertEqual(settings["public_methods"], self.app.config["PUBLIC_METHODS"])
        self.assertEqual(settings["allowed_roles"], self.app.config["ALLOWED_ROLES"])
        self.assertEqual(
            settings["allowed_read_roles"], self.app.config["ALLOWED_READ_ROLES"]
        )
        self.assertEqual(
            settings["allowed_write_roles"], self.app.config["ALLOWED_WRITE_ROLES"]
        )
        self.assertEqual(settings["cache_control"], self.app.config["CACHE_CONTROL"])
        self.assertEqual(settings["cache_expires"], self.app.config["CACHE_EXPIRES"])
        self.assertEqual(settings["item_methods"], self.app.config["ITEM_METHODS"])
        self.assertEqual(
            settings["public_item_methods"], self.app.config["PUBLIC_ITEM_METHODS"]
        )
        self.assertEqual(
            settings["allowed_item_roles"], self.app.config["ALLOWED_ITEM_ROLES"]
        )
        self.assertEqual(
            settings["allowed_item_read_roles"],
            self.app.config["ALLOWED_ITEM_READ_ROLES"],
        )
        self.assertEqual(
            settings["allowed_item_write_roles"],
            self.app.config["ALLOWED_ITEM_WRITE_ROLES"],
        )
        self.assertEqual(settings["item_lookup"], self.app.config["ITEM_LOOKUP"])
        self.assertEqual(
            settings["item_lookup_field"], self.app.config["ITEM_LOOKUP_FIELD"]
        )
        self.assertEqual(settings["item_url"], self.app.config["ITEM_URL"])
        self.assertEqual(settings["item_title"], resource.rstrip("s").capitalize())
        self.assertEqual(
            settings["allowed_filters"], self.app.config["ALLOWED_FILTERS"]
        )
        self.assertEqual(settings["projection"], self.app.config["PROJECTION"])
        self.assertEqual(settings["versioning"], self.app.config["VERSIONING"])
        self.assertEqual(settings["soft_delete"], self.app.config["SOFT_DELETE"])
        self.assertEqual(settings["sorting"], self.app.config["SORTING"])
        self.assertEqual(settings["embedding"], self.app.config["EMBEDDING"])
        self.assertEqual(settings["pagination"], self.app.config["PAGINATION"])
        self.assertEqual(settings["auth_field"], self.app.config["AUTH_FIELD"])
        self.assertEqual(settings["allow_unknown"], self.app.config["ALLOW_UNKNOWN"])
        self.assertEqual(
            settings["extra_response_fields"], self.app.config["EXTRA_RESPONSE_FIELDS"]
        )
        self.assertEqual(
            settings["mongo_query_whitelist"], self.app.config["MONGO_QUERY_WHITELIST"]
        )
        self.assertEqual(
            settings["mongo_write_concern"], self.app.config["MONGO_WRITE_CONCERN"]
        )
        self.assertEqual(settings["resource_title"], settings["url"])

        self.assertNotEqual(settings["schema"], None)
        self.assertEqual(type(settings["schema"]), dict)
        self.assertEqual(settings["etag_ignore_fields"], None)

    def test_datasource(self):
        self._test_datasource_for_resource("invoices")

    def _test_datasource_for_resource(self, resource):
        datasource = self.domain[resource]["datasource"]
        schema = self.domain[resource]["schema"]
        compare = [key for key in datasource["projection"] if key in schema]
        compare.extend(
            [
                self.domain[resource]["id_field"],
                self.app.config["LAST_UPDATED"],
                self.app.config["DATE_CREATED"],
                self.app.config["ETAG"],
            ]
        )

        self.assertEqual(
            datasource["projection"], dict((field, 1) for (field) in compare)
        )
        self.assertEqual(datasource["source"], resource)
        self.assertEqual(datasource["filter"], None)

        self.assertEqual(datasource["aggregation"], None)

    def test_validate_roles(self):
        for resource in self.domain:
            self.assertValidateRoles(resource, "allowed_roles")
            self.assertValidateRoles(resource, "allowed_read_roles")
            self.assertValidateRoles(resource, "allowed_write_roles")
            self.assertValidateRoles(resource, "allowed_item_roles")
            self.assertValidateRoles(resource, "allowed_item_read_roles")
            self.assertValidateRoles(resource, "allowed_item_write_roles")

    def assertValidateRoles(self, resource, directive):
        prev = self.domain[resource][directive]
        self.domain[resource][directive] = "admin"
        self.assertValidateConfigFailure(directive)
        self.domain[resource][directive] = []
        self.assertValidateConfigSuccess()
        self.domain[resource][directive] = ["admin", "dev"]
        self.assertValidateConfigSuccess()
        self.domain[resource][directive] = None
        self.assertValidateConfigFailure(directive)
        self.domain[resource][directive] = prev

    def assertValidateConfigSuccess(self):
        try:
            self.app.validate_domain_struct()
            self.app.validate_config()
        except ConfigException as e:
            self.fail("ConfigException not expected: %s" % e)

    def assertValidateConfigFailure(self, expected):
        try:
            self.app.validate_domain_struct()
            self.app.validate_config()
        except ConfigException as e:
            if isinstance(expected, str):
                expected = [expected]
            for exp in expected:
                self.assertTrue(exp.lower() in str(e).lower())
        else:
            self.fail("ConfigException expected but not raised.")

    def assertValidateSchemaFailure(self, resource, schema, expected):
        try:
            self.app.validate_schema(resource, schema)
        except SchemaException as e:
            self.assertTrue(expected.lower() in str(e).lower())
        else:
            self.fail("SchemaException expected but not raised.")

    def test_url_helpers(self):
        self.assertNotEqual(self.app.config.get("URLS"), None)
        self.assertEqual(type(self.app.config["URLS"]), dict)

        self.assertNotEqual(self.app.config.get("SOURCES"), None)
        self.assertEqual(type(self.app.config["SOURCES"]), dict)

        del self.domain["internal_transactions"]
        for resource, settings in self.domain.items():
            self.assertEqual(
                settings["datasource"], self.app.config["SOURCES"][resource]
            )

    def test_pretty_resource_urls(self):
        """ test that regexes are stripped out of urls and #466 is fixed. """
        resource_url = self.app.config["URLS"]["peopleinvoices"]
        pretty_url = "users/<person>/invoices"
        self.assertEqual(resource_url, pretty_url)
        resource_url = self.app.config["URLS"]["peoplesearches"]
        pretty_url = "users/<person>/saved_searches"
        self.assertEqual(resource_url, pretty_url)

    def test_url_rules(self):
        map_adapter = self.app.url_map.bind("")

        del self.domain["peopleinvoices"]
        del self.domain["peoplerequiredinvoices"]
        del self.domain["peoplesearches"]
        del self.domain["internal_transactions"]
        del self.domain["child_products"]
        for _, settings in self.domain.items():
            for method in settings["resource_methods"]:
                self.assertTrue(map_adapter.test("/%s/" % settings["url"], method))

            # TODO test item endpoints as well. gonna be tricky since
            # we have to reverse regexes here. will be fun.

    def test_register_resource(self):
        resource = "resource"
        settings = {
            "schema": {
                "title": {"type": "string", "default": "Mr."},
                "price": {"type": "integer", "default": 100},
            }
        }
        self.app.register_resource(resource, settings)
        self._test_defaults_for_resource(resource)
        self._test_datasource_for_resource(resource)
        self.test_validate_roles()

    def test_auth_field_as_idfield(self):
        resource = "resource"
        settings = {"auth_field": self.app.config["ID_FIELD"]}
        self.assertRaises(
            ConfigException, self.app.register_resource, resource, settings
        )

    def test_auth_field_as_custom_idfield(self):
        resource = "resource"
        settings = {
            "schema": {"id": {"type": "string"}},
            "id_field": "id",
            "auth_field": "id",
        }
        self.assertRaises(
            ConfigException, self.app.register_resource, resource, settings
        )

    def test_oplog_config(self):

        # if OPLOG_ENDPOINT is eanbled the endoint is included with the domain
        self.app.config["OPLOG_ENDPOINT"] = "oplog"
        self.app._init_oplog()
        self.assertOplog("oplog", "oplog")
        del self.domain["oplog"]

        # OPLOG can be also with a custom name (which will be used
        # as the collection/table name on the db)
        oplog = "custom"
        self.app.config["OPLOG_NAME"] = oplog
        self.app._init_oplog()
        self.assertOplog(oplog, "oplog")
        del self.domain[oplog]

        # oplog can be defined as a regular API endpoint, with a couple caveats
        self.domain["oplog"] = {
            "resource_methods": ["POST", "DELETE"],  # not allowed
            "resource_items": ["PATCH", "PUT"],  # not allowed
            "url": "custom_url",
            "datasource": {"source": "customsource"},
        }
        self.app.config["OPLOG_NAME"] = "oplog"
        settings = self.domain["oplog"]
        self.app._init_oplog()

        # endpoint is always read-only
        self.assertEqual(settings["resource_methods"], ["GET"])
        self.assertEqual(settings["item_methods"], ["GET"])
        # other settings are customizable
        self.assertEqual(settings["url"], "custom_url")
        self.assertEqual(settings["datasource"]["source"], "customsource")

    def assertOplog(self, key, endpoint):
        self.assertTrue(key in self.domain)

        settings = self.domain[key]
        self.assertEqual(settings["resource_methods"], ["GET"])
        self.assertEqual(settings["item_methods"], ["GET"])
        self.assertEqual(settings["url"], endpoint)
        self.assertEqual(settings["datasource"]["source"], key)

    def test_create_indexes(self):
        # prepare a specific schema with mongo indexes declared
        # along with the schema.
        settings = {
            "schema": {
                "name": {"type": "string"},
                "other_field": {"type": "string"},
                "lat_long": {"type": "list"},
            },
            "versioning": True,
            "mongo_indexes": {
                "name": [("name", 1)],
                "composed": [("name", 1), ("other_field", 1)],
                "arguments": ([("lat_long", "2d")], {"sparse": True}),
            },
        }
        self.app.register_resource("mongodb_features", settings)

        # check that the indexes are there as a part of the resource
        # settings
        self.assertEqual(
            self.app.config["DOMAIN"]["mongodb_features"]["mongo_indexes"],
            settings["mongo_indexes"],
        )

        # check that the indexes were created
        from pymongo import MongoClient

        db_name = self.app.config["MONGO_DBNAME"]

        db = MongoClient(host=MONGO_HOST, port=MONGO_PORT)[db_name]
        for coll in [db["mongodb_features"], db["mongodb_features_versions"]]:
            indexes = coll.index_information()

            # at least there is an index for the _id field plus the indexes
            # created by the resource of this test
            self.assertTrue(len(indexes) > len(settings["mongo_indexes"]))

            # check each one, fields involved and arguments given
            for key, value in settings["mongo_indexes"].items():
                if isinstance(value, tuple):
                    fields, args = value
                else:
                    fields = value
                    args = None

                self.assertTrue(key in indexes)
                self.assertEqual(indexes[key]["key"], fields)

                for arg in args or ():
                    self.assertTrue(arg in indexes[key])
                    self.assertEqual(args[arg], indexes[key][arg])

    def test_custom_error_handlers(self):
        """Test that the standard, custom error handler is registered for
        supported error codes.
        """
        codes = self.app.config["STANDARD_ERRORS"]

        # http://flask.pocoo.org/docs/0.10/api/#flask.Flask.error_handler_spec
        handlers = self.app.error_handler_spec[None]

        challenge = lambda code: self.assertTrue(code in handlers)  # noqa
        map(challenge, codes)

    def test_mongodb_settings(self):
        # Create custom app with mongodb settings.
        settings = {"DOMAIN": {"contacts": {}}, "MONGO_OPTIONS": {"connect": False}}
        app = Eve(settings=settings)
        # Check if settings are set.
        self.assertEqual(
            app.config["MONGO_OPTIONS"]["connect"], app.config["MONGO_CONNECT"]
        )
        # Prepare a specific schema with mongo specific settings.
        settings = {
            "schema": {"name": {"type": "string"}},
            "MONGO_OPTIONS": {"connect": False},
        }
        self.app.register_resource("mongodb_settings", settings)
        # check that settings are set.
        resource_settings = self.app.config["DOMAIN"]["mongodb_settings"]
        self.assertEqual(resource_settings["MONGO_OPTIONS"], settings["MONGO_OPTIONS"])
        # check that settings are set.
        self.assertEqual(
            resource_settings["MONGO_OPTIONS"]["connect"],
            settings["MONGO_OPTIONS"]["connect"],
        )
 def test_custom_validator(self):
     class MyTestValidator(Validator):
         pass
     self.app = Eve(validator=MyTestValidator,
                    settings=self.settings_file)
     self.assertEqual(self.app.validator, MyTestValidator)
Example #25
0
 def test_custom_kwargs(self):
     self.app = Eve("unittest", static_folder="static/", settings=self.settings_file)
     self.assertTrue(self.app.static_folder.endswith("static"))
Example #26
0
 def test_existing_env_config(self):
     env = os.environ
     os.environ = {'EVE_SETTINGS': 'test_settings_env.py'}
     self.app = Eve()
     self.assertTrue('env_domain' in self.app.config['DOMAIN'])
     os.environ = env
Example #27
0
class TestConfig(TestBase):

    def test_regexconverter(self):
        regex_converter = self.app.url_map.converters.get('regex')
        self.assertEqual(regex_converter, RegexConverter)

    def test_default_validator(self):
        self.assertEqual(self.app.validator, Validator)

    def test_default_datalayer(self):
        self.assertEqual(type(self.app.data), Mongo)

    def test_default_settings(self):
        self.assertEqual(self.app.settings, self.settings_file)

    def test_unexisting_pyfile_config(self):
        self.assertRaises(IOError, Eve, settings='an_unexisting_pyfile.py')

    def test_unexisting_env_config(self):
        env = os.environ
        try:
            os.environ = {'EVE_SETTINGS': 'an_unexisting_pyfile.py'}
            self.assertRaises(IOError, Eve)
        finally:
            os.environ = env

    def test_custom_validator(self):
        class MyTestValidator(Validator):
            pass
        self.app = Eve(validator=MyTestValidator,
                       settings=self.settings_file)
        self.assertEqual(self.app.validator, MyTestValidator)

    def test_custom_datalayer(self):
        class MyTestDataLayer(DataLayer):
            def init_app(self, app):
                pass
            pass
        self.app = Eve(data=MyTestDataLayer, settings=self.settings_file)
        self.assertEqual(type(self.app.data), MyTestDataLayer)

    def test_validate_domain_struct(self):
        del self.app.config['DOMAIN']
        self.assertValidateConfig('missing')

        self.app.config['DOMAIN'] = []
        self.assertValidateConfig('must be a dict')

        self.app.config['DOMAIN'] = {}
        self.assertValidateConfig('must contain at least one')

    def test_validate_resource_methods(self):
        self.app.config['RESOURCE_METHODS'] = ['PUT', 'GET', 'DELETE', 'POST']
        self.assertValidateConfig('PUT')

    def test_validate_item_methods(self):
        self.app.config['ITEM_METHODS'] = ['PUT', 'GET', 'POST', 'DELETE']
        self.assertValidateConfig('PUT, POST')

    def test_validate_schema_methods(self):
        test = {
            'methods': ['PUT', 'GET', 'DELETE', 'POST'],
        }
        self.app.config['DOMAIN']['test_resource'] = test
        self.assertValidateConfig('PUT')

    def test_validate_schema_item_methods(self):
        test = {
            'methods': ['GET'],
            'item_methods': ['PUT'],
        }
        self.app.config['DOMAIN']['test_resource'] = test
        self.assertValidateConfig('PUT')

    def test_validate_datecreated_in_schema(self):
        self.assertUnallowedField(eve.DATE_CREATED)

    def test_validate_lastupdated_in_schema(self):
        self.assertUnallowedField(eve.LAST_UPDATED)

    def test_validate_idfield_in_schema(self):
        self.assertUnallowedField(eve.ID_FIELD)

    def assertUnallowedField(self, field):
        self.domain.clear()
        self.domain['resource'] = {
            'schema': {
                field: {'type': 'datetime'}
            }
        }
        self.app.set_defaults()
        self.assertValidateConfig('automatically')

    def assertValidateConfig(self, expected):
        try:
            self.app.validate_domain_struct()
            self.app.validate_config()
        except ConfigException, e:
            self.assertTrue(expected.lower() in str(e).lower())
        else:
Example #28
0
File: config.py Project: tdihp/eve
class TestConfig(TestBase):
    def test_default_import_name(self):
        self.assertEqual(self.app.import_name, eve.__package__)

    def test_custom_import_name(self):
        self.app = Eve('custom_import_name', settings=self.settings_file)
        self.assertEqual(self.app.import_name, 'custom_import_name')

    def test_custom_kwargs(self):
        self.app = Eve('custom_import_name', static_folder='/',
                       settings=self.settings_file)
        self.assertEqual(self.app.static_folder, '/')

    def test_regexconverter(self):
        regex_converter = self.app.url_map.converters.get('regex')
        self.assertEqual(regex_converter, RegexConverter)

    def test_default_validator(self):
        self.assertEqual(self.app.validator, Validator)

    def test_default_datalayer(self):
        self.assertEqual(type(self.app.data), Mongo)

    def test_default_settings(self):
        self.assertEqual(self.app.settings, self.settings_file)

        # TODO add tests for other global default values
        self.assertEqual(self.app.config['RATE_LIMIT_GET'], None)
        self.assertEqual(self.app.config['RATE_LIMIT_POST'], None)
        self.assertEqual(self.app.config['RATE_LIMIT_PATCH'], None)
        self.assertEqual(self.app.config['RATE_LIMIT_DELETE'], None)

        self.assertEqual(self.app.config['MONGO_HOST'], 'localhost')
        self.assertEqual(self.app.config['MONGO_PORT'], 27017)
        self.assertEqual(self.app.config['MONGO_QUERY_BLACKLIST'], ['$where',
                                                                    '$regex'])
        self.assertEqual(self.app.config['MONGO_WRITE_CONCERN'], {'w': 1})
        self.assertEqual(self.app.config['ISSUES'], '_issues')

    def test_settings_as_dict(self):
        my_settings = {'API_VERSION': 'override!', 'DOMAIN': {'contacts': {}}}
        self.app = Eve(settings=my_settings)
        self.assertEqual(self.app.config['API_VERSION'], 'override!')
        # did not reset other defaults
        self.assertEqual(self.app.config['MONGO_WRITE_CONCERN'], {'w': 1})

    def test_unexisting_pyfile_config(self):
        self.assertRaises(IOError, Eve, settings='an_unexisting_pyfile.py')

    def test_unexisting_env_config(self):
        env = os.environ
        try:
            os.environ = {'EVE_SETTINGS': 'an_unexisting_pyfile.py'}
            self.assertRaises(IOError, Eve)
        finally:
            os.environ = env

    def test_custom_validator(self):
        class MyTestValidator(Validator):
            pass
        self.app = Eve(validator=MyTestValidator,
                       settings=self.settings_file)
        self.assertEqual(self.app.validator, MyTestValidator)

    def test_custom_datalayer(self):
        class MyTestDataLayer(DataLayer):
            def init_app(self, app):
                pass
        self.app = Eve(data=MyTestDataLayer, settings=self.settings_file)
        self.assertEqual(type(self.app.data), MyTestDataLayer)

    def test_validate_domain_struct(self):
        del self.app.config['DOMAIN']
        self.assertValidateConfigFailure('missing')

        self.app.config['DOMAIN'] = []
        self.assertValidateConfigFailure('must be a dict')

        self.app.config['DOMAIN'] = {}
        self.assertValidateConfigFailure('must contain at least one')

    def test_validate_resource_methods(self):
        self.app.config['RESOURCE_METHODS'] = ['PUT', 'GET', 'DELETE', 'POST']
        self.assertValidateConfigFailure('PUT')

    def test_validate_item_methods(self):
        self.app.config['ITEM_METHODS'] = ['PUT', 'GET', 'POST', 'DELETE']
        self.assertValidateConfigFailure(['POST', 'PUT'])

    def test_validate_schema_methods(self):
        test = {
            'resource_methods': ['PUT', 'GET', 'DELETE', 'POST'],
        }
        self.app.config['DOMAIN']['test_resource'] = test
        self.assertValidateConfigFailure('PUT')

    def test_validate_schema_item_methods(self):
        test = {
            'resource_methods': ['GET'],
            'item_methods': ['POST'],
        }
        self.app.config['DOMAIN']['test_resource'] = test
        self.assertValidateConfigFailure('PUT')

    def test_validate_datecreated_in_schema(self):
        self.assertUnallowedField(eve.DATE_CREATED)

    def test_validate_lastupdated_in_schema(self):
        self.assertUnallowedField(eve.LAST_UPDATED)

    def test_validate_idfield_in_schema(self):
        self.assertUnallowedField(eve.ID_FIELD, 'objectid')

    def assertUnallowedField(self, field, field_type='datetime'):
        self.domain.clear()
        schema = {field: {'type': field_type}}
        self.domain['resource'] = {'schema': schema}
        self.app.set_defaults()
        self.assertValidateSchemaFailure('resource', schema, field)

    def test_validate_schema(self):
        # lack of 'collection' key for 'data_collection' rule
        schema = self.domain['invoices']['schema']
        del(schema['person']['data_relation']['resource'])
        self.assertValidateSchemaFailure('invoices', schema, 'resource')

    def test_set_schema_defaults(self):
        # default data_relation field value
        schema = self.domain['invoices']['schema']
        data_relation = schema['person']['data_relation']
        self.assertTrue('field' in data_relation)
        self.assertEqual(data_relation['field'], self.app.config['ID_FIELD'])

    def test_set_defaults(self):
        self.domain.clear()
        resource = 'plurals'
        self.domain[resource] = {}
        self.app.set_defaults()
        self._test_defaults_for_resource(resource)
        settings = self.domain[resource]
        self.assertEqual(len(settings['schema']), 0)

    def _test_defaults_for_resource(self, resource):
        settings = self.domain[resource]
        self.assertEqual(settings['url'], resource)
        self.assertEqual(settings['resource_methods'],
                         self.app.config['RESOURCE_METHODS'])
        self.assertEqual(settings['public_methods'],
                         self.app.config['PUBLIC_METHODS'])
        self.assertEqual(settings['allowed_roles'],
                         self.app.config['ALLOWED_ROLES'])
        self.assertEqual(settings['cache_control'],
                         self.app.config['CACHE_CONTROL'])
        self.assertEqual(settings['cache_expires'],
                         self.app.config['CACHE_EXPIRES'])
        self.assertEqual(settings['item_methods'],
                         self.app.config['ITEM_METHODS'])
        self.assertEqual(settings['public_item_methods'],
                         self.app.config['PUBLIC_ITEM_METHODS'])
        self.assertEqual(settings['allowed_item_roles'],
                         self.app.config['ALLOWED_ITEM_ROLES'])
        self.assertEqual(settings['item_lookup'],
                         self.app.config['ITEM_LOOKUP'])
        self.assertEqual(settings['item_lookup_field'],
                         self.app.config['ITEM_LOOKUP_FIELD'])
        self.assertEqual(settings['item_url'],
                         self.app.config['ITEM_URL'])
        self.assertEqual(settings['item_title'],
                         resource.rstrip('s').capitalize())
        self.assertEqual(settings['allowed_filters'],
                         self.app.config['ALLOWED_FILTERS'])
        self.assertEqual(settings['projection'], self.app.config['PROJECTION'])
        self.assertEqual(settings['sorting'], self.app.config['SORTING'])
        self.assertEqual(settings['embedding'], self.app.config['EMBEDDING'])
        self.assertEqual(settings['pagination'], self.app.config['PAGINATION'])
        self.assertEqual(settings['auth_field'],
                         self.app.config['AUTH_FIELD'])
        self.assertEqual(settings['allow_unknown'],
                         self.app.config['ALLOW_UNKNOWN'])
        self.assertEqual(settings['extra_response_fields'],
                         self.app.config['EXTRA_RESPONSE_FIELDS'])
        self.assertEqual(settings['mongo_write_concern'],
                         self.app.config['MONGO_WRITE_CONCERN'])
        self.assertEqual(settings['resource_title'], settings['url'])

        self.assertNotEqual(settings['schema'], None)
        self.assertEqual(type(settings['schema']), dict)

    def test_datasource(self):
        self._test_datasource_for_resource('invoices')

    def _test_datasource_for_resource(self, resource):
        datasource = self.domain[resource]['datasource']
        schema = self.domain[resource]['schema']
        compare = [key for key in datasource['projection'] if key in schema]
        compare.extend([self.app.config['ID_FIELD'],
                        self.app.config['LAST_UPDATED'],
                        self.app.config['DATE_CREATED']])

        self.assertEqual(datasource['projection'],
                         dict((field, 1) for (field) in compare))
        self.assertEqual(datasource['source'], resource)
        self.assertEqual(datasource['filter'], None)

    def test_validate_roles(self):
        for resource in self.domain:
            self.assertValidateRoles(resource, 'allowed_roles')
            self.assertValidateRoles(resource, 'allowed_item_roles')

    def assertValidateRoles(self, resource, directive):
        self.domain[resource][directive] = 'admin'
        self.assertValidateConfigFailure(directive)
        self.domain[resource][directive] = []
        self.assertValidateConfigFailure(directive)
        self.domain[resource][directive] = ['admin', 'dev']
        self.assertValidateConfigSuccess()
        self.domain[resource][directive] = None
        self.assertValidateConfigSuccess()

    def assertValidateConfigSuccess(self):
        try:
            self.app.validate_domain_struct()
            self.app.validate_config()
        except ConfigException as e:
            self.fail('ConfigException not expected: %s' % e)

    def assertValidateConfigFailure(self, expected):
        try:
            self.app.validate_domain_struct()
            self.app.validate_config()
        except ConfigException as e:
            if isinstance(expected, str):
                expected = [expected]
            for exp in expected:
                self.assertTrue(exp.lower() in str(e).lower())
        else:
            self.fail("ConfigException expected but not raised.")

    def assertValidateSchemaFailure(self, resource, schema, expected):
        try:
            self.app.validate_schema(resource, schema)
        except SchemaException as e:
            self.assertTrue(expected.lower() in str(e).lower())
        else:
            self.fail("SchemaException expected but not raised.")

    def test_schema_defaults(self):
        self.domain.clear()
        self.domain['resource'] = {
            'schema': {
                'title': {
                    'type': 'string',
                    'default': 'Mr.',
                },
                'price': {
                    'type': 'integer',
                    'default': 100
                },
            }
        }
        self.app.set_defaults()
        settings = self.domain['resource']
        self.assertNotEqual(settings.get('defaults'), None)
        self.assertEqual(type(settings['defaults']), set)
        self.assertEqual(len(settings['defaults']), 2)

    def test_url_helpers(self):
        self.assertNotEqual(self.app.config.get('URLS'), None)
        self.assertEqual(type(self.app.config['URLS']), dict)

        self.assertNotEqual(self.app.config.get('SOURCES'), None)
        self.assertEqual(type(self.app.config['SOURCES']), dict)

        for resource, settings in self.domain.items():
            self.assertEqual(settings['url'],
                             self.app.config['URLS'][resource])
            self.assertEqual(settings['datasource'],
                             self.app.config['SOURCES'][resource])

    def test_url_rules(self):
        map_adapter = self.app.url_map.bind(self.app.config.get(
            'SERVER_NAME', ''))

        del(self.domain['peopleinvoices'])
        for _, settings in self.domain.items():
            for method in settings['resource_methods']:
                self.assertTrue(map_adapter.test('/%s/' % settings['url'],
                                                 method))

            # TODO test item endpoints as well. gonna be tricky since
            # we have to reverse regexes here. will be fun.

    def test_register_resource(self):
        resource = 'resource'
        settings = {
            'schema': {
                'title': {
                    'type': 'string',
                    'default': 'Mr.',
                },
                'price': {
                    'type': 'integer',
                    'default': 100
                },
            }
        }
        self.app.register_resource(resource, settings)
        self._test_defaults_for_resource(resource)
        self._test_datasource_for_resource(resource)
        self.test_validate_roles()
Example #29
0
File: config.py Project: sunbit/eve
 def test_custom_kwargs(self):
     self.app = Eve("unittest", static_folder="/", settings=self.settings_file)
     self.assertEqual(self.app.static_folder, "/")
Example #30
0
File: config.py Project: sunbit/eve
 def test_settings_as_dict(self):
     my_settings = {"API_VERSION": "override!", "DOMAIN": {"contacts": {}}}
     self.app = Eve(settings=my_settings)
     self.assertEqual(self.app.config["API_VERSION"], "override!")
     # did not reset other defaults
     self.assertEqual(self.app.config["MONGO_WRITE_CONCERN"], {"w": 1})
Example #31
0
 def test_existing_env_config(self):
     env = os.environ
     os.environ = {'EVE_SETTINGS': 'test_settings_env.py'}
     self.app = Eve()
     self.assertTrue('env_domain' in self.app.config['DOMAIN'])
     os.environ = env
Example #32
0
File: config.py Project: AdamJB/eve
class TestConfig(TestBase):
    def test_default_import_name(self):
        self.assertEqual(self.app.import_name, eve.__package__)

    def test_custom_import_name(self):
        self.app = Eve('custom_import_name',
                       settings='eve/tests/test_settings.py')
        self.assertEqual(self.app.import_name, 'custom_import_name')

    def test_custom_kwargs(self):
        self.app = Eve('custom_import_name', static_folder='/',
                       settings='eve/tests/test_settings.py')
        self.assertEqual(self.app.static_folder, '/')

    def test_regexconverter(self):
        regex_converter = self.app.url_map.converters.get('regex')
        self.assertEqual(regex_converter, RegexConverter)

    def test_default_validator(self):
        self.assertEqual(self.app.validator, Validator)

    def test_default_datalayer(self):
        self.assertEqual(type(self.app.data), Mongo)

    def test_default_settings(self):
        self.assertEqual(self.app.settings, self.settings_file)

        # TODO add tests for other global default values
        self.assertEqual(self.app.config['RATE_LIMIT_GET'], None)
        self.assertEqual(self.app.config['RATE_LIMIT_POST'], None)
        self.assertEqual(self.app.config['RATE_LIMIT_PATCH'], None)
        self.assertEqual(self.app.config['RATE_LIMIT_DELETE'], None)

        self.assertEqual(self.app.config['MONGO_HOST'], 'localhost')
        self.assertEqual(self.app.config['MONGO_PORT'], 27017)
        self.assertEqual(self.app.config['MONGO_QUERY_BLACKLIST'], ['$where',
                                                                    '$regex'])
        self.assertEqual(self.app.config['MONGO_WRITE_CONCERN'], {'w': 1})

    def test_unexisting_pyfile_config(self):
        self.assertRaises(IOError, Eve, settings='an_unexisting_pyfile.py')

    def test_unexisting_env_config(self):
        env = os.environ
        try:
            os.environ = {'EVE_SETTINGS': 'an_unexisting_pyfile.py'}
            self.assertRaises(IOError, Eve)
        finally:
            os.environ = env

    def test_custom_validator(self):
        class MyTestValidator(Validator):
            pass
        self.app = Eve(validator=MyTestValidator,
                       settings=self.settings_file)
        self.assertEqual(self.app.validator, MyTestValidator)

    def test_custom_datalayer(self):
        class MyTestDataLayer(DataLayer):
            def init_app(self, app):
                pass
            pass
        self.app = Eve(data=MyTestDataLayer, settings=self.settings_file)
        self.assertEqual(type(self.app.data), MyTestDataLayer)

    def test_validate_domain_struct(self):
        del self.app.config['DOMAIN']
        self.assertValidateConfigFailure('missing')

        self.app.config['DOMAIN'] = []
        self.assertValidateConfigFailure('must be a dict')

        self.app.config['DOMAIN'] = {}
        self.assertValidateConfigFailure('must contain at least one')

    def test_validate_resource_methods(self):
        self.app.config['RESOURCE_METHODS'] = ['PUT', 'GET', 'DELETE', 'POST']
        self.assertValidateConfigFailure('PUT')

    def test_validate_item_methods(self):
        self.app.config['ITEM_METHODS'] = ['PUT', 'GET', 'POST', 'DELETE']
        self.assertValidateConfigFailure(['POST', 'PUT'])

    def test_validate_schema_methods(self):
        test = {
            'resource_methods': ['PUT', 'GET', 'DELETE', 'POST'],
        }
        self.app.config['DOMAIN']['test_resource'] = test
        self.assertValidateConfigFailure('PUT')

    def test_validate_schema_item_methods(self):
        test = {
            'resource_methods': ['GET'],
            'item_methods': ['PUT'],
        }
        self.app.config['DOMAIN']['test_resource'] = test
        self.assertValidateConfigFailure('PUT')

    def test_validate_datecreated_in_schema(self):
        self.assertUnallowedField(eve.DATE_CREATED)

    def test_validate_lastupdated_in_schema(self):
        self.assertUnallowedField(eve.LAST_UPDATED)

    def test_validate_idfield_in_schema(self):
        self.assertUnallowedField(eve.ID_FIELD)

    def assertUnallowedField(self, field):
        self.domain.clear()
        schema = {field: {'type': 'datetime'}}
        self.domain['resource'] = {'schema': schema}
        self.app.set_defaults()
        self.assertValidateSchemaFailure('resource', schema, field)

    def test_validate_schema(self):
        # lack of 'collection' key for 'data_collection' rule
        schema = self.domain['invoices']['schema']
        del(schema['person']['data_relation']['collection'])
        self.assertValidateSchemaFailure('invoices', schema, 'collection')

    def test_set_schema_defaults(self):
        # default data_relation field value
        schema = self.domain['invoices']['schema']
        data_relation = schema['person']['data_relation']
        self.assertTrue('field' in data_relation)
        self.assertEqual(data_relation['field'], self.app.config['ID_FIELD'])

    def test_set_defaults(self):
        self.domain.clear()
        resource = 'plurals'
        self.domain[resource] = {}

        self.app.set_defaults()

        settings = self.domain[resource]
        self.assertEqual(settings['url'], resource)
        self.assertEqual(settings['resource_methods'],
                         self.app.config['RESOURCE_METHODS'])
        self.assertEqual(settings['public_methods'],
                         self.app.config['PUBLIC_METHODS'])
        self.assertEqual(settings['allowed_roles'],
                         self.app.config['ALLOWED_ROLES'])
        self.assertEqual(settings['cache_control'],
                         self.app.config['CACHE_CONTROL'])
        self.assertEqual(settings['cache_expires'],
                         self.app.config['CACHE_EXPIRES'])
        self.assertEqual(settings['item_methods'],
                         self.app.config['ITEM_METHODS'])
        self.assertEqual(settings['public_item_methods'],
                         self.app.config['PUBLIC_ITEM_METHODS'])
        self.assertEqual(settings['allowed_item_roles'],
                         self.app.config['ALLOWED_ITEM_ROLES'])
        self.assertEqual(settings['item_lookup'],
                         self.app.config['ITEM_LOOKUP'])
        self.assertEqual(settings['item_lookup_field'],
                         self.app.config['ITEM_LOOKUP_FIELD'])
        self.assertEqual(settings['item_url'],
                         self.app.config['ITEM_URL'])
        self.assertEqual(settings['item_title'],
                         resource.rstrip('s').capitalize())
        self.assertEqual(settings['allowed_filters'],
                         self.app.config['ALLOWED_FILTERS'])
        self.assertEqual(settings['projection'], self.app.config['PROJECTION'])
        self.assertEqual(settings['sorting'], self.app.config['SORTING'])
        self.assertEqual(settings['pagination'], self.app.config['PAGINATION'])
        self.assertEqual(settings['auth_field'],
                         self.app.config['AUTH_FIELD'])
        self.assertEqual(settings['allow_unknown'],
                         self.app.config['ALLOW_UNKNOWN'])
        self.assertEqual(settings['extra_response_fields'],
                         self.app.config['EXTRA_RESPONSE_FIELDS'])
        self.assertEqual(settings['mongo_write_concern'],
                         self.app.config['MONGO_WRITE_CONCERN'])

        self.assertNotEqual(settings['schema'], None)
        self.assertEqual(type(settings['schema']), dict)
        self.assertEqual(len(settings['schema']), 0)

    def test_datasource(self):
        resource = 'invoices'
        datasource = self.domain[resource]['datasource']
        schema = self.domain[resource]['schema']
        compare = [key for key in datasource['projection'] if key in schema]
        compare.extend([self.app.config['ID_FIELD'],
                        self.app.config['LAST_UPDATED'],
                        self.app.config['DATE_CREATED']])

        self.assertEqual(datasource['projection'],
                         dict((field, 1) for (field) in compare))
        self.assertEqual(datasource['source'], resource)
        self.assertEqual(datasource['filter'], None)

    def test_validate_roles(self):
        for resource in self.domain:
            self.assertValidateRoles(resource, 'allowed_roles')
            self.assertValidateRoles(resource, 'allowed_item_roles')

    def assertValidateRoles(self, resource, directive):
        self.domain[resource][directive] = 'admin'
        self.assertValidateConfigFailure(directive)
        self.domain[resource][directive] = []
        self.assertValidateConfigFailure(directive)
        self.domain[resource][directive] = ['admin', 'dev']
        self.assertValidateConfigSuccess()
        self.domain[resource][directive] = None
        self.assertValidateConfigSuccess()

    def assertValidateConfigSuccess(self):
        try:
            self.app.validate_domain_struct()
            self.app.validate_config()
        except ConfigException as e:
            self.fail('ConfigException not expected: %s' % e)

    def assertValidateConfigFailure(self, expected):
        try:
            self.app.validate_domain_struct()
            self.app.validate_config()
        except ConfigException as e:
            if isinstance(expected, str):
                expected = [expected]
            for exp in expected:
                self.assertTrue(exp.lower() in str(e).lower())
        else:
            self.fail("ConfigException expected but not raised.")

    def assertValidateSchemaFailure(self, resource, schema, expected):
        try:
            self.app.validate_schema(resource, schema)
        except SchemaException as e:
            self.assertTrue(expected.lower() in str(e).lower())
        else:
            self.fail("SchemaException expected but not raised.")

    def test_schema_dates(self):
        self.domain.clear()
        self.domain['resource'] = {
            'schema': {
                'born': {
                    'type': 'datetime',
                },
                'name': {
                    'type': 'string',
                },
                'another_date': {
                    'type': 'datetime',
                }
            }
        }
        self.app.set_defaults()
        settings = self.domain['resource']
        self.assertNotEqual(settings.get('dates'), None)
        self.assertEqual(type(settings['dates']), set)
        self.assertEqual(len(settings['dates']), 2)

    def test_schema_defaults(self):
        self.domain.clear()
        self.domain['resource'] = {
            'schema': {
                'title': {
                    'type': 'string',
                    'default': 'Mr.',
                },
                'price': {
                    'type': 'integer',
                    'default': 100
                },
            }
        }
        self.app.set_defaults()
        settings = self.domain['resource']
        self.assertNotEqual(settings.get('defaults'), None)
        self.assertEqual(type(settings['defaults']), set)
        self.assertEqual(len(settings['defaults']), 2)

    def test_url_helpers(self):
        self.assertNotEqual(self.app.config.get('RESOURCES'), None)
        self.assertEqual(type(self.app.config['RESOURCES']), dict)

        self.assertNotEqual(self.app.config.get('URLS'), None)
        self.assertEqual(type(self.app.config['URLS']), dict)

        self.assertNotEqual(self.app.config.get('SOURCES'), None)
        self.assertEqual(type(self.app.config['SOURCES']), dict)

        for resource, settings in self.domain.items():
            self.assertEqual(settings['url'],
                             self.app.config['URLS'][resource])
            self.assertEqual(resource,
                             self.app.config['RESOURCES'][settings['url']])

            self.assertEqual(settings['datasource'],
                             self.app.config['SOURCES'][resource])

    def test_url_rules(self):
        map_adapter = self.app.url_map.bind(self.app.config['SERVER_NAME'])

        for resource, settings in self.domain.items():
            for method in settings['resource_methods']:
                self.assertTrue(map_adapter.test('/%s/' % settings['url'],
                                                 method))
class TestConfig(TestBase):
    def test_allow_unknown_with_soft_delete(self):
        my_settings = {
            'ALLOW_UNKNOWN': True,
            'SOFT_DELETE': True,
            'DOMAIN': {'contacts': {}}
        }
        try:
            self.app = Eve(settings=my_settings)
        except TypeError:
            self.fail("ALLOW_UNKNOWN and SOFT_DELETE enabled should not cause "
                      "a crash.")

    def test_default_import_name(self):
        self.assertEqual(self.app.import_name, eve.__package__)

    def test_custom_import_name(self):
        self.app = Eve('unittest', settings=self.settings_file)
        self.assertEqual(self.app.import_name, 'unittest')

    def test_custom_kwargs(self):
        self.app = Eve('unittest', static_folder='/',
                       settings=self.settings_file)
        self.assertEqual(self.app.static_folder, '/')

    def test_regexconverter(self):
        regex_converter = self.app.url_map.converters.get('regex')
        self.assertEqual(regex_converter, RegexConverter)

    def test_default_validator(self):
        self.assertEqual(self.app.validator, Validator)

    def test_default_datalayer(self):
        self.assertEqual(type(self.app.data), Mongo)

    def test_default_settings(self):
        self.assertEqual(self.app.settings, self.settings_file)

        # TODO add tests for other global default values
        self.assertEqual(self.app.config['RATE_LIMIT_GET'], None)
        self.assertEqual(self.app.config['RATE_LIMIT_POST'], None)
        self.assertEqual(self.app.config['RATE_LIMIT_PATCH'], None)
        self.assertEqual(self.app.config['RATE_LIMIT_DELETE'], None)

        self.assertEqual(self.app.config['MONGO_HOST'], 'localhost')
        self.assertEqual(self.app.config['MONGO_PORT'], 27017)
        self.assertEqual(self.app.config['MONGO_QUERY_BLACKLIST'], ['$where',
                                                                    '$regex'])
        self.assertEqual(self.app.config['MONGO_WRITE_CONCERN'], {'w': 1})
        self.assertEqual(self.app.config['ISSUES'], '_issues')

        self.assertEqual(self.app.config['OPLOG'], False)
        self.assertEqual(self.app.config['OPLOG_NAME'], 'oplog')
        self.assertEqual(self.app.config['OPLOG_ENDPOINT'], None)
        self.assertEqual(self.app.config['OPLOG_AUDIT'], True)
        self.assertEqual(self.app.config['OPLOG_METHODS'], ['DELETE',
                                                            'POST',
                                                            'PATCH',
                                                            'PUT'])
        self.assertEqual(self.app.config['OPLOG_CHANGE_METHODS'], ['DELETE',
                                                                   'PATCH',
                                                                   'PUT'])
        self.assertEqual(self.app.config['QUERY_WHERE'], 'where')
        self.assertEqual(self.app.config['QUERY_PROJECTION'], 'projection')
        self.assertEqual(self.app.config['QUERY_SORT'], 'sort')
        self.assertEqual(self.app.config['QUERY_PAGE'], 'page')
        self.assertEqual(self.app.config['QUERY_MAX_RESULTS'], 'max_results')
        self.assertEqual(self.app.config['QUERY_EMBEDDED'], 'embedded')
        self.assertEqual(self.app.config['QUERY_AGGREGATION'], 'aggregate')

        self.assertEqual(self.app.config['JSON_SORT_KEYS'], False)
        self.assertEqual(self.app.config['SOFT_DELETE'], False)
        self.assertEqual(self.app.config['DELETED'], '_deleted')
        self.assertEqual(self.app.config['SHOW_DELETED_PARAM'], 'show_deleted')
        self.assertEqual(self.app.config['STANDARD_ERRORS'],
                         [400, 401, 404, 405, 406, 409, 410, 412, 422, 428])
        self.assertEqual(self.app.config['UPSERT_ON_PUT'], True)

    def test_settings_as_dict(self):
        my_settings = {'API_VERSION': 'override!', 'DOMAIN': {'contacts': {}}}
        self.app = Eve(settings=my_settings)
        self.assertEqual(self.app.config['API_VERSION'], 'override!')
        # did not reset other defaults
        self.assertEqual(self.app.config['MONGO_WRITE_CONCERN'], {'w': 1})

    def test_unexisting_env_config(self):
        env = os.environ
        try:
            os.environ = {'EVE_SETTINGS': 'an_unexisting_pyfile.py'}
            self.assertRaises(IOError, Eve)
        finally:
            os.environ = env

    def test_custom_validator(self):
        class MyTestValidator(Validator):
            pass
        self.app = Eve(validator=MyTestValidator,
                       settings=self.settings_file)
        self.assertEqual(self.app.validator, MyTestValidator)

    def test_custom_datalayer(self):
        class MyTestDataLayer(DataLayer):
            def init_app(self, app):
                pass
        self.app = Eve(data=MyTestDataLayer, settings=self.settings_file)
        self.assertEqual(type(self.app.data), MyTestDataLayer)

    def test_validate_domain_struct(self):
        del self.app.config['DOMAIN']
        self.assertValidateConfigFailure('missing')

        self.app.config['DOMAIN'] = []
        self.assertValidateConfigFailure('must be a dict')

        self.app.config['DOMAIN'] = {}
        self.assertValidateConfigSuccess()

    def test_validate_resource_methods(self):
        self.app.config['RESOURCE_METHODS'] = ['PUT', 'GET', 'DELETE', 'POST']
        self.assertValidateConfigFailure('PUT')

    def test_validate_item_methods(self):
        self.app.config['ITEM_METHODS'] = ['PUT', 'GET', 'POST', 'DELETE']
        self.assertValidateConfigFailure(['POST', 'PUT'])

    def test_validate_schema_methods(self):
        test = {
            'resource_methods': ['PUT', 'GET', 'DELETE', 'POST'],
        }
        self.app.config['DOMAIN']['test_resource'] = test
        self.assertValidateConfigFailure('PUT')

    def test_validate_schema_item_methods(self):
        test = {
            'resource_methods': ['GET'],
            'item_methods': ['POST'],
        }
        self.app.config['DOMAIN']['test_resource'] = test
        self.assertValidateConfigFailure('PUT')

    def test_validate_datecreated_in_schema(self):
        self.assertUnallowedField(eve.DATE_CREATED)

    def test_validate_lastupdated_in_schema(self):
        self.assertUnallowedField(eve.LAST_UPDATED)

    def assertUnallowedField(self, field, field_type='datetime'):
        self.domain.clear()
        schema = {field: {'type': field_type}}
        self.domain['resource'] = {'schema': schema}
        self.app.set_defaults()
        self.assertValidateSchemaFailure('resource', schema, field)

    def test_validate_schema(self):
        # lack of 'collection' key for 'data_collection' rule
        schema = self.domain['invoices']['schema']
        del(schema['person']['data_relation']['resource'])
        self.assertValidateSchemaFailure('invoices', schema, 'resource')

    def test_validate_invalid_field_names(self):
        schema = self.domain['invoices']['schema']
        schema['te$t'] = {'type': 'string'}
        self.assertValidateSchemaFailure('invoices', schema, 'te$t')
        del(schema['te$t'])

        schema['te.t'] = {'type': 'string'}
        self.assertValidateSchemaFailure('invoices', schema, 'te.t')
        del(schema['te.t'])

        schema['test_a_dict_schema'] = {
            'type': 'dict',
            'schema': {'te$t': {'type': 'string'}}
        }
        self.assertValidateSchemaFailure('invoices', schema, 'te$t')

        schema['test_a_dict_schema']['schema'] = {'te.t': {'type': 'string'}}
        self.assertValidateSchemaFailure('invoices', schema, 'te.t')

    def test_set_schema_defaults(self):
        # default data_relation field value
        schema = self.domain['invoices']['schema']
        data_relation = schema['person']['data_relation']
        self.assertTrue('field' in data_relation)
        self.assertEqual(data_relation['field'],
                         self.domain['contacts']['id_field'])
        id_field = self.domain['invoices']['id_field']
        self.assertTrue(id_field in schema)
        self.assertEqual(schema[id_field], {'type': 'objectid'})

    def test_set_defaults(self):
        self.domain.clear()
        resource = 'plurals'
        self.domain[resource] = {}
        self.app.set_defaults()
        self._test_defaults_for_resource(resource)
        settings = self.domain[resource]
        self.assertEqual(len(settings['schema']), 1)

    def _test_defaults_for_resource(self, resource):
        settings = self.domain[resource]
        self.assertEqual(settings['url'], resource)
        self.assertEqual(settings['internal_resource'],
                         self.app.config['INTERNAL_RESOURCE'])
        self.assertEqual(settings['resource_methods'],
                         self.app.config['RESOURCE_METHODS'])
        self.assertEqual(settings['public_methods'],
                         self.app.config['PUBLIC_METHODS'])
        self.assertEqual(settings['allowed_roles'],
                         self.app.config['ALLOWED_ROLES'])
        self.assertEqual(settings['allowed_read_roles'],
                         self.app.config['ALLOWED_READ_ROLES'])
        self.assertEqual(settings['allowed_write_roles'],
                         self.app.config['ALLOWED_WRITE_ROLES'])
        self.assertEqual(settings['cache_control'],
                         self.app.config['CACHE_CONTROL'])
        self.assertEqual(settings['cache_expires'],
                         self.app.config['CACHE_EXPIRES'])
        self.assertEqual(settings['item_methods'],
                         self.app.config['ITEM_METHODS'])
        self.assertEqual(settings['public_item_methods'],
                         self.app.config['PUBLIC_ITEM_METHODS'])
        self.assertEqual(settings['allowed_item_roles'],
                         self.app.config['ALLOWED_ITEM_ROLES'])
        self.assertEqual(settings['allowed_item_read_roles'],
                         self.app.config['ALLOWED_ITEM_READ_ROLES'])
        self.assertEqual(settings['allowed_item_write_roles'],
                         self.app.config['ALLOWED_ITEM_WRITE_ROLES'])
        self.assertEqual(settings['item_lookup'],
                         self.app.config['ITEM_LOOKUP'])
        self.assertEqual(settings['item_lookup_field'],
                         self.app.config['ITEM_LOOKUP_FIELD'])
        self.assertEqual(settings['item_url'],
                         self.app.config['ITEM_URL'])
        self.assertEqual(settings['item_title'],
                         resource.rstrip('s').capitalize())
        self.assertEqual(settings['allowed_filters'],
                         self.app.config['ALLOWED_FILTERS'])
        self.assertEqual(settings['projection'], self.app.config['PROJECTION'])
        self.assertEqual(settings['versioning'], self.app.config['VERSIONING'])
        self.assertEqual(settings['soft_delete'],
                         self.app.config['SOFT_DELETE'])
        self.assertEqual(settings['sorting'], self.app.config['SORTING'])
        self.assertEqual(settings['embedding'], self.app.config['EMBEDDING'])
        self.assertEqual(settings['pagination'], self.app.config['PAGINATION'])
        self.assertEqual(settings['auth_field'],
                         self.app.config['AUTH_FIELD'])
        self.assertEqual(settings['allow_unknown'],
                         self.app.config['ALLOW_UNKNOWN'])
        self.assertEqual(settings['transparent_schema_rules'],
                         self.app.config['TRANSPARENT_SCHEMA_RULES'])
        self.assertEqual(settings['extra_response_fields'],
                         self.app.config['EXTRA_RESPONSE_FIELDS'])
        self.assertEqual(settings['mongo_write_concern'],
                         self.app.config['MONGO_WRITE_CONCERN'])
        self.assertEqual(settings['resource_title'], settings['url'])

        self.assertNotEqual(settings['schema'], None)
        self.assertEqual(type(settings['schema']), dict)
        self.assertEqual(settings['etag_ignore_fields'], None)

    def test_datasource(self):
        self._test_datasource_for_resource('invoices')

    def _test_datasource_for_resource(self, resource):
        datasource = self.domain[resource]['datasource']
        schema = self.domain[resource]['schema']
        compare = [key for key in datasource['projection'] if key in schema]
        compare.extend([self.domain[resource]['id_field'],
                        self.app.config['LAST_UPDATED'],
                        self.app.config['DATE_CREATED'],
                        self.app.config['ETAG']])

        self.assertEqual(datasource['projection'],
                         dict((field, 1) for (field) in compare))
        self.assertEqual(datasource['source'], resource)
        self.assertEqual(datasource['filter'], None)

        self.assertEqual(datasource['aggregation'], None)

    def test_validate_roles(self):
        for resource in self.domain:
            self.assertValidateRoles(resource, 'allowed_roles')
            self.assertValidateRoles(resource, 'allowed_read_roles')
            self.assertValidateRoles(resource, 'allowed_write_roles')
            self.assertValidateRoles(resource, 'allowed_item_roles')
            self.assertValidateRoles(resource, 'allowed_item_read_roles')
            self.assertValidateRoles(resource, 'allowed_item_write_roles')

    def assertValidateRoles(self, resource, directive):
        prev = self.domain[resource][directive]
        self.domain[resource][directive] = 'admin'
        self.assertValidateConfigFailure(directive)
        self.domain[resource][directive] = []
        self.assertValidateConfigSuccess()
        self.domain[resource][directive] = ['admin', 'dev']
        self.assertValidateConfigSuccess()
        self.domain[resource][directive] = None
        self.assertValidateConfigFailure(directive)
        self.domain[resource][directive] = prev

    def assertValidateConfigSuccess(self):
        try:
            self.app.validate_domain_struct()
            self.app.validate_config()
        except ConfigException as e:
            self.fail('ConfigException not expected: %s' % e)

    def assertValidateConfigFailure(self, expected):
        try:
            self.app.validate_domain_struct()
            self.app.validate_config()
        except ConfigException as e:
            if isinstance(expected, str):
                expected = [expected]
            for exp in expected:
                self.assertTrue(exp.lower() in str(e).lower())
        else:
            self.fail("ConfigException expected but not raised.")

    def assertValidateSchemaFailure(self, resource, schema, expected):
        try:
            self.app.validate_schema(resource, schema)
        except SchemaException as e:
            self.assertTrue(expected.lower() in str(e).lower())
        else:
            self.fail("SchemaException expected but not raised.")

    def test_schema_defaults(self):
        self.domain.clear()
        self.domain['resource'] = {
            'schema': {
                'title': {
                    'type': 'string',
                    'default': 'Mr.',
                },
                'price': {
                    'type': 'integer',
                    'default': 100
                },
            }
        }
        self.app.set_defaults()
        settings = self.domain['resource']
        self.assertEqual({'title': 'Mr.', 'price': 100}, settings['defaults'])

    def test_url_helpers(self):
        self.assertNotEqual(self.app.config.get('URLS'), None)
        self.assertEqual(type(self.app.config['URLS']), dict)

        self.assertNotEqual(self.app.config.get('SOURCES'), None)
        self.assertEqual(type(self.app.config['SOURCES']), dict)

        del(self.domain['internal_transactions'])
        for resource, settings in self.domain.items():
            self.assertEqual(settings['datasource'],
                             self.app.config['SOURCES'][resource])

    def test_pretty_resource_urls(self):
        """ test that regexes are stripped out of urls and #466 is fixed. """
        resource_url = self.app.config['URLS']['peopleinvoices']
        pretty_url = 'users/<person>/invoices'
        self.assertEqual(resource_url, pretty_url)
        resource_url = self.app.config['URLS']['peoplesearches']
        pretty_url = 'users/<person>/saved_searches'
        self.assertEqual(resource_url, pretty_url)

    def test_url_rules(self):
        map_adapter = self.app.url_map.bind('')

        del(self.domain['peopleinvoices'])
        del(self.domain['peoplerequiredinvoices'])
        del(self.domain['peoplesearches'])
        del(self.domain['internal_transactions'])
        del(self.domain['child_products'])
        for _, settings in self.domain.items():
            for method in settings['resource_methods']:
                self.assertTrue(map_adapter.test('/%s/' % settings['url'],
                                                 method))

            # TODO test item endpoints as well. gonna be tricky since
            # we have to reverse regexes here. will be fun.

    def test_register_resource(self):
        resource = 'resource'
        settings = {
            'schema': {
                'title': {
                    'type': 'string',
                    'default': 'Mr.',
                },
                'price': {
                    'type': 'integer',
                    'default': 100
                },
            }
        }
        self.app.register_resource(resource, settings)
        self._test_defaults_for_resource(resource)
        self._test_datasource_for_resource(resource)
        self.test_validate_roles()

    def test_auth_field_as_idfield(self):
        resource = 'resource'
        settings = {
            'auth_field': self.app.config['ID_FIELD'],
        }
        self.assertRaises(ConfigException, self.app.register_resource,
                          resource, settings)

    def test_auth_field_as_custom_idfield(self):
        resource = 'resource'
        settings = {
            'schema': {
                'id': {'type': 'string'}
            },
            'id_field': 'id',
            'auth_field': 'id'
        }
        self.assertRaises(ConfigException, self.app.register_resource,
                          resource, settings)

    def test_oplog_config(self):

        # if OPLOG_ENDPOINT is eanbled the endoint is included with the domain
        self.app.config['OPLOG_ENDPOINT'] = 'oplog'
        self.app._init_oplog()
        self.assertOplog('oplog', 'oplog')
        del(self.domain['oplog'])

        # OPLOG can be also with a custom name (which will be used
        # as the collection/table name on the db)
        oplog = 'custom'
        self.app.config['OPLOG_NAME'] = oplog
        self.app._init_oplog()
        self.assertOplog(oplog, 'oplog')
        del(self.domain[oplog])

        # oplog can be defined as a regular API endpoint, with a couple caveats
        self.domain['oplog'] = {
            'resource_methods': ['POST', 'DELETE'],     # not allowed
            'resource_items': ['PATCH', 'PUT'],         # not allowed
            'url': 'custom_url',
            'datasource': {'source': 'customsource'}
        }
        self.app.config['OPLOG_NAME'] = 'oplog'
        settings = self.domain['oplog']
        self.app._init_oplog()

        # endpoint is always read-only
        self.assertEqual(settings['resource_methods'], ['GET'])
        self.assertEqual(settings['item_methods'], ['GET'])
        # other settings are customizable
        self.assertEqual(settings['url'], 'custom_url')
        self.assertEqual(settings['datasource']['source'], 'customsource')

    def assertOplog(self, key, endpoint):
        self.assertTrue(key in self.domain)

        settings = self.domain[key]
        self.assertEqual(settings['resource_methods'], ['GET'])
        self.assertEqual(settings['item_methods'], ['GET'])
        self.assertEqual(settings['url'], endpoint)
        self.assertEqual(settings['datasource']['source'], key)

    def test_create_indexes(self):
        # prepare a specific schema with mongo indexes declared
        # along with the schema.
        settings = {
            'schema': {
                'name': {'type': 'string'},
                'other_field': {'type': 'string'},
                'lat_long': {'type': 'list'}
            },
            'versioning': True,
            'mongo_indexes': {
                'name': [('name', 1)],
                'composed': [('name', 1), ('other_field', 1)],
                'arguments': ([('lat_long', "2d")], {"sparce": True})
            }
        }
        self.app.register_resource('mongodb_features', settings)

        # check that the indexes are there as a part of the resource
        # settings
        self.assertEqual(
            self.app.config['DOMAIN']['mongodb_features']['mongo_indexes'],
            settings['mongo_indexes']
        )

        # check that the indexes were created
        from pymongo import MongoClient
        db_name = self.app.config['MONGO_DBNAME']

        db = MongoClient()[db_name]
        for coll in [db['mongodb_features'], db['mongodb_features_versions']]:
            indexes = coll.index_information()

            # at least there is an index for the _id field plus the indexes
            # created by the resource of this test
            self.assertTrue(len(indexes) > len(settings['mongo_indexes']))

            # check each one, fields involved and arguments given
            for key, value in settings['mongo_indexes'].items():
                if isinstance(value, tuple):
                    fields, args = value
                else:
                    fields = value
                    args = None

                self.assertTrue(key in indexes)
                self.assertEqual(indexes[key]['key'], fields)

                for arg in args or ():
                    self.assertTrue(arg in indexes[key])
                    self.assertEqual(args[arg], indexes[key][arg])

    def test_custom_error_handlers(self):
        """ Test that the standard, custom error handler is registered for
        supported error codes.
        """
        codes = self.app.config['STANDARD_ERRORS']

        # http://flask.pocoo.org/docs/0.10/api/#flask.Flask.error_handler_spec
        handlers = self.app.error_handler_spec[None]

        challenge = lambda code: self.assertTrue(code in handlers)  # noqa
        map(challenge, codes)
Example #34
0
File: config.py Project: AdamJB/eve
 def test_custom_import_name(self):
     self.app = Eve('custom_import_name',
                    settings='eve/tests/test_settings.py')
     self.assertEqual(self.app.import_name, 'custom_import_name')
 def test_custom_import_name(self):
     self.app = Eve('unittest', settings=self.settings_file)
     self.assertEqual(self.app.import_name, 'unittest')
Example #36
0
File: config.py Project: AdamJB/eve
 def test_custom_kwargs(self):
     self.app = Eve('custom_import_name', static_folder='/',
                    settings='eve/tests/test_settings.py')
     self.assertEqual(self.app.static_folder, '/')
 def test_settings_as_dict(self):
     my_settings = {'API_VERSION': 'override!', 'DOMAIN': {'contacts': {}}}
     self.app = Eve(settings=my_settings)
     self.assertEqual(self.app.config['API_VERSION'], 'override!')
     # did not reset other defaults
     self.assertEqual(self.app.config['MONGO_WRITE_CONCERN'], {'w': 1})
Example #38
0
class TestConfig(TestBase):
    def test_default_import_name(self):
        self.assertEqual(self.app.import_name, eve.__package__)

    def test_custom_import_name(self):
        self.app = Eve("custom_import_name", settings="eve/tests/test_settings.py")
        self.assertEqual(self.app.import_name, "custom_import_name")

    def test_custom_kwargs(self):
        self.app = Eve("custom_import_name", static_folder="/", settings="eve/tests/test_settings.py")
        self.assertEqual(self.app.static_folder, "/")

    def test_regexconverter(self):
        regex_converter = self.app.url_map.converters.get("regex")
        self.assertEqual(regex_converter, RegexConverter)

    def test_default_validator(self):
        self.assertEqual(self.app.validator, Validator)

    def test_default_datalayer(self):
        self.assertEqual(type(self.app.data), Mongo)

    def test_default_settings(self):
        self.assertEqual(self.app.settings, self.settings_file)

    def test_unexisting_pyfile_config(self):
        self.assertRaises(IOError, Eve, settings="an_unexisting_pyfile.py")

    def test_unexisting_env_config(self):
        env = os.environ
        try:
            os.environ = {"EVE_SETTINGS": "an_unexisting_pyfile.py"}
            self.assertRaises(IOError, Eve)
        finally:
            os.environ = env

    def test_custom_validator(self):
        class MyTestValidator(Validator):
            pass

        self.app = Eve(validator=MyTestValidator, settings=self.settings_file)
        self.assertEqual(self.app.validator, MyTestValidator)

    def test_custom_datalayer(self):
        class MyTestDataLayer(DataLayer):
            def init_app(self, app):
                pass

            pass

        self.app = Eve(data=MyTestDataLayer, settings=self.settings_file)
        self.assertEqual(type(self.app.data), MyTestDataLayer)

    def test_validate_domain_struct(self):
        del self.app.config["DOMAIN"]
        self.assertValidateConfigFailure("missing")

        self.app.config["DOMAIN"] = []
        self.assertValidateConfigFailure("must be a dict")

        self.app.config["DOMAIN"] = {}
        self.assertValidateConfigFailure("must contain at least one")

    def test_validate_resource_methods(self):
        self.app.config["RESOURCE_METHODS"] = ["PUT", "GET", "DELETE", "POST"]
        self.assertValidateConfigFailure("PUT")

    def test_validate_item_methods(self):
        self.app.config["ITEM_METHODS"] = ["PUT", "GET", "POST", "DELETE"]
        self.assertValidateConfigFailure("PUT, POST")

    def test_validate_schema_methods(self):
        test = {"resource_methods": ["PUT", "GET", "DELETE", "POST"]}
        self.app.config["DOMAIN"]["test_resource"] = test
        self.assertValidateConfigFailure("PUT")

    def test_validate_schema_item_methods(self):
        test = {"resource_methods": ["GET"], "item_methods": ["PUT"]}
        self.app.config["DOMAIN"]["test_resource"] = test
        self.assertValidateConfigFailure("PUT")

    def test_validate_datecreated_in_schema(self):
        self.assertUnallowedField(eve.DATE_CREATED)

    def test_validate_lastupdated_in_schema(self):
        self.assertUnallowedField(eve.LAST_UPDATED)

    def test_validate_idfield_in_schema(self):
        self.assertUnallowedField(eve.ID_FIELD)

    def assertUnallowedField(self, field):
        self.domain.clear()
        schema = {field: {"type": "datetime"}}
        self.domain["resource"] = {"schema": schema}
        self.app.set_defaults()
        self.assertValidateSchemaFailure("resource", schema, field)

    def test_validate_schema(self):
        # lack of 'collection' key for 'data_collection' rule
        schema = self.domain["invoices"]["schema"]
        del (schema["person"]["data_relation"]["collection"])
        self.assertValidateSchemaFailure("invoices", schema, "collection")

    def test_set_schema_defaults(self):
        # default data_relation field value
        schema = self.domain["invoices"]["schema"]
        data_relation = schema["person"]["data_relation"]
        self.assertTrue("field" in data_relation)
        self.assertEqual(data_relation["field"], self.app.config["ID_FIELD"])

    def test_set_defaults(self):
        self.domain.clear()
        resource = "plurals"
        self.domain[resource] = {}

        self.app.set_defaults()

        settings = self.domain[resource]
        self.assertEqual(settings["url"], resource)
        self.assertEqual(settings["resource_methods"], self.app.config["RESOURCE_METHODS"])
        self.assertEqual(settings["public_methods"], self.app.config["PUBLIC_METHODS"])
        self.assertEqual(settings["allowed_roles"], self.app.config["ALLOWED_ROLES"])
        self.assertEqual(settings["cache_control"], self.app.config["CACHE_CONTROL"])
        self.assertEqual(settings["cache_expires"], self.app.config["CACHE_EXPIRES"])
        self.assertEqual(settings["item_methods"], self.app.config["ITEM_METHODS"])
        self.assertEqual(settings["public_item_methods"], self.app.config["PUBLIC_ITEM_METHODS"])
        self.assertEqual(settings["allowed_item_roles"], self.app.config["ALLOWED_ITEM_ROLES"])
        self.assertEqual(settings["item_lookup"], self.app.config["ITEM_LOOKUP"])
        self.assertEqual(settings["item_lookup_field"], self.app.config["ITEM_LOOKUP_FIELD"])
        self.assertEqual(settings["item_url"], self.app.config["ITEM_URL"])
        self.assertEqual(settings["item_title"], resource.rstrip("s").capitalize())
        self.assertEqual(settings["filters"], self.app.config["FILTERS"])
        self.assertEqual(settings["projection"], self.app.config["PROJECTION"])
        self.assertEqual(settings["sorting"], self.app.config["SORTING"])
        self.assertEqual(settings["pagination"], self.app.config["PAGINATION"])
        self.assertEqual(settings["auth_username_field"], self.app.config["AUTH_USERNAME_FIELD"])
        self.assertEqual(settings["allow_unknown"], self.app.config["ALLOW_UNKNOWN"])

        self.assertNotEqual(settings["schema"], None)
        self.assertEqual(type(settings["schema"]), dict)
        self.assertEqual(len(settings["schema"]), 0)

    def test_datasource(self):
        resource = "invoices"
        datasource = self.domain[resource]["datasource"]
        schema = self.domain[resource]["schema"]
        compare = filter(schema.has_key, datasource["projection"])
        compare.extend([self.app.config["ID_FIELD"], self.app.config["LAST_UPDATED"], self.app.config["DATE_CREATED"]])

        self.assertEqual(datasource["projection"], dict((field, 1) for (field) in compare))
        self.assertEqual(datasource["source"], resource)
        self.assertEqual(datasource["filter"], None)

    def test_validate_roles(self):
        for resource in self.domain:
            self.assertValidateRoles(resource, "allowed_roles")
            self.assertValidateRoles(resource, "allowed_item_roles")

    def assertValidateRoles(self, resource, directive):
        self.domain[resource][directive] = "admin"
        self.assertValidateConfigFailure(directive)
        self.domain[resource][directive] = []
        self.assertValidateConfigFailure(directive)
        self.domain[resource][directive] = ["admin", "dev"]
        self.assertValidateConfigSuccess()
        self.domain[resource][directive] = None
        self.assertValidateConfigSuccess()

    def assertValidateConfigSuccess(self):
        try:
            self.app.validate_domain_struct()
            self.app.validate_config()
        except ConfigException, e:
            self.fail("ConfigException not expected: %s" % e)