class APITest(TestCase): request_factory = RequestFactory() def setUp(self): self.user = User.objects.create(username='******', email='*****@*****.**') self.gargoyle = SwitchManager(Switch, key='key', value='value', instances=True, auto_create=True) self.gargoyle.register(UserConditionSet(User)) self.gargoyle.register(IPAddressConditionSet()) def test_register_unregister_class(self): klass = IPAddressConditionSet registered = self.gargoyle.register(IPAddressConditionSet) assert registered is klass unregistered = self.gargoyle.unregister(klass) assert unregistered unregistered = self.gargoyle.unregister(klass) assert not unregistered def test_register_unregister_instance(self): condition_set = IPAddressConditionSet() registered = self.gargoyle.register(condition_set) assert registered is condition_set unregistered = self.gargoyle.unregister(condition_set) assert unregistered unregistered = self.gargoyle.unregister(condition_set) assert not unregistered def test_builtin_registration(self): assert 'gargoyle.builtins.UserConditionSet(auth.user)' in self.gargoyle._registry assert 'gargoyle.builtins.IPAddressConditionSet' in self.gargoyle._registry assert len(list(self.gargoyle.get_condition_sets())) == 2 def test_user(self): condition_set = 'gargoyle.builtins.UserConditionSet(auth.user)' switch = Switch.objects.create(key='test', status=SELECTIVE) switch = self.gargoyle['test'] switch.add_condition( condition_set=condition_set, field_name='percent', condition='0-50', ) user = User(pk=5) assert self.gargoyle.is_active('test', user) user = User(pk=8771) assert not self.gargoyle.is_active('test', user) switch.add_condition( condition_set=condition_set, field_name='is_staff', condition='1', ) user = User(pk=8771, is_staff=True) assert self.gargoyle.is_active('test', user) user = User(pk=8771, is_superuser=True) assert not self.gargoyle.is_active('test', user) switch.add_condition( condition_set=condition_set, field_name='is_superuser', condition='1', ) user = User(pk=8771, is_superuser=True) assert self.gargoyle.is_active('test', user) # test with request request = self.request_factory.get('/', user=user) assert self.gargoyle.is_active('test', request) # test date joined condition user = User(pk=8771) assert not self.gargoyle.is_active('test', user) switch.add_condition( condition_set=condition_set, field_name='date_joined', condition='2011-07-01', ) user = User(pk=8771, date_joined=datetime.datetime(2011, 7, 2)) assert self.gargoyle.is_active('test', user) user = User(pk=8771, date_joined=datetime.datetime(2012, 7, 2)) assert self.gargoyle.is_active('test', user) user = User(pk=8771, date_joined=datetime.datetime(2011, 6, 2)) assert not self.gargoyle.is_active('test', user) user = User(pk=8771, date_joined=datetime.datetime(2011, 7, 1)) assert self.gargoyle.is_active('test', user) switch.clear_conditions(condition_set=condition_set) switch.add_condition( condition_set=condition_set, field_name='email', condition='*****@*****.**', ) user = User(pk=8771, email="*****@*****.**") assert self.gargoyle.is_active('test', user) user = User(pk=8771, email="*****@*****.**") assert not self.gargoyle.is_active('test', user) user = User(pk=8771) assert not self.gargoyle.is_active('test', user) def test_exclusions(self): condition_set = 'gargoyle.builtins.UserConditionSet(auth.user)' switch = Switch.objects.create(key='test', status=SELECTIVE) switch = self.gargoyle['test'] switch.add_condition( condition_set=condition_set, field_name='is_staff', condition='1', ) switch.add_condition( condition_set=condition_set, field_name='username', condition='foo', ) switch.add_condition( condition_set=condition_set, field_name='username', condition='bar', exclude=True, ) user = User(pk=0, username='******', is_staff=False) assert self.gargoyle.is_active('test', user) user = User(pk=0, username='******', is_staff=True) assert self.gargoyle.is_active('test', user) user = User(pk=0, username='******', is_staff=False) assert not self.gargoyle.is_active('test', user) user = User(pk=0, username='******', is_staff=True) assert not self.gargoyle.is_active('test', user) def test_exclusion_duplicate(self): condition_set = 'gargoyle.builtins.UserConditionSet(auth.user)' switch = Switch.objects.create(key='test', status=SELECTIVE) switch = self.gargoyle['test'] switch.add_condition( condition_set=condition_set, field_name='username', condition='bar', exclude=True, ) switch.add_condition( condition_set=condition_set, field_name='username', condition='bar', exclude=True, ) assert len(switch._switch.value['auth.user']['username']) == 1 def test_exclusion_conflicting(self): condition_set = 'gargoyle.builtins.UserConditionSet(auth.user)' switch = Switch.objects.create(key='test', status=SELECTIVE) switch = self.gargoyle['test'] switch.add_condition( condition_set=condition_set, field_name='username', condition='bar', exclude=True, ) switch.add_condition( condition_set=condition_set, field_name='username', condition='bar', exclude=False, ) assert len(switch._switch.value['auth.user']['username']) == 1 user = User(pk=0, username='******') assert self.gargoyle.is_active('test', user) user = User(pk=0, username='******') assert not self.gargoyle.is_active('test', user) def test_only_exclusions(self): condition_set = 'gargoyle.builtins.UserConditionSet(auth.user)' switch = Switch.objects.create(key='test', status=SELECTIVE) switch = self.gargoyle['test'] # Intent is that this condition is True for all users *except* if the # username == bar switch.add_condition( condition_set=condition_set, field_name='username', condition='bar', exclude=True, ) # username=='foo', so should be active user = User(pk=0, username='******', is_staff=False) assert self.gargoyle.is_active('test', user) # username=='foo', so should be active user = User(pk=0, username='******', is_staff=True) assert self.gargoyle.is_active('test', user) # username=='bar', so should not be active user = User(pk=0, username='******', is_staff=False) assert not self.gargoyle.is_active('test', user) # username=='bar', so should not be active user = User(pk=0, username='******', is_staff=True) assert not self.gargoyle.is_active('test', user) def test_decorator_for_user(self): condition_set = 'gargoyle.builtins.UserConditionSet(auth.user)' switch = Switch.objects.create(key='test', status=DISABLED) switch = self.gargoyle['test'] @switch_is_active('test') def test(request): return True request = self.request_factory.get('/', user=self.user) with pytest.raises(Http404): test(request) switch.status = SELECTIVE switch.save() with pytest.raises(Http404): test(request) switch.add_condition( condition_set=condition_set, field_name='username', condition='foo', ) assert test(request) def test_decorator_for_ip_address(self): condition_set = 'gargoyle.builtins.IPAddressConditionSet' switch = Switch.objects.create(key='test', status=DISABLED) switch = self.gargoyle['test'] @switch_is_active('test') def test(request): return True request = self.request_factory.get('/', REMOTE_ADDR='192.168.1.1') with pytest.raises(Http404): test(request) switch.status = SELECTIVE switch.save() switch.add_condition( condition_set=condition_set, field_name='ip_address', condition='192.168.1.1', ) assert test(request) # add in a second condition, so that removing the first one won't kick # in the "no conditions returns is_active True for selective switches" switch.add_condition( condition_set=condition_set, field_name='ip_address', condition='192.168.1.2', ) switch.remove_condition( condition_set=condition_set, field_name='ip_address', condition='192.168.1.1', ) with pytest.raises(Http404): test(request) switch.add_condition( condition_set=condition_set, field_name='ip_address', condition='192.168.1.1', ) assert test(request) switch.clear_conditions( condition_set=condition_set, field_name='ip_address', ) switch.add_condition( condition_set=condition_set, field_name='percent', condition='50-100', ) assert test(request) switch.clear_conditions(condition_set=condition_set, ) switch.add_condition( condition_set=condition_set, field_name='percent', condition='0-50', ) with pytest.raises(Http404): test(request) def test_decorator_with_redirect(self): Switch.objects.create(key='test', status=DISABLED) request = self.request_factory.get('/', user=self.user) @switch_is_active('test', redirect_to='/foo') def test(request): return HttpResponse() response = test(request) assert response.status_code, 302 assert 'Location' in response assert response['Location'] == '/foo' @switch_is_active('test', redirect_to='gargoyle_test_foo') def test2(request): return HttpResponse() response = test2(request) assert response.status_code, 302 assert 'Location' in response assert response['Location'] == '/foo/' def test_global(self): switch = Switch.objects.create(key='test', status=DISABLED) switch = self.gargoyle['test'] assert not self.gargoyle.is_active('test') assert not self.gargoyle.is_active('test', self.user) switch.status = GLOBAL switch.save() assert self.gargoyle.is_active('test') assert self.gargoyle.is_active('test', self.user) def test_disable(self): switch = Switch.objects.create(key='test') switch = self.gargoyle['test'] switch.status = DISABLED switch.save() assert not self.gargoyle.is_active('test') assert not self.gargoyle.is_active('test', self.user) def test_deletion(self): switch = Switch.objects.create(key='test') switch = self.gargoyle['test'] assert 'test' in self.gargoyle switch.delete() assert 'test' not in self.gargoyle def test_expiration(self): switch = Switch.objects.create(key='test') switch = self.gargoyle['test'] switch.status = DISABLED switch.save() assert not self.gargoyle.is_active('test') Switch.objects.filter(key='test').update(value={}, status=GLOBAL) # cache shouldn't have expired assert not self.gargoyle.is_active('test') cache_key = self.gargoyle.remote_cache_key # in memory cache shouldnt have expired cache.delete(cache_key) assert not self.gargoyle.is_active('test') switch.status, switch.value = GLOBAL, {} # Ensure post save gets sent self.gargoyle._post_save(sender=None, instance=switch, created=False) # any request should expire the in memory cache self.client.get('/') assert self.gargoyle.is_active('test') def test_anonymous_user(self): condition_set = 'gargoyle.builtins.UserConditionSet(auth.user)' switch = Switch.objects.create(key='test') switch = self.gargoyle['test'] switch.status = SELECTIVE switch.save() user = AnonymousUser() assert not self.gargoyle.is_active('test', user) switch.add_condition( condition_set=condition_set, field_name='percent', condition='1-10', ) assert not self.gargoyle.is_active('test', user) switch.clear_conditions(condition_set=condition_set) assert not self.gargoyle.is_active('test', user) switch.add_condition( condition_set=condition_set, field_name='is_anonymous', condition='1', ) assert self.gargoyle.is_active('test', user) switch.add_condition( condition_set=condition_set, field_name='percent', condition='1-10', ) assert self.gargoyle.is_active('test', user) def test_ip_address_internal_ips(self): condition_set = 'gargoyle.builtins.IPAddressConditionSet' Switch.objects.create(key='test', status=SELECTIVE) switch = self.gargoyle['test'] request = self.request_factory.get('/', REMOTE_ADDR='192.168.1.1') assert not self.gargoyle.is_active('test', request) switch.add_condition( condition_set=condition_set, field_name='internal_ip', condition='1', ) with override_settings(INTERNAL_IPS=['192.168.1.1']): assert self.gargoyle.is_active('test', request) assert not self.gargoyle.is_active('test', request) def test_ip_address(self): condition_set = 'gargoyle.builtins.IPAddressConditionSet' switch = Switch.objects.create(key='test', status=SELECTIVE) switch = self.gargoyle['test'] request = self.request_factory.get('/', REMOTE_ADDR='192.168.1.1') assert not self.gargoyle.is_active('test', request) switch.add_condition( condition_set=condition_set, field_name='ip_address', condition='192.168.1.1', ) assert self.gargoyle.is_active('test', request) switch.clear_conditions(condition_set=condition_set) switch.add_condition( condition_set=condition_set, field_name='ip_address', condition='127.0.0.1', ) assert not self.gargoyle.is_active('test', request) switch.clear_conditions(condition_set=condition_set) assert not self.gargoyle.is_active('test', request) switch.add_condition( condition_set=condition_set, field_name='percent', condition='50-100', ) assert self.gargoyle.is_active('test', request) assert self.gargoyle.is_active( 'test', self.request_factory.get('/', REMOTE_ADDR='192.168.1.1')) switch.clear_conditions(condition_set=condition_set) switch.add_condition( condition_set=condition_set, field_name='percent', condition='0-50', ) assert not self.gargoyle.is_active('test', request) assert self.gargoyle.is_active( 'test', self.request_factory.get('/', REMOTE_ADDR='::1')) switch.clear_conditions(condition_set=condition_set) switch.add_condition( condition_set=condition_set, field_name='percent', condition='0-50', ) assert not self.gargoyle.is_active('test', request) def test_to_dict(self): condition_set = 'gargoyle.builtins.IPAddressConditionSet' switch = Switch.objects.create( label='my switch', description='foo bar baz', key='test', status=SELECTIVE, ) switch.add_condition( manager=self.gargoyle, condition_set=condition_set, field_name='ip_address', condition='192.168.1.1', ) result = switch.to_dict(self.gargoyle) assert result['label'] == 'my switch' assert result['status'] == SELECTIVE assert result['description'] == 'foo bar baz' assert result['key'] == 'test' assert len(result['conditions']) == 1 condition = result['conditions'][0] assert condition['id'] == condition_set assert condition['label'] == 'IP Address' assert len(condition['conditions']) == 1 inner_condition = condition['conditions'][0] assert len(inner_condition) == 4 assert inner_condition[0] == 'ip_address' assert inner_condition[1] == '192.168.1.1' assert inner_condition[2] == '192.168.1.1' assert not inner_condition[3] def test_remove_condition(self): condition_set = 'gargoyle.builtins.UserConditionSet(auth.user)' switch = Switch.objects.create( key='test', status=SELECTIVE, ) switch = self.gargoyle['test'] user5 = User(pk=5, email='*****@*****.**') # inactive if selective with no conditions assert not self.gargoyle.is_active('test', user5) user8771 = User(pk=8771, email='*****@*****.**', is_superuser=True) switch.add_condition( condition_set=condition_set, field_name='is_superuser', condition='1', ) assert self.gargoyle.is_active('test', user8771) # No longer is_active for user5 as we have other conditions assert not self.gargoyle.is_active('test', user5) switch.remove_condition( condition_set=condition_set, field_name='is_superuser', condition='1', ) # back to inactive for everyone with no conditions assert not self.gargoyle.is_active('test', user5) assert not self.gargoyle.is_active('test', user8771) def test_add_condition_empty(self): condition_set = 'gargoyle.builtins.UserConditionSet(auth.user)' switch = Switch.objects.create(key='test', status=SELECTIVE) switch = self.gargoyle['test'] user_empty = User(email='') user_non_empty = User(email='*****@*****.**') switch.add_condition( condition_set=condition_set, field_name='email', condition='', ) assert self.gargoyle.is_active('test', user_empty) assert not self.gargoyle.is_active('test', user_non_empty) def test_switch_defaults(self): """Test that defaults pulled from GARGOYLE_SWITCH_DEFAULTS. Requires SwitchManager to use auto_create. """ assert self.gargoyle.is_active('active_by_default') assert not self.gargoyle.is_active('inactive_by_default') assert self.gargoyle['inactive_by_default'].label == 'Default Inactive' assert self.gargoyle['active_by_default'].label == 'Default Active' active_by_default = self.gargoyle['active_by_default'] active_by_default.status = DISABLED active_by_default.save() assert not self.gargoyle.is_active('active_by_default') assert self.gargoyle['selective_by_default'].status == SELECTIVE def test_invalid_condition(self): condition_set = 'gargoyle.builtins.UserConditionSet(auth.user)' switch = Switch.objects.create( key='test', status=SELECTIVE, ) switch = self.gargoyle['test'] user5 = User(pk=5, email='*****@*****.**') # inactive if selective with no conditions assert not self.gargoyle.is_active('test', user5) user8771 = User(pk=8771, email='*****@*****.**', is_superuser=True) switch.add_condition( condition_set=condition_set, field_name='foo', condition='1', ) assert not self.gargoyle.is_active('test', user8771) def test_inheritance(self): condition_set = 'gargoyle.builtins.UserConditionSet(auth.user)' # we need a better API for this (model dict isnt cutting it) switch = Switch.objects.create(key='test', status=SELECTIVE) switch = self.gargoyle['test'] switch.add_condition( condition_set=condition_set, field_name='percent', condition='0-50', ) switch = Switch.objects.create(key='test:child', status=INHERIT) switch = self.gargoyle['test'] user = User(pk=5) assert self.gargoyle.is_active('test:child', user) user = User(pk=8771) assert not self.gargoyle.is_active('test:child', user) switch = self.gargoyle['test'] switch.status = DISABLED user = User(pk=5) assert not self.gargoyle.is_active('test:child', user) user = User(pk=8771) assert not self.gargoyle.is_active('test:child', user) switch = self.gargoyle['test'] switch.status = GLOBAL user = User(pk=5) assert self.gargoyle.is_active('test:child', user) user = User(pk=8771) assert self.gargoyle.is_active('test:child', user) def test_parent_override_child_state(self): Switch.objects.create(key='test', status=DISABLED) Switch.objects.create(key='test:child', status=GLOBAL) assert not self.gargoyle.is_active('test:child') def test_child_state_is_used(self): Switch.objects.create(key='test', status=GLOBAL) Switch.objects.create(key='test:child', status=DISABLED) assert not self.gargoyle.is_active('test:child') def test_parent_override_child_condition(self): condition_set = 'gargoyle.builtins.UserConditionSet(auth.user)' Switch.objects.create(key='test', status=SELECTIVE) parent = self.gargoyle['test'] parent.add_condition( condition_set=condition_set, field_name='username', condition='bob', ) Switch.objects.create(key='test:child', status=GLOBAL) user = User(username='******') assert self.gargoyle.is_active('test:child', user) user = User(username='******') assert not self.gargoyle.is_active('test:child', user) assert not self.gargoyle.is_active('test:child') def test_child_condition_differing_than_parent_loses(self): condition_set = 'gargoyle.builtins.UserConditionSet(auth.user)' Switch.objects.create(key='test', status=SELECTIVE) parent = self.gargoyle['test'] parent.add_condition( condition_set=condition_set, field_name='username', condition='bob', ) Switch.objects.create(key='test:child', status=SELECTIVE) child = self.gargoyle['test:child'] child.add_condition( condition_set=condition_set, field_name='username', condition='joe', ) user = User(username='******') assert not self.gargoyle.is_active('test:child', user) user = User(username='******') assert not self.gargoyle.is_active('test:child', user) user = User(username='******') assert not self.gargoyle.is_active('test:child', user) assert not self.gargoyle.is_active('test:child') def test_child_condition_including_parent_wins(self): condition_set = 'gargoyle.builtins.UserConditionSet(auth.user)' Switch.objects.create(key='test', status=SELECTIVE) parent = self.gargoyle['test'] parent.add_condition( condition_set=condition_set, field_name='username', condition='bob', ) Switch.objects.create(key='test:child', status=SELECTIVE) child = self.gargoyle['test:child'] child.add_condition( condition_set=condition_set, field_name='username', condition='bob', ) child.add_condition( condition_set=condition_set, field_name='username', condition='joe', ) user = User(username='******') assert self.gargoyle.is_active('test:child', user) user = User(username='******') assert not self.gargoyle.is_active('test:child', user) user = User(username='******') assert not self.gargoyle.is_active('test:child', user) assert not self.gargoyle.is_active('test:child')
class APITest(TestCase): urls = 'tests.urls' def setUp(self): self.user = User.objects.create(username='******', email='*****@*****.**') self.gargoyle = SwitchManager(Switch, key='key', value='value', instances=True, auto_create=True) self.gargoyle.register(UserConditionSet(User)) self.gargoyle.register(IPAddressConditionSet()) self.internal_ips = settings.INTERNAL_IPS def tearDown(self): settings.INTERNAL_IPS = self.internal_ips def test_builtin_registration(self): self.assertTrue('gargoyle.builtins.UserConditionSet(auth.user)' in self.gargoyle._registry) self.assertTrue('gargoyle.builtins.IPAddressConditionSet' in self.gargoyle._registry) self.assertEquals(len(list(self.gargoyle.get_condition_sets())), 2, self.gargoyle) def test_user(self): condition_set = 'gargoyle.builtins.UserConditionSet(auth.user)' # we need a better API for this (model dict isnt cutting it) switch = Switch.objects.create( key='test', status=SELECTIVE, ) switch = self.gargoyle['test'] switch.add_condition( condition_set=condition_set, field_name='percent', condition='0-50', ) user = User(pk=5) self.assertTrue(self.gargoyle.is_active('test', user)) user = User(pk=8771) self.assertFalse(self.gargoyle.is_active('test', user)) switch.add_condition( condition_set=condition_set, field_name='is_staff', condition='1', ) user = User(pk=8771, is_staff=True) self.assertTrue(self.gargoyle.is_active('test', user)) user = User(pk=8771, is_superuser=True) self.assertFalse(self.gargoyle.is_active('test', user)) switch.add_condition( condition_set=condition_set, field_name='is_superuser', condition='1', ) user = User(pk=8771, is_superuser=True) self.assertTrue(self.gargoyle.is_active('test', user)) # test with mock request self.assertTrue(self.gargoyle.is_active('test', self.gargoyle.as_request(user=user))) # test date joined condition user = User(pk=8771) self.assertFalse(self.gargoyle.is_active('test', user)) switch.add_condition( condition_set=condition_set, field_name='date_joined', condition='2011-07-01', ) user = User(pk=8771, date_joined=datetime.datetime(2011, 07, 02)) self.assertTrue(self.gargoyle.is_active('test', user)) user = User(pk=8771, date_joined=datetime.datetime(2012, 07, 02)) self.assertTrue(self.gargoyle.is_active('test', user)) user = User(pk=8771, date_joined=datetime.datetime(2011, 06, 02)) self.assertFalse(self.gargoyle.is_active('test', user)) user = User(pk=8771, date_joined=datetime.datetime(2011, 07, 01)) self.assertTrue(self.gargoyle.is_active('test', user)) switch.clear_conditions(condition_set=condition_set) switch.add_condition( condition_set=condition_set, field_name='email', condition='*****@*****.**', ) user = User(pk=8771, email="*****@*****.**") self.assertTrue(self.gargoyle.is_active('test', user)) user = User(pk=8771, email="*****@*****.**") self.assertFalse(self.gargoyle.is_active('test', user)) user = User(pk=8771) self.assertFalse(self.gargoyle.is_active('test', user)) def test_exclusions(self): condition_set = 'gargoyle.builtins.UserConditionSet(auth.user)' switch = Switch.objects.create( key='test', status=SELECTIVE, ) switch = self.gargoyle['test'] switch.add_condition( condition_set=condition_set, field_name='is_staff', condition='1', ) switch.add_condition( condition_set=condition_set, field_name='username', condition='foo', ) switch.add_condition( condition_set=condition_set, field_name='username', condition='bar', exclude=True ) user = User(pk=0, username='******', is_staff=False) self.assertTrue(self.gargoyle.is_active('test', user)) user = User(pk=0, username='******', is_staff=True) self.assertTrue(self.gargoyle.is_active('test', user)) user = User(pk=0, username='******', is_staff=False) self.assertFalse(self.gargoyle.is_active('test', user)) user = User(pk=0, username='******', is_staff=True) self.assertFalse(self.gargoyle.is_active('test', user)) def test_only_exclusions(self): condition_set = 'gargoyle.builtins.UserConditionSet(auth.user)' switch = Switch.objects.create( key='test', status=SELECTIVE, ) switch = self.gargoyle['test'] switch.add_condition( condition_set=condition_set, field_name='username', condition='bar', exclude=True ) user = User(pk=0, username='******', is_staff=False) self.assertFalse(self.gargoyle.is_active('test', user)) user = User(pk=0, username='******', is_staff=True) self.assertFalse(self.gargoyle.is_active('test', user)) user = User(pk=0, username='******', is_staff=False) self.assertFalse(self.gargoyle.is_active('test', user)) user = User(pk=0, username='******', is_staff=True) self.assertFalse(self.gargoyle.is_active('test', user)) def test_decorator_for_user(self): condition_set = 'gargoyle.builtins.UserConditionSet(auth.user)' switch = Switch.objects.create( key='test', status=DISABLED, ) switch = self.gargoyle['test'] @switch_is_active('test') def test(request): return True request = HttpRequest() request.user = self.user self.assertRaises(Http404, test, request) switch.status = SELECTIVE switch.save() self.assertRaises(Http404, test, request) switch.add_condition( condition_set=condition_set, field_name='username', condition='foo', ) self.assertTrue(test(request)) def test_decorator_for_ip_address(self): condition_set = 'gargoyle.builtins.IPAddressConditionSet' switch = Switch.objects.create( key='test', status=DISABLED, ) switch = self.gargoyle['test'] @switch_is_active('test') def test(request): return True request = HttpRequest() request.META['REMOTE_ADDR'] = '192.168.1.1' self.assertRaises(Http404, test, request) switch.status = SELECTIVE switch.save() switch.add_condition( condition_set=condition_set, field_name='ip_address', condition='192.168.1.1', ) self.assertTrue(test(request)) # add in a second condition, so that removing the first one won't kick # in the "no conditions returns is_active True for selective switches" switch.add_condition( condition_set=condition_set, field_name='ip_address', condition='192.168.1.2', ) switch.remove_condition( condition_set=condition_set, field_name='ip_address', condition='192.168.1.1', ) self.assertRaises(Http404, test, request) switch.add_condition( condition_set=condition_set, field_name='ip_address', condition='192.168.1.1', ) self.assertTrue(test(request)) switch.clear_conditions( condition_set=condition_set, field_name='ip_address', ) switch.add_condition( condition_set=condition_set, field_name='percent', condition='50-100', ) self.assertTrue(test(request)) switch.clear_conditions( condition_set=condition_set, ) switch.add_condition( condition_set=condition_set, field_name='percent', condition='0-50', ) self.assertRaises(Http404, test, request) def test_decorator_with_redirect(self): Switch.objects.create( key='test', status=DISABLED, ) request = HttpRequest() request.user = self.user @switch_is_active('test', redirect_to='/foo') def test(request): return HttpResponse() response = test(request) self.assertTrue(response.status_code, 302) self.assertTrue('Location' in response) self.assertTrue(response['Location'], '/foo') @switch_is_active('test', redirect_to='gargoyle_test_foo') def test2(request): return HttpResponse() response = test2(request) self.assertTrue(response.status_code, 302) self.assertTrue('Location' in response) self.assertTrue(response['Location'], '') def test_global(self): switch = Switch.objects.create( key='test', status=DISABLED, ) switch = self.gargoyle['test'] self.assertFalse(self.gargoyle.is_active('test')) self.assertFalse(self.gargoyle.is_active('test', self.user)) switch.status = GLOBAL switch.save() self.assertTrue(self.gargoyle.is_active('test')) self.assertTrue(self.gargoyle.is_active('test', self.user)) def test_disable(self): switch = Switch.objects.create(key='test') switch = self.gargoyle['test'] switch.status = DISABLED switch.save() self.assertFalse(self.gargoyle.is_active('test')) self.assertFalse(self.gargoyle.is_active('test', self.user)) def test_deletion(self): switch = Switch.objects.create(key='test') switch = self.gargoyle['test'] self.assertTrue('test' in self.gargoyle) switch.delete() self.assertFalse('test' in self.gargoyle) def test_expiration(self): switch = Switch.objects.create(key='test') switch = self.gargoyle['test'] switch.status = DISABLED switch.save() self.assertFalse(self.gargoyle.is_active('test')) Switch.objects.filter(key='test').update(value={}, status=GLOBAL) # cache shouldn't have expired self.assertFalse(self.gargoyle.is_active('test')) # in memory cache shouldnt have expired cache.delete(self.gargoyle.remote_cache_key) self.assertFalse(self.gargoyle.is_active('test')) switch.status, switch.value = GLOBAL, {} # Ensure post save gets sent self.gargoyle._post_save(sender=None, instance=switch, created=False) # any request should expire the in memory cache self.client.get('/') self.assertTrue(self.gargoyle.is_active('test')) def test_anonymous_user(self): condition_set = 'gargoyle.builtins.UserConditionSet(auth.user)' switch = Switch.objects.create(key='test') switch = self.gargoyle['test'] switch.status = SELECTIVE switch.save() user = AnonymousUser() self.assertFalse(self.gargoyle.is_active('test', user)) switch.add_condition( condition_set=condition_set, field_name='percent', condition='1-10', ) self.assertFalse(self.gargoyle.is_active('test', user)) switch.clear_conditions( condition_set=condition_set, ) self.assertFalse(self.gargoyle.is_active('test', user)) switch.add_condition( condition_set=condition_set, field_name='is_anonymous', condition='1', ) self.assertTrue(self.gargoyle.is_active('test', user)) switch.add_condition( condition_set=condition_set, field_name='percent', condition='1-10', ) self.assertTrue(self.gargoyle.is_active('test', user)) def test_ip_address_internal_ips(self): condition_set = 'gargoyle.builtins.IPAddressConditionSet' Switch.objects.create( key='test', status=SELECTIVE, ) switch = self.gargoyle['test'] request = HttpRequest() request.META['REMOTE_ADDR'] = '192.168.1.1' self.assertFalse(self.gargoyle.is_active('test', request)) switch.add_condition( condition_set=condition_set, field_name='internal_ip', condition='1', ) settings.INTERNAL_IPS = ['192.168.1.1'] self.assertTrue(self.gargoyle.is_active('test', request)) settings.INTERNAL_IPS = [] self.assertFalse(self.gargoyle.is_active('test', request)) def test_ip_address(self): condition_set = 'gargoyle.builtins.IPAddressConditionSet' switch = Switch.objects.create( key='test', status=SELECTIVE, ) switch = self.gargoyle['test'] request = HttpRequest() request.META['REMOTE_ADDR'] = '192.168.1.1' self.assertFalse(self.gargoyle.is_active('test', request)) switch.add_condition( condition_set=condition_set, field_name='ip_address', condition='192.168.1.1', ) self.assertTrue(self.gargoyle.is_active('test', request)) switch.clear_conditions( condition_set=condition_set, ) switch.add_condition( condition_set=condition_set, field_name='ip_address', condition='127.0.0.1', ) self.assertFalse(self.gargoyle.is_active('test', request)) switch.clear_conditions( condition_set=condition_set, ) self.assertFalse(self.gargoyle.is_active('test', request)) switch.add_condition( condition_set=condition_set, field_name='percent', condition='50-100', ) self.assertTrue(self.gargoyle.is_active('test', request)) # test with mock request self.assertTrue(self.gargoyle.is_active('test', self.gargoyle.as_request(ip_address='192.168.1.1'))) switch.clear_conditions( condition_set=condition_set, ) switch.add_condition( condition_set=condition_set, field_name='percent', condition='0-50', ) self.assertFalse(self.gargoyle.is_active('test', request)) def test_to_dict(self): condition_set = 'gargoyle.builtins.IPAddressConditionSet' switch = Switch.objects.create( label='my switch', description='foo bar baz', key='test', status=SELECTIVE, ) switch.add_condition( manager=self.gargoyle, condition_set=condition_set, field_name='ip_address', condition='192.168.1.1', ) result = switch.to_dict(self.gargoyle) self.assertTrue('label' in result) self.assertEquals(result['label'], 'my switch') self.assertTrue('status' in result) self.assertEquals(result['status'], SELECTIVE) self.assertTrue('description' in result) self.assertEquals(result['description'], 'foo bar baz') self.assertTrue('key' in result) self.assertEquals(result['key'], 'test') self.assertTrue('conditions' in result) self.assertEquals(len(result['conditions']), 1) condition = result['conditions'][0] self.assertTrue('id' in condition) self.assertEquals(condition['id'], condition_set) self.assertTrue('label' in condition) self.assertEquals(condition['label'], 'IP Address') self.assertTrue('conditions' in condition) self.assertEquals(len(condition['conditions']), 1) inner_condition = condition['conditions'][0] self.assertEquals(len(inner_condition), 4) self.assertTrue(inner_condition[0], 'ip_address') self.assertTrue(inner_condition[1], '192.168.1.1') self.assertTrue(inner_condition[2], '192.168.1.1') self.assertFalse(inner_condition[3]) def test_remove_condition(self): condition_set = 'gargoyle.builtins.UserConditionSet(auth.user)' switch = Switch.objects.create( key='test', status=SELECTIVE, ) switch = self.gargoyle['test'] user5 = User(pk=5, email='*****@*****.**') # inactive if selective with no conditions self.assertFalse(self.gargoyle.is_active('test', user5)) user8771 = User(pk=8771, email='*****@*****.**', is_superuser=True) switch.add_condition( condition_set=condition_set, field_name='is_superuser', condition='1', ) self.assertTrue(self.gargoyle.is_active('test', user8771)) # No longer is_active for user5 as we have other conditions self.assertFalse(self.gargoyle.is_active('test', user5)) switch.remove_condition( condition_set=condition_set, field_name='is_superuser', condition='1', ) # back to inactive for everyone with no conditions self.assertFalse(self.gargoyle.is_active('test', user5)) self.assertFalse(self.gargoyle.is_active('test', user8771)) def test_switch_defaults(self): """Test that defaults pulled from GARGOYLE_SWITCH_DEFAULTS. Requires SwitchManager to use auto_create. """ self.assertTrue(self.gargoyle.is_active('active_by_default')) self.assertFalse(self.gargoyle.is_active('inactive_by_default')) self.assertEquals( self.gargoyle['inactive_by_default'].label, 'Default Inactive', ) self.assertEquals( self.gargoyle['active_by_default'].label, 'Default Active', ) active_by_default = self.gargoyle['active_by_default'] active_by_default.status = DISABLED active_by_default.save() self.assertFalse(self.gargoyle.is_active('active_by_default')) def test_invalid_condition(self): condition_set = 'gargoyle.builtins.UserConditionSet(auth.user)' switch = Switch.objects.create( key='test', status=SELECTIVE, ) switch = self.gargoyle['test'] user5 = User(pk=5, email='*****@*****.**') # inactive if selective with no conditions self.assertFalse(self.gargoyle.is_active('test', user5)) user8771 = User(pk=8771, email='*****@*****.**', is_superuser=True) switch.add_condition( condition_set=condition_set, field_name='foo', condition='1', ) self.assertFalse(self.gargoyle.is_active('test', user8771)) def test_inheritance(self): condition_set = 'gargoyle.builtins.UserConditionSet(auth.user)' # we need a better API for this (model dict isnt cutting it) switch = Switch.objects.create( key='test', status=SELECTIVE, ) switch = self.gargoyle['test'] switch.add_condition( condition_set=condition_set, field_name='percent', condition='0-50', ) switch = Switch.objects.create( key='test:child', status=INHERIT, ) switch = self.gargoyle['test'] user = User(pk=5) self.assertTrue(self.gargoyle.is_active('test:child', user)) user = User(pk=8771) self.assertFalse(self.gargoyle.is_active('test:child', user)) switch = self.gargoyle['test'] switch.status = DISABLED user = User(pk=5) self.assertFalse(self.gargoyle.is_active('test:child', user)) user = User(pk=8771) self.assertFalse(self.gargoyle.is_active('test:child', user)) switch = self.gargoyle['test'] switch.status = GLOBAL user = User(pk=5) self.assertTrue(self.gargoyle.is_active('test:child', user)) user = User(pk=8771) self.assertTrue(self.gargoyle.is_active('test:child', user)) def test_parent_override_child_state(self): Switch.objects.create( key='test', status=DISABLED, ) Switch.objects.create( key='test:child', status=GLOBAL, ) self.assertFalse(self.gargoyle.is_active('test:child')) def test_child_state_is_used(self): Switch.objects.create( key='test', status=GLOBAL, ) Switch.objects.create( key='test:child', status=DISABLED, ) self.assertFalse(self.gargoyle.is_active('test:child')) def test_parent_override_child_condition(self): condition_set = 'gargoyle.builtins.UserConditionSet(auth.user)' Switch.objects.create( key='test', status=SELECTIVE, ) parent = self.gargoyle['test'] parent.add_condition( condition_set=condition_set, field_name='username', condition='bob', ) Switch.objects.create( key='test:child', status=GLOBAL, ) user = User(username='******') self.assertTrue(self.gargoyle.is_active('test:child', user)) user = User(username='******') self.assertFalse(self.gargoyle.is_active('test:child', user)) self.assertFalse(self.gargoyle.is_active('test:child')) def test_child_condition_differing_than_parent_loses(self): condition_set = 'gargoyle.builtins.UserConditionSet(auth.user)' Switch.objects.create( key='test', status=SELECTIVE, ) parent = self.gargoyle['test'] parent.add_condition( condition_set=condition_set, field_name='username', condition='bob', ) Switch.objects.create( key='test:child', status=SELECTIVE, ) child = self.gargoyle['test:child'] child.add_condition( condition_set=condition_set, field_name='username', condition='joe', ) user = User(username='******') self.assertFalse(self.gargoyle.is_active('test:child', user)) user = User(username='******') self.assertFalse(self.gargoyle.is_active('test:child', user)) user = User(username='******') self.assertFalse(self.gargoyle.is_active('test:child', user)) self.assertFalse(self.gargoyle.is_active('test:child')) def test_child_condition_including_parent_wins(self): condition_set = 'gargoyle.builtins.UserConditionSet(auth.user)' Switch.objects.create( key='test', status=SELECTIVE, ) parent = self.gargoyle['test'] parent.add_condition( condition_set=condition_set, field_name='username', condition='bob', ) Switch.objects.create( key='test:child', status=SELECTIVE, ) child = self.gargoyle['test:child'] child.add_condition( condition_set=condition_set, field_name='username', condition='bob', ) child.add_condition( condition_set=condition_set, field_name='username', condition='joe', ) user = User(username='******') self.assertTrue(self.gargoyle.is_active('test:child', user)) user = User(username='******') self.assertFalse(self.gargoyle.is_active('test:child', user)) user = User(username='******') self.assertFalse(self.gargoyle.is_active('test:child', user)) self.assertFalse(self.gargoyle.is_active('test:child'))
class APITest(TestCase): urls = 'tests.urls' def setUp(self): self.user = User.objects.create(username='******', email='*****@*****.**') self.gargoyle = SwitchManager(Switch, key='key', value='value', instances=True, auto_create=True) self.gargoyle.register(UserConditionSet(User)) self.gargoyle.register(IPAddressConditionSet()) self.internal_ips = settings.INTERNAL_IPS def tearDown(self): settings.INTERNAL_IPS = self.internal_ips def test_builtin_registration(self): self.assertTrue('gargoyle.builtins.UserConditionSet(auth.user)' in self.gargoyle._registry) self.assertTrue('gargoyle.builtins.IPAddressConditionSet' in self.gargoyle._registry) self.assertEquals(len(list(self.gargoyle.get_condition_sets())), 2, self.gargoyle) def test_user(self): condition_set = 'gargoyle.builtins.UserConditionSet(auth.user)' # we need a better API for this (model dict isnt cutting it) switch = Switch.objects.create( key='test', status=SELECTIVE, ) switch = self.gargoyle['test'] switch.add_condition( condition_set=condition_set, field_name='percent', condition='0-50', ) user = User(pk=5) self.assertTrue(self.gargoyle.is_active('test', user)) user = User(pk=8771) self.assertFalse(self.gargoyle.is_active('test', user)) switch.add_condition( condition_set=condition_set, field_name='is_staff', condition='1', ) user = User(pk=8771, is_staff=True) self.assertTrue(self.gargoyle.is_active('test', user)) user = User(pk=8771, is_superuser=True) self.assertFalse(self.gargoyle.is_active('test', user)) switch.add_condition( condition_set=condition_set, field_name='is_superuser', condition='1', ) user = User(pk=8771, is_superuser=True) self.assertTrue(self.gargoyle.is_active('test', user)) # test with mock request self.assertTrue( self.gargoyle.is_active('test', self.gargoyle.as_request(user=user))) # test date joined condition user = User(pk=8771) self.assertFalse(self.gargoyle.is_active('test', user)) switch.add_condition( condition_set=condition_set, field_name='date_joined', condition='2011-07-01', ) user = User(pk=8771, date_joined=datetime.datetime(2011, 07, 02)) self.assertTrue(self.gargoyle.is_active('test', user)) user = User(pk=8771, date_joined=datetime.datetime(2012, 07, 02)) self.assertTrue(self.gargoyle.is_active('test', user)) user = User(pk=8771, date_joined=datetime.datetime(2011, 06, 02)) self.assertFalse(self.gargoyle.is_active('test', user)) user = User(pk=8771, date_joined=datetime.datetime(2011, 07, 01)) self.assertTrue(self.gargoyle.is_active('test', user)) switch.clear_conditions(condition_set=condition_set) switch.add_condition( condition_set=condition_set, field_name='email', condition='*****@*****.**', ) user = User(pk=8771, email="*****@*****.**") self.assertTrue(self.gargoyle.is_active('test', user)) user = User(pk=8771, email="*****@*****.**") self.assertFalse(self.gargoyle.is_active('test', user)) user = User(pk=8771) self.assertFalse(self.gargoyle.is_active('test', user)) def test_exclusions(self): condition_set = 'gargoyle.builtins.UserConditionSet(auth.user)' switch = Switch.objects.create( key='test', status=SELECTIVE, ) switch = self.gargoyle['test'] switch.add_condition( condition_set=condition_set, field_name='is_staff', condition='1', ) switch.add_condition( condition_set=condition_set, field_name='username', condition='foo', ) switch.add_condition(condition_set=condition_set, field_name='username', condition='bar', exclude=True) user = User(pk=0, username='******', is_staff=False) self.assertTrue(self.gargoyle.is_active('test', user)) user = User(pk=0, username='******', is_staff=True) self.assertTrue(self.gargoyle.is_active('test', user)) user = User(pk=0, username='******', is_staff=False) self.assertFalse(self.gargoyle.is_active('test', user)) user = User(pk=0, username='******', is_staff=True) self.assertFalse(self.gargoyle.is_active('test', user)) def test_only_exclusions(self): condition_set = 'gargoyle.builtins.UserConditionSet(auth.user)' switch = Switch.objects.create( key='test', status=SELECTIVE, ) switch = self.gargoyle['test'] switch.add_condition(condition_set=condition_set, field_name='username', condition='bar', exclude=True) user = User(pk=0, username='******', is_staff=False) self.assertFalse(self.gargoyle.is_active('test', user)) user = User(pk=0, username='******', is_staff=True) self.assertFalse(self.gargoyle.is_active('test', user)) user = User(pk=0, username='******', is_staff=False) self.assertFalse(self.gargoyle.is_active('test', user)) user = User(pk=0, username='******', is_staff=True) self.assertFalse(self.gargoyle.is_active('test', user)) def test_decorator_for_user(self): condition_set = 'gargoyle.builtins.UserConditionSet(auth.user)' switch = Switch.objects.create( key='test', status=DISABLED, ) switch = self.gargoyle['test'] @switch_is_active('test') def test(request): return True request = HttpRequest() request.user = self.user self.assertRaises(Http404, test, request) switch.status = SELECTIVE switch.save() self.assertRaises(Http404, test, request) switch.add_condition( condition_set=condition_set, field_name='username', condition='foo', ) self.assertTrue(test(request)) def test_decorator_for_ip_address(self): condition_set = 'gargoyle.builtins.IPAddressConditionSet' switch = Switch.objects.create( key='test', status=DISABLED, ) switch = self.gargoyle['test'] @switch_is_active('test') def test(request): return True request = HttpRequest() request.META['REMOTE_ADDR'] = '192.168.1.1' self.assertRaises(Http404, test, request) switch.status = SELECTIVE switch.save() switch.add_condition( condition_set=condition_set, field_name='ip_address', condition='192.168.1.1', ) self.assertTrue(test(request)) # add in a second condition, so that removing the first one won't kick # in the "no conditions returns is_active True for selective switches" switch.add_condition( condition_set=condition_set, field_name='ip_address', condition='192.168.1.2', ) switch.remove_condition( condition_set=condition_set, field_name='ip_address', condition='192.168.1.1', ) self.assertRaises(Http404, test, request) switch.add_condition( condition_set=condition_set, field_name='ip_address', condition='192.168.1.1', ) self.assertTrue(test(request)) switch.clear_conditions( condition_set=condition_set, field_name='ip_address', ) switch.add_condition( condition_set=condition_set, field_name='percent', condition='50-100', ) self.assertTrue(test(request)) switch.clear_conditions(condition_set=condition_set, ) switch.add_condition( condition_set=condition_set, field_name='percent', condition='0-50', ) self.assertRaises(Http404, test, request) def test_decorator_with_redirect(self): Switch.objects.create( key='test', status=DISABLED, ) request = HttpRequest() request.user = self.user @switch_is_active('test', redirect_to='/foo') def test(request): return HttpResponse() response = test(request) self.assertTrue(response.status_code, 302) self.assertTrue('Location' in response) self.assertTrue(response['Location'], '/foo') @switch_is_active('test', redirect_to='gargoyle_test_foo') def test2(request): return HttpResponse() response = test2(request) self.assertTrue(response.status_code, 302) self.assertTrue('Location' in response) self.assertTrue(response['Location'], '') def test_global(self): switch = Switch.objects.create( key='test', status=DISABLED, ) switch = self.gargoyle['test'] self.assertFalse(self.gargoyle.is_active('test')) self.assertFalse(self.gargoyle.is_active('test', self.user)) switch.status = GLOBAL switch.save() self.assertTrue(self.gargoyle.is_active('test')) self.assertTrue(self.gargoyle.is_active('test', self.user)) def test_disable(self): switch = Switch.objects.create(key='test') switch = self.gargoyle['test'] switch.status = DISABLED switch.save() self.assertFalse(self.gargoyle.is_active('test')) self.assertFalse(self.gargoyle.is_active('test', self.user)) def test_deletion(self): switch = Switch.objects.create(key='test') switch = self.gargoyle['test'] self.assertTrue('test' in self.gargoyle) switch.delete() self.assertFalse('test' in self.gargoyle) def test_expiration(self): switch = Switch.objects.create(key='test') switch = self.gargoyle['test'] switch.status = DISABLED switch.save() self.assertFalse(self.gargoyle.is_active('test')) Switch.objects.filter(key='test').update(value={}, status=GLOBAL) # cache shouldn't have expired self.assertFalse(self.gargoyle.is_active('test')) # lookup cache_key in a modeldict 1.2/1.4 compatible way if hasattr(self.gargoyle, 'remote_cache_key'): cache_key = self.gargoyle.remote_cache_key else: cache_key = self.gargoyle.cache_key # in memory cache shouldnt have expired cache.delete(cache_key) self.assertFalse(self.gargoyle.is_active('test')) switch.status, switch.value = GLOBAL, {} # Ensure post save gets sent self.gargoyle._post_save(sender=None, instance=switch, created=False) # any request should expire the in memory cache self.client.get('/') self.assertTrue(self.gargoyle.is_active('test')) def test_anonymous_user(self): condition_set = 'gargoyle.builtins.UserConditionSet(auth.user)' switch = Switch.objects.create(key='test') switch = self.gargoyle['test'] switch.status = SELECTIVE switch.save() user = AnonymousUser() self.assertFalse(self.gargoyle.is_active('test', user)) switch.add_condition( condition_set=condition_set, field_name='percent', condition='1-10', ) self.assertFalse(self.gargoyle.is_active('test', user)) switch.clear_conditions(condition_set=condition_set, ) self.assertFalse(self.gargoyle.is_active('test', user)) switch.add_condition( condition_set=condition_set, field_name='is_anonymous', condition='1', ) self.assertTrue(self.gargoyle.is_active('test', user)) switch.add_condition( condition_set=condition_set, field_name='percent', condition='1-10', ) self.assertTrue(self.gargoyle.is_active('test', user)) def test_ip_address_internal_ips(self): condition_set = 'gargoyle.builtins.IPAddressConditionSet' Switch.objects.create( key='test', status=SELECTIVE, ) switch = self.gargoyle['test'] request = HttpRequest() request.META['REMOTE_ADDR'] = '192.168.1.1' self.assertFalse(self.gargoyle.is_active('test', request)) switch.add_condition( condition_set=condition_set, field_name='internal_ip', condition='1', ) settings.INTERNAL_IPS = ['192.168.1.1'] self.assertTrue(self.gargoyle.is_active('test', request)) settings.INTERNAL_IPS = [] self.assertFalse(self.gargoyle.is_active('test', request)) def test_ip_address(self): condition_set = 'gargoyle.builtins.IPAddressConditionSet' switch = Switch.objects.create( key='test', status=SELECTIVE, ) switch = self.gargoyle['test'] request = HttpRequest() request.META['REMOTE_ADDR'] = '192.168.1.1' self.assertFalse(self.gargoyle.is_active('test', request)) switch.add_condition( condition_set=condition_set, field_name='ip_address', condition='192.168.1.1', ) self.assertTrue(self.gargoyle.is_active('test', request)) switch.clear_conditions(condition_set=condition_set, ) switch.add_condition( condition_set=condition_set, field_name='ip_address', condition='127.0.0.1', ) self.assertFalse(self.gargoyle.is_active('test', request)) switch.clear_conditions(condition_set=condition_set, ) self.assertFalse(self.gargoyle.is_active('test', request)) switch.add_condition( condition_set=condition_set, field_name='percent', condition='50-100', ) self.assertTrue(self.gargoyle.is_active('test', request)) # test with mock request self.assertTrue( self.gargoyle.is_active( 'test', self.gargoyle.as_request(ip_address='192.168.1.1'))) switch.clear_conditions(condition_set=condition_set, ) switch.add_condition( condition_set=condition_set, field_name='percent', condition='0-50', ) self.assertFalse(self.gargoyle.is_active('test', request)) self.assertTrue( self.gargoyle.is_active( 'test', self.gargoyle.as_request(ip_address='::1'))) switch.clear_conditions(condition_set=condition_set, ) switch.add_condition( condition_set=condition_set, field_name='percent', condition='0-50', ) self.assertFalse(self.gargoyle.is_active('test', request)) def test_to_dict(self): condition_set = 'gargoyle.builtins.IPAddressConditionSet' switch = Switch.objects.create( label='my switch', description='foo bar baz', key='test', status=SELECTIVE, ) switch.add_condition( manager=self.gargoyle, condition_set=condition_set, field_name='ip_address', condition='192.168.1.1', ) result = switch.to_dict(self.gargoyle) self.assertTrue('label' in result) self.assertEquals(result['label'], 'my switch') self.assertTrue('status' in result) self.assertEquals(result['status'], SELECTIVE) self.assertTrue('description' in result) self.assertEquals(result['description'], 'foo bar baz') self.assertTrue('key' in result) self.assertEquals(result['key'], 'test') self.assertTrue('conditions' in result) self.assertEquals(len(result['conditions']), 1) condition = result['conditions'][0] self.assertTrue('id' in condition) self.assertEquals(condition['id'], condition_set) self.assertTrue('label' in condition) self.assertEquals(condition['label'], 'IP Address') self.assertTrue('conditions' in condition) self.assertEquals(len(condition['conditions']), 1) inner_condition = condition['conditions'][0] self.assertEquals(len(inner_condition), 4) self.assertTrue(inner_condition[0], 'ip_address') self.assertTrue(inner_condition[1], '192.168.1.1') self.assertTrue(inner_condition[2], '192.168.1.1') self.assertFalse(inner_condition[3]) def test_remove_condition(self): condition_set = 'gargoyle.builtins.UserConditionSet(auth.user)' switch = Switch.objects.create( key='test', status=SELECTIVE, ) switch = self.gargoyle['test'] user5 = User(pk=5, email='*****@*****.**') # inactive if selective with no conditions self.assertFalse(self.gargoyle.is_active('test', user5)) user8771 = User(pk=8771, email='*****@*****.**', is_superuser=True) switch.add_condition( condition_set=condition_set, field_name='is_superuser', condition='1', ) self.assertTrue(self.gargoyle.is_active('test', user8771)) # No longer is_active for user5 as we have other conditions self.assertFalse(self.gargoyle.is_active('test', user5)) switch.remove_condition( condition_set=condition_set, field_name='is_superuser', condition='1', ) # back to inactive for everyone with no conditions self.assertFalse(self.gargoyle.is_active('test', user5)) self.assertFalse(self.gargoyle.is_active('test', user8771)) def test_switch_defaults(self): """Test that defaults pulled from GARGOYLE_SWITCH_DEFAULTS. Requires SwitchManager to use auto_create. """ self.assertTrue(self.gargoyle.is_active('active_by_default')) self.assertFalse(self.gargoyle.is_active('inactive_by_default')) self.assertEquals( self.gargoyle['inactive_by_default'].label, 'Default Inactive', ) self.assertEquals( self.gargoyle['active_by_default'].label, 'Default Active', ) active_by_default = self.gargoyle['active_by_default'] active_by_default.status = DISABLED active_by_default.save() self.assertFalse(self.gargoyle.is_active('active_by_default')) def test_invalid_condition(self): condition_set = 'gargoyle.builtins.UserConditionSet(auth.user)' switch = Switch.objects.create( key='test', status=SELECTIVE, ) switch = self.gargoyle['test'] user5 = User(pk=5, email='*****@*****.**') # inactive if selective with no conditions self.assertFalse(self.gargoyle.is_active('test', user5)) user8771 = User(pk=8771, email='*****@*****.**', is_superuser=True) switch.add_condition( condition_set=condition_set, field_name='foo', condition='1', ) self.assertFalse(self.gargoyle.is_active('test', user8771)) def test_inheritance(self): condition_set = 'gargoyle.builtins.UserConditionSet(auth.user)' # we need a better API for this (model dict isnt cutting it) switch = Switch.objects.create( key='test', status=SELECTIVE, ) switch = self.gargoyle['test'] switch.add_condition( condition_set=condition_set, field_name='percent', condition='0-50', ) switch = Switch.objects.create( key='test:child', status=INHERIT, ) switch = self.gargoyle['test'] user = User(pk=5) self.assertTrue(self.gargoyle.is_active('test:child', user)) user = User(pk=8771) self.assertFalse(self.gargoyle.is_active('test:child', user)) switch = self.gargoyle['test'] switch.status = DISABLED user = User(pk=5) self.assertFalse(self.gargoyle.is_active('test:child', user)) user = User(pk=8771) self.assertFalse(self.gargoyle.is_active('test:child', user)) switch = self.gargoyle['test'] switch.status = GLOBAL user = User(pk=5) self.assertTrue(self.gargoyle.is_active('test:child', user)) user = User(pk=8771) self.assertTrue(self.gargoyle.is_active('test:child', user)) def test_parent_override_child_state(self): Switch.objects.create( key='test', status=DISABLED, ) Switch.objects.create( key='test:child', status=GLOBAL, ) self.assertFalse(self.gargoyle.is_active('test:child')) def test_child_state_is_used(self): Switch.objects.create( key='test', status=GLOBAL, ) Switch.objects.create( key='test:child', status=DISABLED, ) self.assertFalse(self.gargoyle.is_active('test:child')) def test_parent_override_child_condition(self): condition_set = 'gargoyle.builtins.UserConditionSet(auth.user)' Switch.objects.create( key='test', status=SELECTIVE, ) parent = self.gargoyle['test'] parent.add_condition( condition_set=condition_set, field_name='username', condition='bob', ) Switch.objects.create( key='test:child', status=GLOBAL, ) user = User(username='******') self.assertTrue(self.gargoyle.is_active('test:child', user)) user = User(username='******') self.assertFalse(self.gargoyle.is_active('test:child', user)) self.assertFalse(self.gargoyle.is_active('test:child')) def test_child_condition_differing_than_parent_loses(self): condition_set = 'gargoyle.builtins.UserConditionSet(auth.user)' Switch.objects.create( key='test', status=SELECTIVE, ) parent = self.gargoyle['test'] parent.add_condition( condition_set=condition_set, field_name='username', condition='bob', ) Switch.objects.create( key='test:child', status=SELECTIVE, ) child = self.gargoyle['test:child'] child.add_condition( condition_set=condition_set, field_name='username', condition='joe', ) user = User(username='******') self.assertFalse(self.gargoyle.is_active('test:child', user)) user = User(username='******') self.assertFalse(self.gargoyle.is_active('test:child', user)) user = User(username='******') self.assertFalse(self.gargoyle.is_active('test:child', user)) self.assertFalse(self.gargoyle.is_active('test:child')) def test_child_condition_including_parent_wins(self): condition_set = 'gargoyle.builtins.UserConditionSet(auth.user)' Switch.objects.create( key='test', status=SELECTIVE, ) parent = self.gargoyle['test'] parent.add_condition( condition_set=condition_set, field_name='username', condition='bob', ) Switch.objects.create( key='test:child', status=SELECTIVE, ) child = self.gargoyle['test:child'] child.add_condition( condition_set=condition_set, field_name='username', condition='bob', ) child.add_condition( condition_set=condition_set, field_name='username', condition='joe', ) user = User(username='******') self.assertTrue(self.gargoyle.is_active('test:child', user)) user = User(username='******') self.assertFalse(self.gargoyle.is_active('test:child', user)) user = User(username='******') self.assertFalse(self.gargoyle.is_active('test:child', user)) self.assertFalse(self.gargoyle.is_active('test:child'))
class APITest(TestCase): request_factory = RequestFactory() def setUp(self): self.user = User.objects.create(username='******', email='*****@*****.**') self.gargoyle = SwitchManager(Switch, key='key', value='value', instances=True, auto_create=True) self.gargoyle.register(UserConditionSet(User)) self.gargoyle.register(IPAddressConditionSet()) def test_register_unregister_class(self): klass = IPAddressConditionSet registered = self.gargoyle.register(IPAddressConditionSet) assert registered is klass unregistered = self.gargoyle.unregister(klass) assert unregistered unregistered = self.gargoyle.unregister(klass) assert not unregistered def test_register_unregister_instance(self): condition_set = IPAddressConditionSet() registered = self.gargoyle.register(condition_set) assert registered is condition_set unregistered = self.gargoyle.unregister(condition_set) assert unregistered unregistered = self.gargoyle.unregister(condition_set) assert not unregistered def test_builtin_registration(self): assert 'gargoyle.builtins.UserConditionSet(auth.user)' in self.gargoyle._registry assert 'gargoyle.builtins.IPAddressConditionSet' in self.gargoyle._registry assert len(list(self.gargoyle.get_condition_sets())) == 2 def test_user(self): condition_set = 'gargoyle.builtins.UserConditionSet(auth.user)' switch = Switch.objects.create(key='test', status=SELECTIVE) switch = self.gargoyle['test'] switch.add_condition( condition_set=condition_set, field_name='percent', condition='0-50', ) user = User(pk=5) assert self.gargoyle.is_active('test', user) user = User(pk=8771) assert not self.gargoyle.is_active('test', user) switch.add_condition( condition_set=condition_set, field_name='is_staff', condition='1', ) user = User(pk=8771, is_staff=True) assert self.gargoyle.is_active('test', user) user = User(pk=8771, is_superuser=True) assert not self.gargoyle.is_active('test', user) switch.add_condition( condition_set=condition_set, field_name='is_superuser', condition='1', ) user = User(pk=8771, is_superuser=True) assert self.gargoyle.is_active('test', user) # test with request request = self.request_factory.get('/', user=user) assert self.gargoyle.is_active('test', request) # test date joined condition user = User(pk=8771) assert not self.gargoyle.is_active('test', user) switch.add_condition( condition_set=condition_set, field_name='date_joined', condition='2011-07-01', ) user = User(pk=8771, date_joined=datetime.datetime(2011, 7, 2)) assert self.gargoyle.is_active('test', user) user = User(pk=8771, date_joined=datetime.datetime(2012, 7, 2)) assert self.gargoyle.is_active('test', user) user = User(pk=8771, date_joined=datetime.datetime(2011, 6, 2)) assert not self.gargoyle.is_active('test', user) user = User(pk=8771, date_joined=datetime.datetime(2011, 7, 1)) assert self.gargoyle.is_active('test', user) switch.clear_conditions(condition_set=condition_set) switch.add_condition( condition_set=condition_set, field_name='email', condition='*****@*****.**', ) user = User(pk=8771, email="*****@*****.**") assert self.gargoyle.is_active('test', user) user = User(pk=8771, email="*****@*****.**") assert not self.gargoyle.is_active('test', user) user = User(pk=8771) assert not self.gargoyle.is_active('test', user) def test_exclusions(self): condition_set = 'gargoyle.builtins.UserConditionSet(auth.user)' switch = Switch.objects.create(key='test', status=SELECTIVE) switch = self.gargoyle['test'] switch.add_condition( condition_set=condition_set, field_name='is_staff', condition='1', ) switch.add_condition( condition_set=condition_set, field_name='username', condition='foo', ) switch.add_condition( condition_set=condition_set, field_name='username', condition='bar', exclude=True ) user = User(pk=0, username='******', is_staff=False) assert self.gargoyle.is_active('test', user) user = User(pk=0, username='******', is_staff=True) assert self.gargoyle.is_active('test', user) user = User(pk=0, username='******', is_staff=False) assert not self.gargoyle.is_active('test', user) user = User(pk=0, username='******', is_staff=True) assert not self.gargoyle.is_active('test', user) def test_only_exclusions(self): condition_set = 'gargoyle.builtins.UserConditionSet(auth.user)' switch = Switch.objects.create(key='test', status=SELECTIVE) switch = self.gargoyle['test'] # Intent is that this condition is True for all users *except* if the # username == bar switch.add_condition( condition_set=condition_set, field_name='username', condition='bar', exclude=True ) # username=='foo', so should be active user = User(pk=0, username='******', is_staff=False) assert self.gargoyle.is_active('test', user) # username=='foo', so should be active user = User(pk=0, username='******', is_staff=True) assert self.gargoyle.is_active('test', user) # username=='bar', so should not be active user = User(pk=0, username='******', is_staff=False) assert not self.gargoyle.is_active('test', user) # username=='bar', so should not be active user = User(pk=0, username='******', is_staff=True) assert not self.gargoyle.is_active('test', user) def test_decorator_for_user(self): condition_set = 'gargoyle.builtins.UserConditionSet(auth.user)' switch = Switch.objects.create(key='test', status=DISABLED) switch = self.gargoyle['test'] @switch_is_active('test') def test(request): return True request = self.request_factory.get('/', user=self.user) with pytest.raises(Http404): test(request) switch.status = SELECTIVE switch.save() with pytest.raises(Http404): test(request) switch.add_condition( condition_set=condition_set, field_name='username', condition='foo', ) assert test(request) def test_decorator_for_ip_address(self): condition_set = 'gargoyle.builtins.IPAddressConditionSet' switch = Switch.objects.create(key='test', status=DISABLED) switch = self.gargoyle['test'] @switch_is_active('test') def test(request): return True request = self.request_factory.get('/', REMOTE_ADDR='192.168.1.1') with pytest.raises(Http404): test(request) switch.status = SELECTIVE switch.save() switch.add_condition( condition_set=condition_set, field_name='ip_address', condition='192.168.1.1', ) assert test(request) # add in a second condition, so that removing the first one won't kick # in the "no conditions returns is_active True for selective switches" switch.add_condition( condition_set=condition_set, field_name='ip_address', condition='192.168.1.2', ) switch.remove_condition( condition_set=condition_set, field_name='ip_address', condition='192.168.1.1', ) with pytest.raises(Http404): test(request) switch.add_condition( condition_set=condition_set, field_name='ip_address', condition='192.168.1.1', ) assert test(request) switch.clear_conditions( condition_set=condition_set, field_name='ip_address', ) switch.add_condition( condition_set=condition_set, field_name='percent', condition='50-100', ) assert test(request) switch.clear_conditions( condition_set=condition_set, ) switch.add_condition( condition_set=condition_set, field_name='percent', condition='0-50', ) with pytest.raises(Http404): test(request) def test_decorator_with_redirect(self): Switch.objects.create(key='test', status=DISABLED) request = self.request_factory.get('/', user=self.user) @switch_is_active('test', redirect_to='/foo') def test(request): return HttpResponse() response = test(request) assert response.status_code, 302 assert 'Location' in response assert response['Location'] == '/foo' @switch_is_active('test', redirect_to='gargoyle_test_foo') def test2(request): return HttpResponse() response = test2(request) assert response.status_code, 302 assert 'Location' in response assert response['Location'] == '/foo/' def test_global(self): switch = Switch.objects.create(key='test', status=DISABLED) switch = self.gargoyle['test'] assert not self.gargoyle.is_active('test') assert not self.gargoyle.is_active('test', self.user) switch.status = GLOBAL switch.save() assert self.gargoyle.is_active('test') assert self.gargoyle.is_active('test', self.user) def test_disable(self): switch = Switch.objects.create(key='test') switch = self.gargoyle['test'] switch.status = DISABLED switch.save() assert not self.gargoyle.is_active('test') assert not self.gargoyle.is_active('test', self.user) def test_deletion(self): switch = Switch.objects.create(key='test') switch = self.gargoyle['test'] assert 'test' in self.gargoyle switch.delete() assert 'test' not in self.gargoyle def test_expiration(self): switch = Switch.objects.create(key='test') switch = self.gargoyle['test'] switch.status = DISABLED switch.save() assert not self.gargoyle.is_active('test') Switch.objects.filter(key='test').update(value={}, status=GLOBAL) # cache shouldn't have expired assert not self.gargoyle.is_active('test') cache_key = self.gargoyle.remote_cache_key # in memory cache shouldnt have expired cache.delete(cache_key) assert not self.gargoyle.is_active('test') switch.status, switch.value = GLOBAL, {} # Ensure post save gets sent self.gargoyle._post_save(sender=None, instance=switch, created=False) # any request should expire the in memory cache self.client.get('/') assert self.gargoyle.is_active('test') def test_anonymous_user(self): condition_set = 'gargoyle.builtins.UserConditionSet(auth.user)' switch = Switch.objects.create(key='test') switch = self.gargoyle['test'] switch.status = SELECTIVE switch.save() user = AnonymousUser() assert not self.gargoyle.is_active('test', user) switch.add_condition( condition_set=condition_set, field_name='percent', condition='1-10', ) assert not self.gargoyle.is_active('test', user) switch.clear_conditions(condition_set=condition_set) assert not self.gargoyle.is_active('test', user) switch.add_condition( condition_set=condition_set, field_name='is_anonymous', condition='1', ) assert self.gargoyle.is_active('test', user) switch.add_condition( condition_set=condition_set, field_name='percent', condition='1-10', ) assert self.gargoyle.is_active('test', user) def test_ip_address_internal_ips(self): condition_set = 'gargoyle.builtins.IPAddressConditionSet' Switch.objects.create(key='test', status=SELECTIVE) switch = self.gargoyle['test'] request = self.request_factory.get('/', REMOTE_ADDR='192.168.1.1') assert not self.gargoyle.is_active('test', request) switch.add_condition( condition_set=condition_set, field_name='internal_ip', condition='1', ) with override_settings(INTERNAL_IPS=['192.168.1.1']): assert self.gargoyle.is_active('test', request) assert not self.gargoyle.is_active('test', request) def test_ip_address(self): condition_set = 'gargoyle.builtins.IPAddressConditionSet' switch = Switch.objects.create(key='test', status=SELECTIVE) switch = self.gargoyle['test'] request = self.request_factory.get('/', REMOTE_ADDR='192.168.1.1') assert not self.gargoyle.is_active('test', request) switch.add_condition( condition_set=condition_set, field_name='ip_address', condition='192.168.1.1', ) assert self.gargoyle.is_active('test', request) switch.clear_conditions(condition_set=condition_set) switch.add_condition( condition_set=condition_set, field_name='ip_address', condition='127.0.0.1', ) assert not self.gargoyle.is_active('test', request) switch.clear_conditions(condition_set=condition_set) assert not self.gargoyle.is_active('test', request) switch.add_condition( condition_set=condition_set, field_name='percent', condition='50-100', ) assert self.gargoyle.is_active('test', request) assert self.gargoyle.is_active('test', self.request_factory.get('/', REMOTE_ADDR='192.168.1.1')) switch.clear_conditions(condition_set=condition_set) switch.add_condition( condition_set=condition_set, field_name='percent', condition='0-50', ) assert not self.gargoyle.is_active('test', request) assert self.gargoyle.is_active('test', self.request_factory.get('/', REMOTE_ADDR='::1')) switch.clear_conditions(condition_set=condition_set) switch.add_condition( condition_set=condition_set, field_name='percent', condition='0-50', ) assert not self.gargoyle.is_active('test', request) def test_to_dict(self): condition_set = 'gargoyle.builtins.IPAddressConditionSet' switch = Switch.objects.create( label='my switch', description='foo bar baz', key='test', status=SELECTIVE, ) switch.add_condition( manager=self.gargoyle, condition_set=condition_set, field_name='ip_address', condition='192.168.1.1', ) result = switch.to_dict(self.gargoyle) assert result['label'] == 'my switch' assert result['status'] == SELECTIVE assert result['description'] == 'foo bar baz' assert result['key'] == 'test' assert len(result['conditions']) == 1 condition = result['conditions'][0] assert condition['id'] == condition_set assert condition['label'] == 'IP Address' assert len(condition['conditions']) == 1 inner_condition = condition['conditions'][0] assert len(inner_condition) == 4 assert inner_condition[0] == 'ip_address' assert inner_condition[1] == '192.168.1.1' assert inner_condition[2] == '192.168.1.1' assert not inner_condition[3] def test_remove_condition(self): condition_set = 'gargoyle.builtins.UserConditionSet(auth.user)' switch = Switch.objects.create( key='test', status=SELECTIVE, ) switch = self.gargoyle['test'] user5 = User(pk=5, email='*****@*****.**') # inactive if selective with no conditions assert not self.gargoyle.is_active('test', user5) user8771 = User(pk=8771, email='*****@*****.**', is_superuser=True) switch.add_condition( condition_set=condition_set, field_name='is_superuser', condition='1', ) assert self.gargoyle.is_active('test', user8771) # No longer is_active for user5 as we have other conditions assert not self.gargoyle.is_active('test', user5) switch.remove_condition( condition_set=condition_set, field_name='is_superuser', condition='1', ) # back to inactive for everyone with no conditions assert not self.gargoyle.is_active('test', user5) assert not self.gargoyle.is_active('test', user8771) def test_add_condition_empty(self): condition_set = 'gargoyle.builtins.UserConditionSet(auth.user)' switch = Switch.objects.create(key='test', status=SELECTIVE) switch = self.gargoyle['test'] user_empty = User(email='') user_non_empty = User(email='*****@*****.**') switch.add_condition( condition_set=condition_set, field_name='email', condition='', ) assert self.gargoyle.is_active('test', user_empty) assert not self.gargoyle.is_active('test', user_non_empty) def test_switch_defaults(self): """Test that defaults pulled from GARGOYLE_SWITCH_DEFAULTS. Requires SwitchManager to use auto_create. """ assert self.gargoyle.is_active('active_by_default') assert not self.gargoyle.is_active('inactive_by_default') assert self.gargoyle['inactive_by_default'].label == 'Default Inactive' assert self.gargoyle['active_by_default'].label == 'Default Active' active_by_default = self.gargoyle['active_by_default'] active_by_default.status = DISABLED active_by_default.save() assert not self.gargoyle.is_active('active_by_default') def test_invalid_condition(self): condition_set = 'gargoyle.builtins.UserConditionSet(auth.user)' switch = Switch.objects.create( key='test', status=SELECTIVE, ) switch = self.gargoyle['test'] user5 = User(pk=5, email='*****@*****.**') # inactive if selective with no conditions assert not self.gargoyle.is_active('test', user5) user8771 = User(pk=8771, email='*****@*****.**', is_superuser=True) switch.add_condition( condition_set=condition_set, field_name='foo', condition='1', ) assert not self.gargoyle.is_active('test', user8771) def test_inheritance(self): condition_set = 'gargoyle.builtins.UserConditionSet(auth.user)' # we need a better API for this (model dict isnt cutting it) switch = Switch.objects.create(key='test', status=SELECTIVE) switch = self.gargoyle['test'] switch.add_condition( condition_set=condition_set, field_name='percent', condition='0-50', ) switch = Switch.objects.create(key='test:child', status=INHERIT) switch = self.gargoyle['test'] user = User(pk=5) assert self.gargoyle.is_active('test:child', user) user = User(pk=8771) assert not self.gargoyle.is_active('test:child', user) switch = self.gargoyle['test'] switch.status = DISABLED user = User(pk=5) assert not self.gargoyle.is_active('test:child', user) user = User(pk=8771) assert not self.gargoyle.is_active('test:child', user) switch = self.gargoyle['test'] switch.status = GLOBAL user = User(pk=5) assert self.gargoyle.is_active('test:child', user) user = User(pk=8771) assert self.gargoyle.is_active('test:child', user) def test_parent_override_child_state(self): Switch.objects.create(key='test', status=DISABLED) Switch.objects.create(key='test:child', status=GLOBAL) assert not self.gargoyle.is_active('test:child') def test_child_state_is_used(self): Switch.objects.create(key='test', status=GLOBAL) Switch.objects.create(key='test:child', status=DISABLED) assert not self.gargoyle.is_active('test:child') def test_parent_override_child_condition(self): condition_set = 'gargoyle.builtins.UserConditionSet(auth.user)' Switch.objects.create(key='test', status=SELECTIVE) parent = self.gargoyle['test'] parent.add_condition( condition_set=condition_set, field_name='username', condition='bob', ) Switch.objects.create(key='test:child', status=GLOBAL) user = User(username='******') assert self.gargoyle.is_active('test:child', user) user = User(username='******') assert not self.gargoyle.is_active('test:child', user) assert not self.gargoyle.is_active('test:child') def test_child_condition_differing_than_parent_loses(self): condition_set = 'gargoyle.builtins.UserConditionSet(auth.user)' Switch.objects.create(key='test', status=SELECTIVE) parent = self.gargoyle['test'] parent.add_condition( condition_set=condition_set, field_name='username', condition='bob', ) Switch.objects.create(key='test:child', status=SELECTIVE) child = self.gargoyle['test:child'] child.add_condition( condition_set=condition_set, field_name='username', condition='joe', ) user = User(username='******') assert not self.gargoyle.is_active('test:child', user) user = User(username='******') assert not self.gargoyle.is_active('test:child', user) user = User(username='******') assert not self.gargoyle.is_active('test:child', user) assert not self.gargoyle.is_active('test:child') def test_child_condition_including_parent_wins(self): condition_set = 'gargoyle.builtins.UserConditionSet(auth.user)' Switch.objects.create(key='test', status=SELECTIVE) parent = self.gargoyle['test'] parent.add_condition( condition_set=condition_set, field_name='username', condition='bob', ) Switch.objects.create(key='test:child', status=SELECTIVE) child = self.gargoyle['test:child'] child.add_condition( condition_set=condition_set, field_name='username', condition='bob', ) child.add_condition( condition_set=condition_set, field_name='username', condition='joe', ) user = User(username='******') assert self.gargoyle.is_active('test:child', user) user = User(username='******') assert not self.gargoyle.is_active('test:child', user) user = User(username='******') assert not self.gargoyle.is_active('test:child', user) assert not self.gargoyle.is_active('test:child')