def test_auto_drop_schema_bulk_delete(self): """ When bulk deleting tenants, it should also drop the schemas of tenants that have auto_drop_schema set to True. """ Tenant.auto_drop_schema = True schemas = ['auto_drop_schema1', 'auto_drop_schema2'] for schema in schemas: self.assertFalse(schema_exists(schema)) tenant = Tenant( domain_url='%s.test.com' % schema, schema_name=schema ) tenant.save(verbosity=BaseTestCase.get_verbosity()) self.assertTrue(schema_exists(tenant.schema_name)) # Force pending trigger events to be executed cursor = connection.cursor() cursor.execute('SET CONSTRAINTS ALL IMMEDIATE') # get a queryset of our 2 tenants and do a bulk delete Tenant.objects.filter(schema_name__in=schemas).delete() # verify that the schemas where deleted for schema in schemas: self.assertFalse(schema_exists(schema)) Tenant.auto_drop_schema = False
def test_tenant_schema_is_created(self): """ When saving a tenant, it's schema should be created. """ tenant = Tenant(domain_url='something.test.com', schema_name='test') tenant.save() self.assertTrue(schema_exists(tenant.schema_name))
def test_throw_exception_if_db_not_specified(self): """ When saving a tenant without 'using' kwarg of save method throw MultiDBError """ tenant = Tenant(domain_url='something.test.com', schema_name='test') try: tenant.save( verbosity=BaseTestCase.get_verbosity()) except Exception as e: self.assertTrue(isinstance(e, MultipleDBError))
def test_switching_tenant_without_previous_tenant(self): tenant = Tenant(domain_url='something.test.com', schema_name='test') tenant.save() connection.tenant = None with tenant_context(tenant): DummyModel(name="No exception please").save() connection.tenant = None with schema_context(tenant.schema_name): DummyModel(name="Survived it!").save()
def setUp(self): # settings needs some patching settings.TENANT_MODEL = 'tenant_schemas.Tenant' # add the public tenant self.public_tenant_domain = 'test.com' self.public_tenant = Tenant(domain_url=self.public_tenant_domain, schema_name='public') self.public_tenant.save() connection.set_schema_to_public()
def test_switching_tenant_without_previous_tenant(self): tenant = Tenant(domain_url="something.test.com", schema_name="test") tenant.save(verbosity=BaseTestCase.get_verbosity()) connection.tenant = None with tenant_context(tenant): DummyModel(name="No exception please").save() connection.tenant = None with schema_context(tenant.schema_name): DummyModel(name="Survived it!").save()
class RoutesTestCase(BaseTestCase): @classmethod def setUpClass(cls): super(RoutesTestCase, cls).setUpClass() settings.SHARED_APPS = ('tenant_schemas', ) settings.TENANT_APPS = ( 'dts_test_app', 'django.contrib.contenttypes', 'django.contrib.auth', ) settings.INSTALLED_APPS = settings.SHARED_APPS + settings.TENANT_APPS cls.sync_shared() cls.public_tenant = Tenant(domain_url='test.com', schema_name=get_public_schema_name()) cls.public_tenant.save(verbosity=BaseTestCase.get_verbosity()) def setUp(self): super(RoutesTestCase, self).setUp() self.factory = RequestFactory() self.tm = TenantMiddleware() self.tenant_domain = 'tenant.test.com' self.tenant = Tenant(domain_url=self.tenant_domain, schema_name='test') self.tenant.save(verbosity=BaseTestCase.get_verbosity()) def test_tenant_routing(self): """ Request path should not be altered. """ request_url = '/any/request/' request = self.factory.get('/any/request/', HTTP_HOST=self.tenant_domain) self.tm.process_request(request) self.assertEquals(request.path_info, request_url) # request.tenant should also have been set self.assertEquals(request.tenant, self.tenant) def test_public_schema_routing(self): """ Request path should not be altered. """ request_url = '/any/request/' request = self.factory.get('/any/request/', HTTP_HOST=self.public_tenant.domain_url) self.tm.process_request(request) self.assertEquals(request.path_info, request_url) # request.tenant should also have been set self.assertEquals(request.tenant, self.public_tenant)
class RoutesTestCase(TransactionTestCase): @classmethod def setUpClass(cls): settings.TENANT_APPS = ('tenant_schemas', 'django.contrib.contenttypes', 'django.contrib.auth', ) def setUp(self): self.factory = RequestFactory() self.tm = TenantMiddleware() # settings needs some patching settings.TENANT_MODEL = 'tenant_schemas.Tenant' settings.PUBLIC_SCHEMA_URL_TOKEN = '/public' # add the public tenant self.public_tenant_domain = 'test.com' self.public_tenant = Tenant(domain_url=self.public_tenant_domain, schema_name='public') self.public_tenant.save() # add a test tenant self.tenant_domain = 'tenant.test.com' self.tenant = Tenant(domain_url=self.tenant_domain, schema_name='test') self.tenant.save() def tearDown(self): Tenant.objects.all().delete() def test_tenant_routing(self): """ request path should not be altered """ request_url = '/any/request/' request = self.factory.get('/any/request/', HTTP_HOST=self.tenant_domain) self.tm.process_request(request) self.assertEquals(request.path_info, request_url) # request.tenant should also have been set self.assertEquals(request.tenant, self.tenant) def test_public_schema_routing(self): """ request path should get prepended with PUBLIC_SCHEMA_URL_TOKEN """ request_url = '/any/request/' request = self.factory.get('/any/request/', HTTP_HOST=self.public_tenant_domain) self.tm.process_request(request) self.assertEquals(request.path_info, settings.PUBLIC_SCHEMA_URL_TOKEN + request_url) # request.tenant should also have been set self.assertEquals(request.tenant, self.public_tenant)
class RoutesTestCase(TestCase): def setUp(self): self.factory = RequestFactory() self.tm = TenantMiddleware() # settings needs some patching settings.TENANT_MODEL = 'tenant_schemas.Tenant' settings.PUBLIC_SCHEMA_URL_TOKEN = '/public' # add the public tenant self.public_tenant_domain = 'test.com' self.public_tenant = Tenant(domain_url=self.public_tenant_domain, schema_name='public') self.public_tenant.save() # add a test tenant self.tenant_domain = 'tenant.test.com' self.tenant = Tenant(domain_url=self.tenant_domain, schema_name='test') self.tenant.save() def tearDown(self): Tenant.objects.all().delete() def test_tenant_routing(self): """ request path should not be altered """ request_url = '/any/request/' request = self.factory.get('/any/request/', HTTP_HOST=self.tenant_domain) self.tm.process_request(request) self.assertEquals(request.path_info, request_url) # request.tenant should also have been set self.assertEquals(request.tenant, self.tenant) def test_public_schema_routing(self): """ request path should get prepended with PUBLIC_SCHEMA_URL_TOKEN """ request_url = '/any/request/' request = self.factory.get('/any/request/', HTTP_HOST=self.public_tenant_domain) self.tm.process_request(request) self.assertEquals(request.path_info, settings.PUBLIC_SCHEMA_URL_TOKEN + request_url) # request.tenant should also have been set self.assertEquals(request.tenant, self.public_tenant)
def setUp(self): super(RoutesTestCase, self).setUp() self.factory = RequestFactory() self.tm = TenantMiddleware() self.dtm = DefaultTenantMiddleware() self.tenant_domain = 'tenant.test.com' self.tenant = Tenant(domain_url=self.tenant_domain, schema_name='test') self.tenant.save(verbosity=BaseTestCase.get_verbosity()) self.non_existent_domain = 'no-tenant.test.com' self.non_existent_tenant = Tenant(domain_url=self.non_existent_domain, schema_name='no-tenant') self.url = '/any/path/'
def test_switching_search_path(self): dummies_tenant1_count, dummies_tenant2_count = 0, 0 tenant1 = Tenant(domain_url='test.com', schema_name='tenant1') tenant1.save() connection.set_schema_to_public() tenant2 = Tenant(domain_url='example.com', schema_name='tenant2') tenant2.save() # go to tenant1's path connection.set_tenant(tenant1) # add some data DummyModel(name="Schemas are").save() DummyModel(name="awesome!").save() dummies_tenant1_count = DummyModel.objects.count() # switch temporarily to tenant2's path with tenant_context(tenant2): # add some data DummyModel(name="Man,").save() DummyModel(name="testing").save() DummyModel(name="is great!").save() dummies_tenant2_count = DummyModel.objects.count() # we should be back to tenant1's path, test what we have self.assertEqual(DummyModel.objects.count(), dummies_tenant1_count) # switch back to tenant2's path with tenant_context(tenant2): self.assertEqual(DummyModel.objects.count(), dummies_tenant2_count)
def test_switching_search_path(self): tenant1 = Tenant(domain_url='something.test.com', schema_name='tenant1') tenant1.save(verbosity=BaseTestCase.get_verbosity()) connection.set_schema_to_public() tenant2 = Tenant(domain_url='example.com', schema_name='tenant2') tenant2.save(verbosity=BaseTestCase.get_verbosity()) # go to tenant1's path connection.set_tenant(tenant1) # add some data, 2 DummyModels for tenant1 DummyModel(name="Schemas are").save() DummyModel(name="awesome!").save() # switch temporarily to tenant2's path with tenant_context(tenant2): # add some data, 3 DummyModels for tenant2 DummyModel(name="Man,").save() DummyModel(name="testing").save() DummyModel(name="is great!").save() # we should be back to tenant1's path, test what we have self.assertEqual(2, DummyModel.objects.count()) # switch back to tenant2's path with tenant_context(tenant2): self.assertEqual(3, DummyModel.objects.count())
class RoutesTestCase(BaseTestCase): @classmethod def setUpClass(cls): super(RoutesTestCase, cls).setUpClass() settings.SHARED_APPS = ('tenant_schemas', ) settings.TENANT_APPS = ('dts_test_app', 'django.contrib.contenttypes', 'django.contrib.auth', ) settings.INSTALLED_APPS = settings.SHARED_APPS + settings.TENANT_APPS cls.sync_shared() cls.public_tenant = Tenant(domain_url='test.com', schema_name=get_public_schema_name()) cls.public_tenant.save(verbosity=BaseTestCase.get_verbosity()) def setUp(self): super(RoutesTestCase, self).setUp() self.factory = RequestFactory() self.tm = TenantMiddleware() self.tenant_domain = 'tenant.test.com' self.tenant = Tenant(domain_url=self.tenant_domain, schema_name='test') self.tenant.save(verbosity=BaseTestCase.get_verbosity()) def test_tenant_routing(self): """ Request path should not be altered. """ request_url = '/any/request/' request = self.factory.get('/any/request/', HTTP_HOST=self.tenant_domain) self.tm.process_request(request) self.assertEquals(request.path_info, request_url) # request.tenant should also have been set self.assertEquals(request.tenant, self.tenant) def test_public_schema_routing(self): """ Request path should not be altered. """ request_url = '/any/request/' request = self.factory.get('/any/request/', HTTP_HOST=self.public_tenant.domain_url) self.tm.process_request(request) self.assertEquals(request.path_info, request_url) # request.tenant should also have been set self.assertEquals(request.tenant, self.public_tenant)
def setUp(self): super(CeleryTasksTests, self).setUp() self.tenant1 = Tenant(domain_url='test1', schema_name='test1') self.tenant1.save() self.tenant2 = Tenant(domain_url='test2', schema_name='test2') self.tenant2.save() connection.set_tenant(self.tenant1) self.dummy1 = DummyModel.objects.create(name='test1') connection.set_tenant(self.tenant2) self.dummy2 = DummyModel.objects.create(name='test2') connection.set_schema_to_public()
def test_command(self): """ Tests that tenant_command is capable of wrapping commands and its parameters. """ settings.SHARED_APPS = ( "tenant_schemas", "django.contrib.contenttypes", ) settings.TENANT_APPS = () settings.INSTALLED_APPS = settings.SHARED_APPS + settings.TENANT_APPS self.sync_shared() Tenant( domain_url="localhost", schema_name="public").save(verbosity=BaseTestCase.get_verbosity()) out = StringIO() tenant_command.Command().handle( "dumpdata", get_public_schema_name(), "tenant_schemas", natural_foreign=True, stdout=out, ) self.assertJSONEqual( out.getvalue(), [{ "fields": { "domain_url": "localhost", "schema_name": "public" }, "model": "tenant_schemas.tenant", "pk": 1, }], )
def test_command(self): """ Tests that tenant_command is capable of wrapping commands and its parameters. """ settings.SHARED_APPS = ( 'tenant_schemas', 'django.contrib.contenttypes', ) settings.TENANT_APPS = () settings.INSTALLED_APPS = settings.SHARED_APPS + settings.TENANT_APPS self.sync_shared() Tenant( domain_url='localhost', schema_name='public').save(verbosity=BaseTestCase.get_verbosity()) out = StringIO() call_command('tenant_command', args=('dumpdata', 'tenant_schemas'), natural_foreign=True, schema_name=get_public_schema_name(), stdout=out) self.assertEqual( json.loads( '[{"fields": {"domain_url": "localhost", "schema_name": "public"}, ' '"model": "tenant_schemas.tenant", "pk": 1}]'), json.loads(out.getvalue()))
class RoutesTestCase(TestCase): def setUp(self): self.factory = RequestFactory() self.tm = TenantMiddleware() # settings needs some patching settings.TENANT_MODEL = 'tenant_schemas.Tenant' settings.TENANT_URL_TOKEN = '/tenant' # add the public tenant self.public_tenant_domain = 'test.com' self.public_tenant = Tenant(domain_url=self.public_tenant_domain, schema_name='public') self.public_tenant.save() # add a test tenant self.tenant_domain = 'tenant.test.com' self.tenant = Tenant(domain_url=self.tenant_domain, schema_name='test') self.tenant.save() def tearDown(self): Tenant.objects.all().delete() def test_tenant_routing(self): """ request path should get prepended with TENANT_URL_TOKEN """ request_url = '/any/request/' request = self.factory.get('/any/request/', HTTP_HOST=self.tenant_domain) self.tm.process_request(request) self.assertEquals(request.path_info, settings.TENANT_URL_TOKEN + request_url) # request.tenant should also have been set self.assertEquals(request.tenant, self.tenant) def test_public_schema_routing(self): """ request path should not be altered, tenant should be the public one """ request_url = '/any/request/' request = self.factory.get('/any/request/', HTTP_HOST=self.public_tenant_domain) self.tm.process_request(request) self.assertEquals(request.path_info, request_url) # request.tenant should also have been set self.assertEquals(request.tenant, self.public_tenant)
def setUp(self): self.factory = RequestFactory() self.tm = TenantMiddleware() # settings needs some patching settings.TENANT_MODEL = 'tenant_schemas.Tenant' # add the public tenant self.public_tenant_domain = 'test.com' self.public_tenant = Tenant(domain_url=self.public_tenant_domain, schema_name='public') self.public_tenant.save() # add a test tenant self.tenant_domain = 'tenant.test.com' self.tenant = Tenant(domain_url=self.tenant_domain, schema_name='test') self.tenant.save()
def setUp(self): super(RoutesTestCase, self).setUp() self.factory = RequestFactory() self.tm = TenantMiddleware() self.tenant_domain = 'tenant.test.com' self.tenant = Tenant(domain_url=self.tenant_domain, schema_name='test') self.tenant.save()
def test_tenant_apps_does_not_sync_shared_apps(self): """ Tests that if an app is in TENANT_APPS, it does not get synced to the public schema. """ settings.SHARED_APPS = ('tenant_schemas', 'django.contrib.auth', 'django.contrib.contenttypes', ) settings.TENANT_APPS = ('django.contrib.sessions', ) # 1 table settings.INSTALLED_APPS = settings.SHARED_APPS + settings.TENANT_APPS self.sync_shared() tenant = Tenant(domain_url='arbitrary.test.com', schema_name='test') tenant.save() tenant_tables = self.get_tables_list_in_schema(tenant.schema_name) self.assertEqual(1+self.MIGRATION_TABLE_SIZE, len(tenant_tables)) self.assertIn('django_session', tenant_tables)
def setUp(self): self.factory = RequestFactory() self.tm = TenantMiddleware() # settings needs some patching settings.TENANT_MODEL = 'tenant_schemas.Tenant' settings.PUBLIC_SCHEMA_URL_TOKEN = '/public' # add the public tenant self.public_tenant_domain = 'test.com' self.public_tenant = Tenant(domain_url=self.public_tenant_domain, schema_name='public') self.public_tenant.save() # add a test tenant self.tenant_domain = 'tenant.test.com' self.tenant = Tenant(domain_url=self.tenant_domain, schema_name='test') self.tenant.save()
def setUpClass(cls): super(TenantDataAndSettingsTest, cls).setUpClass() settings.SHARED_APPS = ('tenant_schemas', ) settings.TENANT_APPS = ('dts_test_app', 'django.contrib.contenttypes', 'django.contrib.auth', ) settings.INSTALLED_APPS = settings.SHARED_APPS + settings.TENANT_APPS cls.sync_shared() Tenant(domain_url='test.com', schema_name=get_public_schema_name()).save()
def test_auto_drop_schema(self): """ When deleting a tenant with auto_drop_schema=True, it should delete the schema associated with the tenant. """ self.assertFalse(schema_exists('auto_drop_tenant')) Tenant.auto_drop_schema = True tenant = Tenant(domain_url='something.test.com', schema_name='auto_drop_tenant') tenant.save(verbosity=BaseTestCase.get_verbosity()) self.assertTrue(schema_exists(tenant.schema_name)) cursor = connection.cursor() # Force pending trigger events to be executed cursor.execute('SET CONSTRAINTS ALL IMMEDIATE') tenant.delete() self.assertFalse(schema_exists(tenant.schema_name)) Tenant.auto_drop_schema = False
def test_tenant_apps_does_not_sync_shared_apps(self): """ Tests that if an app is in TENANT_APPS, it does not get synced to the public schema. """ settings.SHARED_APPS = ( "tenant_schemas", "django.contrib.auth", "django.contrib.contenttypes", ) settings.TENANT_APPS = ("django.contrib.sessions", ) # 1 table settings.INSTALLED_APPS = settings.SHARED_APPS + settings.TENANT_APPS self.sync_shared() tenant = Tenant(domain_url="arbitrary.test.com", schema_name="test") tenant.save(verbosity=BaseTestCase.get_verbosity()) tenant_tables = self.get_tables_list_in_schema(tenant.schema_name) self.assertEqual(1 + self.MIGRATION_TABLE_SIZE, len(tenant_tables)) self.assertIn("django_session", tenant_tables)
def test_content_types_is_not_mandatory(self): """ Tests that even if content types is in SHARED_APPS, it's not required in TENANT_APPS. """ settings.SHARED_APPS = ('tenant_schemas', # 2 tables 'django.contrib.contenttypes', ) # 1 table settings.TENANT_APPS = ('django.contrib.sessions', ) # 1 table settings.INSTALLED_APPS = settings.SHARED_APPS + settings.TENANT_APPS self.sync_shared() tenant = Tenant(domain_url='something.test.com', schema_name='test') tenant.save() shared_tables = self.get_tables_list_in_schema(get_public_schema_name()) tenant_tables = self.get_tables_list_in_schema(tenant.schema_name) self.assertEqual(2+1+self.MIGRATION_TABLE_SIZE, len(shared_tables)) self.assertIn('django_session', tenant_tables) self.assertEqual(1+self.MIGRATION_TABLE_SIZE, len(tenant_tables)) self.assertIn('django_session', tenant_tables)
def setUpClass(cls): super(RoutesTestCase, cls).setUpClass() settings.SHARED_APPS = ('tenant_schemas', ) settings.TENANT_APPS = ('dts_test_app', 'django.contrib.contenttypes', 'django.contrib.auth', ) settings.INSTALLED_APPS = settings.SHARED_APPS + settings.TENANT_APPS cls.sync_shared() cls.public_tenant = Tenant(domain_url='test.com', schema_name=get_public_schema_name()) cls.public_tenant.save(verbosity=BaseTestCase.get_verbosity())
def test_tenant_schema_creation_in_specified_db(self): """ When saving a tenant using a db, its schema should be created in that db """ db = random.choice(get_all_dbs()) tenant = Tenant(domain_url='something1.test.com', schema_name='test1') tenant.save( verbosity=BaseTestCase.get_verbosity(), using=db) for d in get_all_dbs(): if d == db: self.assertTrue(schema_exists( tenant.schema_name, db=d)) else: self.assertFalse(schema_exists( tenant.schema_name, db=d))
def test_tenant_apps_and_shared_apps_can_have_the_same_apps(self): """ Tests that both SHARED_APPS and TENANT_APPS can have apps in common. In this case they should get synced to both tenant and public schemas. """ settings.SHARED_APPS = ('tenant_schemas', # 2 tables 'django.contrib.auth', # 6 tables 'django.contrib.contenttypes', # 1 table 'django.contrib.sessions', ) # 1 table settings.TENANT_APPS = ('django.contrib.sessions', ) # 1 table settings.INSTALLED_APPS = settings.SHARED_APPS + settings.TENANT_APPS self.sync_shared() tenant = Tenant(domain_url='arbitrary.test.com', schema_name='test') tenant.save() shared_tables = self.get_tables_list_in_schema(get_public_schema_name()) tenant_tables = self.get_tables_list_in_schema(tenant.schema_name) self.assertEqual(2+6+1+1+self.MIGRATION_TABLE_SIZE, len(shared_tables)) self.assertIn('django_session', shared_tables) self.assertEqual(1+self.MIGRATION_TABLE_SIZE, len(tenant_tables)) self.assertIn('django_session', tenant_tables)
def test_switching_search_path(self): dummies_tenant1_count, dummies_tenant2_count = 0, 0 tenant1 = Tenant(domain_url='test.com', schema_name='tenant1') tenant1.save() tenant2 = Tenant(domain_url='example.com', schema_name='tenant2') tenant2.save() # go to tenant1's path connection.set_tenant(tenant1) # add some data DummyModel(name="Schemas are").save() DummyModel(name="awesome!").save() dummies_tenant1_count = DummyModel.objects.count() # switch temporarily to tenant2's path with tenant_context(tenant2): # add some data DummyModel(name="Man,").save() DummyModel(name="testing").save() DummyModel(name="is great!").save() dummies_tenant2_count = DummyModel.objects.count() # we should be back to tenant1's path, test what we have self.assertEqual(DummyModel.objects.count(), dummies_tenant1_count) # switch back to tenant2's path with tenant_context(tenant2): self.assertEqual(DummyModel.objects.count(), dummies_tenant2_count)
def test_switching_search_path(self): tenant1 = Tenant(domain_url='something.test.com', schema_name='tenant1') tenant1.save() connection.set_schema_to_public() tenant2 = Tenant(domain_url='example.com', schema_name='tenant2') tenant2.save() # go to tenant1's path connection.set_tenant(tenant1) # add some data, 2 DummyModels for tenant1 DummyModel(name="Schemas are").save() DummyModel(name="awesome!").save() # switch temporarily to tenant2's path with tenant_context(tenant2): # add some data, 3 DummyModels for tenant2 DummyModel(name="Man,").save() DummyModel(name="testing").save() DummyModel(name="is great!").save() # we should be back to tenant1's path, test what we have self.assertEqual(2, DummyModel.objects.count()) # switch back to tenant2's path with tenant_context(tenant2): self.assertEqual(3, DummyModel.objects.count())
def setUpClass(cls): settings.SHARED_APPS = ('tenant_schemas', ) settings.TENANT_APPS = ('dts_test_app', 'django.contrib.contenttypes', 'django.contrib.auth', ) settings.INSTALLED_APPS = settings.SHARED_APPS + settings.TENANT_APPS super(MultiDBTenantDataAndSettingsTest, cls).setUpClass() for db in get_all_dbs(): cls.sync_shared(db=db) Tenant(domain_url='test.com', schema_name=get_public_schema_name()).save( verbosity=cls.get_verbosity(), using=db )
def setUpClass(cls): super(TenantDataAndSettingsTest, cls).setUpClass() settings.SHARED_APPS = ("tenant_schemas", ) settings.TENANT_APPS = ( "dts_test_app", "django.contrib.contenttypes", "django.contrib.auth", ) settings.INSTALLED_APPS = settings.SHARED_APPS + settings.TENANT_APPS cls.sync_shared() Tenant(domain_url="test.com", schema_name=get_public_schema_name()).save( verbosity=cls.get_verbosity())
class RoutesTestCase(BaseTestCase): def setUp(self): super(RoutesTestCase, self).setUp() self.factory = RequestFactory() self.tm = TenantMiddleware() self.tenant_domain = 'tenant.test.com' self.tenant = Tenant(domain_url=self.tenant_domain, schema_name='test') self.tenant.save() def test_tenant_routing(self): """ request path should not be altered """ request_url = '/any/request/' request = self.factory.get('/any/request/', HTTP_HOST=self.tenant_domain) self.tm.process_request(request) self.assertEquals(request.path_info, request_url) # request.tenant should also have been set self.assertEquals(request.tenant, self.tenant) def test_public_schema_routing(self): """ request path should not be altered """ request_url = '/any/request/' request = self.factory.get('/any/request/', HTTP_HOST=self.public_tenant_domain) self.tm.process_request(request) self.assertEquals(request.path_info, request_url) # request.tenant should also have been set self.assertEquals(request.tenant, self.public_tenant)
def test_edit_tenant(self): """ when editing an existing tenant, all data should be kept """ tenant = Tenant(domain_url='test.com', schema_name='test') tenant.save() # go to tenant's path connection.set_tenant(tenant) # add some data DummyModel(name="Schemas are").save() DummyModel(name="awesome!").save() # edit tenant tenant.domain_url = 'example.com' tenant.save() # test if data is still there self.assertEquals(DummyModel.objects.count(), 2)
def test_sync_tenant(self): """ When editing an existing tenant, all data should be kept. """ tenant = Tenant(domain_url='something.test.com', schema_name='test') tenant.save(verbosity=BaseTestCase.get_verbosity()) # go to tenant's path connection.set_tenant(tenant) # add some data DummyModel(name="Schemas are").save() DummyModel(name="awesome!").save() # edit tenant connection.set_schema_to_public() tenant.domain_url = 'example.com' tenant.save(verbosity=BaseTestCase.get_verbosity()) connection.set_tenant(tenant) # test if data is still there self.assertEqual(DummyModel.objects.count(), 2)
def test_sync_tenant(self): """ When editing an existing tenant, all data should be kept. """ tenant = Tenant(domain_url='something.test.com', schema_name='test') tenant.save(verbosity=BaseTestCase.get_verbosity()) # go to tenant's path connection.set_tenant(tenant) # add some data DummyModel(name="Schemas are").save() DummyModel(name="awesome!").save() # edit tenant connection.set_schema_to_public() tenant.domain_url = 'example.com' tenant.save(verbosity=BaseTestCase.get_verbosity()) connection.set_tenant(tenant) # test if data is still there self.assertEquals(DummyModel.objects.count(), 2)
class TenantTestCase(TransactionTestCase): @classmethod def setUpClass(cls): settings.TENANT_APPS = ( 'tenant_schemas', 'django.contrib.contenttypes', 'django.contrib.auth', ) def setUp(self): # settings needs some patching settings.TENANT_MODEL = 'tenant_schemas.Tenant' # add the public tenant self.public_tenant_domain = 'test.com' self.public_tenant = Tenant(domain_url=self.public_tenant_domain, schema_name='public') self.public_tenant.save() connection.set_schema_to_public() def tearDown(self): """ Delete all tenant schemas. Tenant schema are not deleted automatically by django. """ connection.set_schema_to_public() do_not_delete = [get_public_schema_name(), 'information_schema'] cursor = connection.cursor() # Use information_schema.schemata instead of pg_catalog.pg_namespace in # utils.schema_exists, so that we only "see" schemas that we own cursor.execute('SELECT schema_name FROM information_schema.schemata') for row in cursor.fetchall(): if not row[0].startswith('pg_') and row[0] not in do_not_delete: print("Deleting schema %s" % row[0]) cursor.execute('DROP SCHEMA %s CASCADE' % row[0]) Tenant.objects.all().delete() NonAutoSyncTenant.objects.all().delete() def test_tenant_schema_is_created(self): """ when saving a tenant, it's schema should be created """ tenant = Tenant(domain_url='something.test.com', schema_name='test') tenant.save() self.assertTrue(schema_exists(tenant.schema_name)) def test_non_auto_sync_tenant(self): """ when saving a tenant that has the flag auto_create_schema as False, the schema should not be created when saving the tenant """ self.assertFalse(schema_exists('non_auto_sync_tenant')) tenant = NonAutoSyncTenant(domain_url='something.test.com', schema_name='test') tenant.save() self.assertFalse(schema_exists(tenant.schema_name)) def test_sync_tenant(self): """ when editing an existing tenant, all data should be kept """ tenant = Tenant(domain_url='something.test.com', schema_name='test') tenant.save() # go to tenant's path connection.set_tenant(tenant) # add some data DummyModel(name="Schemas are").save() DummyModel(name="awesome!").save() # edit tenant connection.set_schema_to_public() tenant.domain_url = 'example.com' tenant.save() connection.set_tenant(tenant) # test if data is still there self.assertEquals(DummyModel.objects.count(), 2) def test_switching_search_path(self): dummies_tenant1_count, dummies_tenant2_count = 0, 0 tenant1 = Tenant(domain_url='something.test.com', schema_name='tenant1') tenant1.save() connection.set_schema_to_public() tenant2 = Tenant(domain_url='example.com', schema_name='tenant2') tenant2.save() # go to tenant1's path connection.set_tenant(tenant1) # add some data DummyModel(name="Schemas are").save() DummyModel(name="awesome!").save() dummies_tenant1_count = DummyModel.objects.count() # switch temporarily to tenant2's path with tenant_context(tenant2): # add some data DummyModel(name="Man,").save() DummyModel(name="testing").save() DummyModel(name="is great!").save() dummies_tenant2_count = DummyModel.objects.count() # we should be back to tenant1's path, test what we have self.assertEqual(DummyModel.objects.count(), dummies_tenant1_count) # switch back to tenant2's path with tenant_context(tenant2): self.assertEqual(DummyModel.objects.count(), dummies_tenant2_count) def test_switching_tenant_without_previous_tenant(self): tenant = Tenant(domain_url='something.test.com', schema_name='test') tenant.save() connection.tenant = None with tenant_context(tenant): DummyModel(name="No exception please").save() connection.tenant = None with schema_context(tenant.schema_name): DummyModel(name="Survived it!").save()
class CeleryTasksTests(BaseTestCase): def setUp(self): super(CeleryTasksTests, self).setUp() self.tenant1 = Tenant(domain_url='test1', schema_name='test1') self.tenant1.save() self.tenant2 = Tenant(domain_url='test2', schema_name='test2') self.tenant2.save() connection.set_tenant(self.tenant1) self.dummy1 = DummyModel.objects.create(name='test1') connection.set_tenant(self.tenant2) self.dummy2 = DummyModel.objects.create(name='test2') connection.set_schema_to_public() def test_basic_model_update(self): # We should be in public schema where dummies don't exist. for dummy in self.dummy1, self.dummy2: # Test both async and local versions. with self.assertRaises(DummyModel.DoesNotExist): update_task.apply_async(args=(dummy.pk, 'updated-name')) with self.assertRaises(DummyModel.DoesNotExist): update_task.apply(args=(dummy.pk, 'updated-name')) connection.set_tenant(self.tenant1) update_task.apply_async(args=(self.dummy1.pk, 'updated-name')) self.assertEqual(connection.schema_name, self.tenant1.schema_name) # The task restores the schema from before running the task, so we are # using the `tenant1` tenant now. model_count = DummyModel.objects.filter(name='updated-name').count() self.assertEqual(model_count, 1) connection.set_tenant(self.tenant2) model_count = DummyModel.objects.filter(name='updated-name').count() self.assertEqual(model_count, 0) def test_task_retry(self): # Schema name should persist through retry attempts. connection.set_tenant(self.tenant1) update_retry_task.apply_async(args=(self.dummy1.pk, 'updated-name')) model_count = DummyModel.objects.filter(name='updated-name').count() self.assertEqual(model_count, 1) def test_restoring_schema_name(self): update_task.apply_async( args=(self.dummy1.pk, 'updated-name'), kwargs={'_schema_name': self.tenant1.schema_name}) self.assertEqual(connection.schema_name, get_public_schema_name()) connection.set_tenant(self.tenant1) update_task.apply_async( args=(self.dummy2.pk, 'updated-name'), kwargs={'_schema_name': self.tenant2.schema_name}) self.assertEqual(connection.schema_name, self.tenant1.schema_name) connection.set_tenant(self.tenant2) # The model does not exist in the public schema. with self.assertRaises(DummyModel.DoesNotExist): update_task.apply_async( args=(self.dummy2.pk, 'updated-name'), kwargs={'_schema_name': get_public_schema_name()}) self.assertEqual(connection.schema_name, self.tenant2.schema_name)
class RoutesTestCase(TransactionTestCase): @classmethod def setUpClass(cls): settings.TENANT_APPS = ('tenant_schemas', 'django.contrib.contenttypes', 'django.contrib.auth', ) def setUp(self): self.factory = RequestFactory() self.tm = TenantMiddleware() # settings needs some patching settings.TENANT_MODEL = 'tenant_schemas.Tenant' # add the public tenant self.public_tenant_domain = 'test.com' self.public_tenant = Tenant(domain_url=self.public_tenant_domain, schema_name='public') self.public_tenant.save() # add a test tenant self.tenant_domain = 'tenant.test.com' self.tenant = Tenant(domain_url=self.tenant_domain, schema_name='test') self.tenant.save() def tearDown(self): """ Delete all tenant schemas. Tenant schema are not deleted automatically by django. """ connection.set_schema_to_public() do_not_delete = [get_public_schema_name(), 'information_schema'] cursor = connection.cursor() # Use information_schema.schemata instead of pg_catalog.pg_namespace in # utils.schema_exists, so that we only "see" schemas that we own cursor.execute('SELECT schema_name FROM information_schema.schemata') for row in cursor.fetchall(): if not row[0].startswith('pg_') and row[0] not in do_not_delete: print("Deleting schema %s" % row[0]) cursor.execute('DROP SCHEMA %s CASCADE' % row[0]) Tenant.objects.all().delete() def test_tenant_routing(self): """ request path should not be altered """ request_url = '/any/request/' request = self.factory.get('/any/request/', HTTP_HOST=self.tenant_domain) self.tm.process_request(request) self.assertEquals(request.path_info, request_url) # request.tenant should also have been set self.assertEquals(request.tenant, self.tenant) def test_public_schema_routing(self): """ request path should not be altered """ request_url = '/any/request/' request = self.factory.get('/any/request/', HTTP_HOST=self.public_tenant_domain) self.tm.process_request(request) self.assertEquals(request.path_info, request_url) # request.tenant should also have been set self.assertEquals(request.tenant, self.public_tenant)
class RoutesTestCase(BaseTestCase): @classmethod def setUpClass(cls): super(RoutesTestCase, cls).setUpClass() settings.SHARED_APPS = ('tenant_schemas', ) settings.TENANT_APPS = ('dts_test_app', 'django.contrib.contenttypes', 'django.contrib.auth', ) settings.INSTALLED_APPS = settings.SHARED_APPS + settings.TENANT_APPS cls.sync_shared() cls.public_tenant = Tenant(domain_url='test.com', schema_name=get_public_schema_name()) cls.public_tenant.save(verbosity=BaseTestCase.get_verbosity()) def setUp(self): super(RoutesTestCase, self).setUp() self.factory = RequestFactory() self.tm = TenantMiddleware() self.dtm = DefaultTenantMiddleware() self.tenant_domain = 'tenant.test.com' self.tenant = Tenant(domain_url=self.tenant_domain, schema_name='test') self.tenant.save(verbosity=BaseTestCase.get_verbosity()) self.non_existent_domain = 'no-tenant.test.com' self.non_existent_tenant = Tenant(domain_url=self.non_existent_domain, schema_name='no-tenant') self.url = '/any/path/' def test_tenant_routing(self): request = self.factory.get( self.url, HTTP_HOST=self.tenant_domain) self.tm.process_request(request) self.assertEquals(request.path_info, self.url) self.assertEquals(request.tenant, self.tenant) def test_public_schema_routing(self): request = self.factory.get( self.url, HTTP_HOST=self.public_tenant.domain_url) self.tm.process_request(request) self.assertEquals(request.path_info, self.url) self.assertEquals(request.tenant, self.public_tenant) def test_non_existent_tenant_routing(self): """Raise 404 for unrecognised hostnames.""" request = self.factory.get( self.url, HTTP_HOST=self.non_existent_tenant.domain_url) self.assertRaises(Http404, self.tm.process_request, request) def test_non_existent_tenant_to_default_schema_routing(self): """Route unrecognised hostnames to the 'public' tenant.""" request = self.factory.get( self.url, HTTP_HOST=self.non_existent_tenant.domain_url) self.dtm.process_request(request) self.assertEquals(request.path_info, self.url) self.assertEquals(request.tenant, self.public_tenant) def test_non_existent_tenant_custom_middleware(self): """Route unrecognised hostnames to the 'test' tenant.""" dtm = TestDefaultTenantMiddleware() request = self.factory.get( self.url, HTTP_HOST=self.non_existent_tenant.domain_url) dtm.process_request(request) self.assertEquals(request.path_info, self.url) self.assertEquals(request.tenant, self.tenant) def test_non_existent_tenant_and_default_custom_middleware(self): """Route unrecognised hostnames to the 'missing' tenant.""" dtm = MissingDefaultTenantMiddleware() request = self.factory.get( self.url, HTTP_HOST=self.non_existent_tenant.domain_url) self.assertRaises(DisallowedHost, dtm.process_request, request)
class CeleryTasksTests(BaseTestCase): def setUp(self): super(CeleryTasksTests, self).setUp() self.tenant1 = Tenant(domain_url='test1', schema_name='test1') self.tenant1.save() self.tenant2 = Tenant(domain_url='test2', schema_name='test2') self.tenant2.save() connection.set_tenant(self.tenant1) self.dummy1 = DummyModel.objects.create(name='test1') connection.set_tenant(self.tenant2) self.dummy2 = DummyModel.objects.create(name='test2') connection.set_schema_to_public() def test_basic_model_update(self): # We should be in public schema where dummies don't exist. for dummy in self.dummy1, self.dummy2: # Test both async and local versions. with self.assertRaises(DummyModel.DoesNotExist): update_task.apply_async(args=(dummy.pk, 'updated-name')) with self.assertRaises(DummyModel.DoesNotExist): update_task.apply(args=(dummy.pk, 'updated-name')) connection.set_tenant(self.tenant1) update_task.apply_async(args=(self.dummy1.pk, 'updated-name')) self.assertEqual(connection.schema_name, self.tenant1.schema_name) # The task restores the schema from before running the task, so we are # using the `tenant1` tenant now. model_count = DummyModel.objects.filter(name='updated-name').count() self.assertEqual(model_count, 1) connection.set_tenant(self.tenant2) model_count = DummyModel.objects.filter(name='updated-name').count() self.assertEqual(model_count, 0) def test_task_retry(self): # Schema name should persist through retry attempts. connection.set_tenant(self.tenant1) update_retry_task.apply_async(args=(self.dummy1.pk, 'updated-name')) model_count = DummyModel.objects.filter(name='updated-name').count() self.assertEqual(model_count, 1) def test_restoring_schema_name(self): update_task.apply_async( args=(self.dummy1.pk, 'updated-name'), kwargs={'_schema_name': self.tenant1.schema_name} ) self.assertEqual(connection.schema_name, get_public_schema_name()) connection.set_tenant(self.tenant1) update_task.apply_async( args=(self.dummy2.pk, 'updated-name'), kwargs={'_schema_name': self.tenant2.schema_name} ) self.assertEqual(connection.schema_name, self.tenant1.schema_name) connection.set_tenant(self.tenant2) # The model does not exist in the public schema. with self.assertRaises(DummyModel.DoesNotExist): update_task.apply_async( args=(self.dummy2.pk, 'updated-name'), kwargs={'_schema_name': get_public_schema_name()} ) self.assertEqual(connection.schema_name, self.tenant2.schema_name)
class TenantTestCase(TransactionTestCase): @classmethod def setUpClass(cls): settings.TENANT_APPS = ('tenant_schemas', 'django.contrib.contenttypes', 'django.contrib.auth', ) def setUp(self): # settings needs some patching settings.TENANT_MODEL = 'tenant_schemas.Tenant' # add the public tenant self.public_tenant_domain = 'test.com' self.public_tenant = Tenant(domain_url=self.public_tenant_domain, schema_name='public') self.public_tenant.save() connection.set_schema_to_public() def tearDown(self): """ Delete all tenant schemas. Tenant schema are not deleted automatically by django. """ connection.set_schema_to_public() do_not_delete = [get_public_schema_name(), 'information_schema'] cursor = connection.cursor() # Use information_schema.schemata instead of pg_catalog.pg_namespace in # utils.schema_exists, so that we only "see" schemas that we own cursor.execute('SELECT schema_name FROM information_schema.schemata') for row in cursor.fetchall(): if not row[0].startswith('pg_') and row[0] not in do_not_delete: print("Deleting schema %s" % row[0]) cursor.execute('DROP SCHEMA %s CASCADE' % row[0]) Tenant.objects.all().delete() NonAutoSyncTenant.objects.all().delete() def test_tenant_schema_is_created(self): """ when saving a tenant, it's schema should be created """ tenant = Tenant(domain_url='something.test.com', schema_name='test') tenant.save() self.assertTrue(schema_exists(tenant.schema_name)) def test_non_auto_sync_tenant(self): """ when saving a tenant that has the flag auto_create_schema as False, the schema should not be created when saving the tenant """ self.assertFalse(schema_exists('non_auto_sync_tenant')) tenant = NonAutoSyncTenant(domain_url='something.test.com', schema_name='test') tenant.save() self.assertFalse(schema_exists(tenant.schema_name)) def test_sync_tenant(self): """ when editing an existing tenant, all data should be kept """ tenant = Tenant(domain_url='something.test.com', schema_name='test') tenant.save() # go to tenant's path connection.set_tenant(tenant) # add some data DummyModel(name="Schemas are").save() DummyModel(name="awesome!").save() # edit tenant connection.set_schema_to_public() tenant.domain_url = 'example.com' tenant.save() connection.set_tenant(tenant) # test if data is still there self.assertEquals(DummyModel.objects.count(), 2) def test_switching_search_path(self): dummies_tenant1_count, dummies_tenant2_count = 0, 0 tenant1 = Tenant(domain_url='something.test.com', schema_name='tenant1') tenant1.save() connection.set_schema_to_public() tenant2 = Tenant(domain_url='example.com', schema_name='tenant2') tenant2.save() # go to tenant1's path connection.set_tenant(tenant1) # add some data DummyModel(name="Schemas are").save() DummyModel(name="awesome!").save() dummies_tenant1_count = DummyModel.objects.count() # switch temporarily to tenant2's path with tenant_context(tenant2): # add some data DummyModel(name="Man,").save() DummyModel(name="testing").save() DummyModel(name="is great!").save() dummies_tenant2_count = DummyModel.objects.count() # we should be back to tenant1's path, test what we have self.assertEqual(DummyModel.objects.count(), dummies_tenant1_count) # switch back to tenant2's path with tenant_context(tenant2): self.assertEqual(DummyModel.objects.count(), dummies_tenant2_count)
class RoutesTestCase(TransactionTestCase): @classmethod def setUpClass(cls): settings.TENANT_APPS = ( 'tenant_schemas', 'django.contrib.contenttypes', 'django.contrib.auth', ) def setUp(self): self.factory = RequestFactory() self.tm = TenantMiddleware() # settings needs some patching settings.TENANT_MODEL = 'tenant_schemas.Tenant' # add the public tenant self.public_tenant_domain = 'test.com' self.public_tenant = Tenant(domain_url=self.public_tenant_domain, schema_name='public') self.public_tenant.save() # add a test tenant self.tenant_domain = 'tenant.test.com' self.tenant = Tenant(domain_url=self.tenant_domain, schema_name='test') self.tenant.save() def tearDown(self): """ Delete all tenant schemas. Tenant schema are not deleted automatically by django. """ connection.set_schema_to_public() do_not_delete = [get_public_schema_name(), 'information_schema'] cursor = connection.cursor() # Use information_schema.schemata instead of pg_catalog.pg_namespace in # utils.schema_exists, so that we only "see" schemas that we own cursor.execute('SELECT schema_name FROM information_schema.schemata') for row in cursor.fetchall(): if not row[0].startswith('pg_') and row[0] not in do_not_delete: print("Deleting schema %s" % row[0]) cursor.execute('DROP SCHEMA %s CASCADE' % row[0]) Tenant.objects.all().delete() def test_tenant_routing(self): """ request path should not be altered """ request_url = '/any/request/' request = self.factory.get('/any/request/', HTTP_HOST=self.tenant_domain) self.tm.process_request(request) self.assertEquals(request.path_info, request_url) # request.tenant should also have been set self.assertEquals(request.tenant, self.tenant) def test_public_schema_routing(self): """ request path should not be altered """ request_url = '/any/request/' request = self.factory.get('/any/request/', HTTP_HOST=self.public_tenant_domain) self.tm.process_request(request) self.assertEquals(request.path_info, request_url) # request.tenant should also have been set self.assertEquals(request.tenant, self.public_tenant)