123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379 |
- 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)))
|