123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382 |
- from __future__ import absolute_import
- import pickle
- import six
- from django.db import connection, models
- from django.db.models import F
- from django.test import TestCase
- from bitfield import Bit, BitField, BitHandler
- from bitfield.compat import bitand, bitor
- from .forms import BitFieldTestModelForm
- from .models import BitFieldTestModel
- class BitHandlerTest(TestCase):
- def test_comparison(self):
- bithandler_1 = BitHandler(0, ('FLAG_0', 'FLAG_1', 'FLAG_2', 'FLAG_3'))
- bithandler_2 = BitHandler(1, ('FLAG_0', 'FLAG_1', 'FLAG_2', 'FLAG_3'))
- bithandler_3 = BitHandler(0, ('FLAG_0', 'FLAG_1', 'FLAG_2', 'FLAG_3'))
- assert bithandler_1 == bithandler_1
- assert bithandler_1 != bithandler_2
- assert bithandler_1 == bithandler_3
- def test_defaults(self):
- bithandler = BitHandler(0, ('FLAG_0', 'FLAG_1', 'FLAG_2', 'FLAG_3'))
- # Default value of 0.
- self.assertEquals(int(bithandler), 0)
- # Test bit numbers.
- self.assertEquals(int(bithandler.FLAG_0.number), 0)
- self.assertEquals(int(bithandler.FLAG_1.number), 1)
- self.assertEquals(int(bithandler.FLAG_2.number), 2)
- self.assertEquals(int(bithandler.FLAG_3.number), 3)
- # Negative test non-existant key.
- self.assertRaises(AttributeError, lambda: bithandler.FLAG_4)
- # Test bool().
- self.assertEquals(bool(bithandler.FLAG_0), False)
- self.assertEquals(bool(bithandler.FLAG_1), False)
- self.assertEquals(bool(bithandler.FLAG_2), False)
- self.assertEquals(bool(bithandler.FLAG_3), False)
- def test_nonzero_default(self):
- bithandler = BitHandler(1, ('FLAG_0', 'FLAG_1', 'FLAG_2', 'FLAG_3'))
- self.assertEquals(bool(bithandler.FLAG_0), True)
- self.assertEquals(bool(bithandler.FLAG_1), False)
- self.assertEquals(bool(bithandler.FLAG_2), False)
- self.assertEquals(bool(bithandler.FLAG_3), False)
- bithandler = BitHandler(2, ('FLAG_0', 'FLAG_1', 'FLAG_2', 'FLAG_3'))
- self.assertEquals(bool(bithandler.FLAG_0), False)
- self.assertEquals(bool(bithandler.FLAG_1), True)
- self.assertEquals(bool(bithandler.FLAG_2), False)
- self.assertEquals(bool(bithandler.FLAG_3), False)
- bithandler = BitHandler(3, ('FLAG_0', 'FLAG_1', 'FLAG_2', 'FLAG_3'))
- self.assertEquals(bool(bithandler.FLAG_0), True)
- self.assertEquals(bool(bithandler.FLAG_1), True)
- self.assertEquals(bool(bithandler.FLAG_2), False)
- self.assertEquals(bool(bithandler.FLAG_3), False)
- bithandler = BitHandler(4, ('FLAG_0', 'FLAG_1', 'FLAG_2', 'FLAG_3'))
- self.assertEquals(bool(bithandler.FLAG_0), False)
- self.assertEquals(bool(bithandler.FLAG_1), False)
- self.assertEquals(bool(bithandler.FLAG_2), True)
- self.assertEquals(bool(bithandler.FLAG_3), False)
- def test_mutation(self):
- bithandler = BitHandler(0, ('FLAG_0', 'FLAG_1', 'FLAG_2', 'FLAG_3'))
- self.assertEquals(bool(bithandler.FLAG_0), False)
- self.assertEquals(bool(bithandler.FLAG_1), False)
- self.assertEquals(bool(bithandler.FLAG_2), False)
- self.assertEquals(bool(bithandler.FLAG_3), False)
- bithandler = BitHandler(bithandler | 1, bithandler._keys)
- self.assertEquals(bool(bithandler.FLAG_0), True)
- self.assertEquals(bool(bithandler.FLAG_1), False)
- self.assertEquals(bool(bithandler.FLAG_2), False)
- self.assertEquals(bool(bithandler.FLAG_3), False)
- bithandler ^= 3
- self.assertEquals(int(bithandler), 2)
- self.assertEquals(bool(bithandler & 1), False)
- bithandler.FLAG_0 = False
- self.assertEquals(bithandler.FLAG_0, False)
- bithandler.FLAG_1 = True
- self.assertEquals(bithandler.FLAG_0, False)
- self.assertEquals(bithandler.FLAG_1, True)
- bithandler.FLAG_2 = False
- self.assertEquals(bithandler.FLAG_0, False)
- self.assertEquals(bithandler.FLAG_1, True)
- self.assertEquals(bithandler.FLAG_2, False)
- class BitTest(TestCase):
- def test_int(self):
- bit = Bit(0)
- self.assertEquals(int(bit), 1)
- self.assertEquals(bool(bit), True)
- self.assertFalse(not bit)
- def test_comparison(self):
- self.assertEquals(Bit(0), Bit(0))
- self.assertNotEquals(Bit(1), Bit(0))
- self.assertNotEquals(Bit(0, 0), Bit(0, 1))
- self.assertEquals(Bit(0, 1), Bit(0, 1))
- self.assertEquals(Bit(0), 1)
- def test_and(self):
- self.assertEquals(1 & Bit(2), 0)
- self.assertEquals(1 & Bit(0), 1)
- self.assertEquals(1 & ~Bit(0), 0)
- self.assertEquals(Bit(0) & Bit(2), 0)
- self.assertEquals(Bit(0) & Bit(0), 1)
- self.assertEquals(Bit(0) & ~Bit(0), 0)
- def test_or(self):
- self.assertEquals(1 | Bit(2), 5)
- self.assertEquals(1 | Bit(5), 33)
- self.assertEquals(1 | ~Bit(2), -5)
- self.assertEquals(Bit(0) | Bit(2), 5)
- self.assertEquals(Bit(0) | Bit(5), 33)
- self.assertEquals(Bit(0) | ~Bit(2), -5)
- def test_xor(self):
- self.assertEquals(1 ^ Bit(2), 5)
- self.assertEquals(1 ^ Bit(0), 0)
- self.assertEquals(1 ^ Bit(1), 3)
- self.assertEquals(1 ^ Bit(5), 33)
- self.assertEquals(1 ^ ~Bit(2), -6)
- self.assertEquals(Bit(0) ^ Bit(2), 5)
- self.assertEquals(Bit(0) ^ Bit(0), 0)
- self.assertEquals(Bit(0) ^ Bit(1), 3)
- self.assertEquals(Bit(0) ^ Bit(5), 33)
- self.assertEquals(Bit(0) ^ ~Bit(2), -6)
- class BitFieldTest(TestCase):
- def test_basic(self):
- # Create instance and make sure flags are working properly.
- instance = BitFieldTestModel.objects.create(flags=1)
- self.assertTrue(instance.flags.FLAG_0)
- self.assertFalse(instance.flags.FLAG_1)
- self.assertFalse(instance.flags.FLAG_2)
- self.assertFalse(instance.flags.FLAG_3)
- def test_regression_1425(self):
- # Creating new instances shouldn't allow negative values.
- instance = BitFieldTestModel.objects.create(flags=-1)
- self.assertEqual(instance.flags._value, 15)
- self.assertTrue(instance.flags.FLAG_0)
- self.assertTrue(instance.flags.FLAG_1)
- self.assertTrue(instance.flags.FLAG_2)
- self.assertTrue(instance.flags.FLAG_3)
- cursor = connection.cursor()
- flags_field = BitFieldTestModel._meta.get_field('flags')
- flags_db_column = flags_field.db_column or flags_field.name
- cursor.execute(
- "INSERT INTO %s (%s) VALUES (-1)" % (BitFieldTestModel._meta.db_table, flags_db_column)
- )
- # There should only be the one row we inserted through the cursor.
- instance = BitFieldTestModel.objects.get(flags=-1)
- self.assertTrue(instance.flags.FLAG_0)
- self.assertTrue(instance.flags.FLAG_1)
- self.assertTrue(instance.flags.FLAG_2)
- self.assertTrue(instance.flags.FLAG_3)
- instance.save()
- self.assertEqual(BitFieldTestModel.objects.filter(flags=15).count(), 2)
- self.assertEqual(BitFieldTestModel.objects.filter(flags__lt=0).count(), 0)
- def test_select(self):
- BitFieldTestModel.objects.create(flags=3)
- self.assertTrue(
- BitFieldTestModel.objects.filter(flags=BitFieldTestModel.flags.FLAG_1).exists()
- )
- self.assertTrue(
- BitFieldTestModel.objects.filter(flags=BitFieldTestModel.flags.FLAG_0).exists()
- )
- self.assertFalse(
- BitFieldTestModel.objects.exclude(flags=BitFieldTestModel.flags.FLAG_0).exists()
- )
- self.assertFalse(
- BitFieldTestModel.objects.exclude(flags=BitFieldTestModel.flags.FLAG_1).exists()
- )
- def test_update(self):
- instance = BitFieldTestModel.objects.create(flags=0)
- self.assertFalse(instance.flags.FLAG_0)
- BitFieldTestModel.objects.filter(pk=instance.pk).update(
- flags=bitor(F('flags'), BitFieldTestModel.flags.FLAG_1)
- )
- instance = BitFieldTestModel.objects.get(pk=instance.pk)
- self.assertTrue(instance.flags.FLAG_1)
- BitFieldTestModel.objects.filter(pk=instance.pk).update(
- flags=bitor(
- F('flags'), ((~BitFieldTestModel.flags.FLAG_0 | BitFieldTestModel.flags.FLAG_3))
- )
- )
- instance = BitFieldTestModel.objects.get(pk=instance.pk)
- self.assertFalse(instance.flags.FLAG_0)
- self.assertTrue(instance.flags.FLAG_1)
- self.assertTrue(instance.flags.FLAG_3)
- self.assertFalse(
- BitFieldTestModel.objects.filter(flags=BitFieldTestModel.flags.FLAG_0).exists()
- )
- BitFieldTestModel.objects.filter(pk=instance.pk).update(
- flags=bitand(F('flags'), ~BitFieldTestModel.flags.FLAG_3)
- )
- instance = BitFieldTestModel.objects.get(pk=instance.pk)
- self.assertFalse(instance.flags.FLAG_0)
- self.assertTrue(instance.flags.FLAG_1)
- self.assertFalse(instance.flags.FLAG_3)
- def test_update_with_handler(self):
- instance = BitFieldTestModel.objects.create(flags=0)
- self.assertFalse(instance.flags.FLAG_0)
- instance.flags.FLAG_1 = True
- BitFieldTestModel.objects.filter(pk=instance.pk).update(
- flags=bitor(F('flags'), instance.flags)
- )
- instance = BitFieldTestModel.objects.get(pk=instance.pk)
- self.assertTrue(instance.flags.FLAG_1)
- def test_negate(self):
- BitFieldTestModel.objects.create(
- flags=BitFieldTestModel.flags.FLAG_0 | BitFieldTestModel.flags.FLAG_1
- )
- BitFieldTestModel.objects.create(flags=BitFieldTestModel.flags.FLAG_1)
- self.assertEqual(
- BitFieldTestModel.objects.filter(flags=~BitFieldTestModel.flags.FLAG_0).count(), 1
- )
- self.assertEqual(
- BitFieldTestModel.objects.filter(flags=~BitFieldTestModel.flags.FLAG_1).count(), 0
- )
- self.assertEqual(
- BitFieldTestModel.objects.filter(flags=~BitFieldTestModel.flags.FLAG_2).count(), 2
- )
- def test_default_value(self):
- instance = BitFieldTestModel.objects.create()
- self.assertTrue(instance.flags.FLAG_0)
- self.assertTrue(instance.flags.FLAG_1)
- self.assertFalse(instance.flags.FLAG_2)
- self.assertFalse(instance.flags.FLAG_3)
- def test_binary_capacity(self):
- import math
- from django.db.models.fields import BigIntegerField
- # Local maximum value, slow canonical algorithm
- MAX_COUNT = int(math.floor(math.log(BigIntegerField.MAX_BIGINT, 2)))
- # Big flags list
- flags = ['f' + six.text_type(i) for i in range(100)]
- try:
- BitField(flags=flags[:MAX_COUNT])
- except ValueError:
- self.fail("It should work well with these flags")
- self.assertRaises(ValueError, BitField, flags=flags[:(MAX_COUNT + 1)])
- def test_dictionary_init(self):
- flags = {
- 0: 'zero',
- 1: 'first',
- 10: 'tenth',
- 2: 'second',
- 'wrongkey': 'wrongkey',
- 100: 'bigkey',
- -100: 'smallkey',
- }
- try:
- bf = BitField(flags)
- except ValueError:
- self.fail("It should work well with these flags")
- self.assertEquals(
- bf.flags, ['zero', 'first', 'second', '', '', '', '', '', '', '', 'tenth']
- )
- self.assertRaises(ValueError, BitField, flags={})
- self.assertRaises(ValueError, BitField, flags={'wrongkey': 'wrongkey'})
- self.assertRaises(ValueError, BitField, flags={'1': 'non_int_key'})
- def test_defaults_as_key_names(self):
- class TestModel(models.Model):
- flags = BitField(
- flags=('FLAG_0', 'FLAG_1', 'FLAG_2', 'FLAG_3', ), default=('FLAG_1', 'FLAG_2')
- )
- field = TestModel._meta.get_field('flags')
- self.assertEquals(field.default, TestModel.flags.FLAG_1 | TestModel.flags.FLAG_2)
- class BitFieldSerializationTest(TestCase):
- def test_can_unserialize_bithandler(self):
- bf = BitFieldTestModel()
- bf.flags.FLAG_0 = 1
- bf.flags.FLAG_1 = 0
- data = pickle.dumps(bf)
- inst = pickle.loads(data)
- self.assertTrue(inst.flags.FLAG_0)
- self.assertFalse(inst.flags.FLAG_1)
- def test_pickle_integration(self):
- inst = BitFieldTestModel.objects.create(flags=1)
- data = pickle.dumps(inst)
- inst = pickle.loads(data)
- self.assertEquals(type(inst.flags), BitHandler)
- self.assertEquals(int(inst.flags), 1)
- def test_added_field(self):
- bf = BitFieldTestModel()
- bf.flags.FLAG_0 = 1
- bf.flags.FLAG_1 = 0
- bf.flags.FLAG_3 = 0
- data = pickle.dumps(bf)
- inst = pickle.loads(data)
- self.assertTrue('FLAG_3' in inst.flags.keys())
- class BitFormFieldTest(TestCase):
- def test_form_new_invalid(self):
- invalid_data_dicts = [
- {
- 'flags': ['FLAG_0', 'FLAG_FLAG']
- }, {
- 'flags': ['FLAG_4']
- }, {
- 'flags': [1, 2]
- }
- ]
- for invalid_data in invalid_data_dicts:
- form = BitFieldTestModelForm(data=invalid_data)
- self.assertFalse(form.is_valid())
- def test_form_new(self):
- data_dicts = [{'flags': ['FLAG_0', 'FLAG_1']}, {'flags': ['FLAG_3']}, {'flags': []}, {}]
- for data in data_dicts:
- form = BitFieldTestModelForm(data=data)
- self.failUnless(form.is_valid())
- instance = form.save()
- flags = data['flags'] if 'flags' in data else []
- for k in BitFieldTestModel.flags:
- self.assertEquals(bool(getattr(instance.flags, k)), k in flags)
- def test_form_update(self):
- instance = BitFieldTestModel.objects.create(flags=0)
- for k in BitFieldTestModel.flags:
- self.assertFalse(bool(getattr(instance.flags, k)))
- data = {'flags': ['FLAG_0', 'FLAG_1']}
- form = BitFieldTestModelForm(data=data, instance=instance)
- self.failUnless(form.is_valid())
- instance = form.save()
- for k in BitFieldTestModel.flags:
- self.assertEquals(bool(getattr(instance.flags, k)), k in data['flags'])
- data = {'flags': ['FLAG_2', 'FLAG_3']}
- form = BitFieldTestModelForm(data=data, instance=instance)
- self.failUnless(form.is_valid())
- instance = form.save()
- for k in BitFieldTestModel.flags:
- self.assertEquals(bool(getattr(instance.flags, k)), k in data['flags'])
- data = {'flags': []}
- form = BitFieldTestModelForm(data=data, instance=instance)
- self.failUnless(form.is_valid())
- instance = form.save()
- for k in BitFieldTestModel.flags:
- self.assertFalse(bool(getattr(instance.flags, k)))
|