tests.py 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418
  1. from __future__ import absolute_import
  2. import pickle
  3. import six
  4. from django.db import connection, models
  5. from django.db.models import F
  6. from django.test import TestCase
  7. from bitfield import Bit, BitField, BitHandler
  8. from bitfield.compat import bitand, bitor
  9. from .forms import BitFieldTestModelForm
  10. from .models import BitFieldTestModel, CompositeBitFieldTestModel
  11. class BitHandlerTest(TestCase):
  12. def test_comparison(self):
  13. bithandler_1 = BitHandler(0, ('FLAG_0', 'FLAG_1', 'FLAG_2', 'FLAG_3'))
  14. bithandler_2 = BitHandler(1, ('FLAG_0', 'FLAG_1', 'FLAG_2', 'FLAG_3'))
  15. bithandler_3 = BitHandler(0, ('FLAG_0', 'FLAG_1', 'FLAG_2', 'FLAG_3'))
  16. assert bithandler_1 == bithandler_1
  17. assert bithandler_1 != bithandler_2
  18. assert bithandler_1 == bithandler_3
  19. def test_defaults(self):
  20. bithandler = BitHandler(0, ('FLAG_0', 'FLAG_1', 'FLAG_2', 'FLAG_3'))
  21. # Default value of 0.
  22. self.assertEquals(int(bithandler), 0)
  23. # Test bit numbers.
  24. self.assertEquals(int(bithandler.FLAG_0.number), 0)
  25. self.assertEquals(int(bithandler.FLAG_1.number), 1)
  26. self.assertEquals(int(bithandler.FLAG_2.number), 2)
  27. self.assertEquals(int(bithandler.FLAG_3.number), 3)
  28. # Negative test non-existant key.
  29. self.assertRaises(AttributeError, lambda: bithandler.FLAG_4)
  30. # Test bool().
  31. self.assertEquals(bool(bithandler.FLAG_0), False)
  32. self.assertEquals(bool(bithandler.FLAG_1), False)
  33. self.assertEquals(bool(bithandler.FLAG_2), False)
  34. self.assertEquals(bool(bithandler.FLAG_3), False)
  35. def test_nonzero_default(self):
  36. bithandler = BitHandler(1, ('FLAG_0', 'FLAG_1', 'FLAG_2', 'FLAG_3'))
  37. self.assertEquals(bool(bithandler.FLAG_0), True)
  38. self.assertEquals(bool(bithandler.FLAG_1), False)
  39. self.assertEquals(bool(bithandler.FLAG_2), False)
  40. self.assertEquals(bool(bithandler.FLAG_3), False)
  41. bithandler = BitHandler(2, ('FLAG_0', 'FLAG_1', 'FLAG_2', 'FLAG_3'))
  42. self.assertEquals(bool(bithandler.FLAG_0), False)
  43. self.assertEquals(bool(bithandler.FLAG_1), True)
  44. self.assertEquals(bool(bithandler.FLAG_2), False)
  45. self.assertEquals(bool(bithandler.FLAG_3), False)
  46. bithandler = BitHandler(3, ('FLAG_0', 'FLAG_1', 'FLAG_2', 'FLAG_3'))
  47. self.assertEquals(bool(bithandler.FLAG_0), True)
  48. self.assertEquals(bool(bithandler.FLAG_1), True)
  49. self.assertEquals(bool(bithandler.FLAG_2), False)
  50. self.assertEquals(bool(bithandler.FLAG_3), False)
  51. bithandler = BitHandler(4, ('FLAG_0', 'FLAG_1', 'FLAG_2', 'FLAG_3'))
  52. self.assertEquals(bool(bithandler.FLAG_0), False)
  53. self.assertEquals(bool(bithandler.FLAG_1), False)
  54. self.assertEquals(bool(bithandler.FLAG_2), True)
  55. self.assertEquals(bool(bithandler.FLAG_3), False)
  56. def test_mutation(self):
  57. bithandler = BitHandler(0, ('FLAG_0', 'FLAG_1', 'FLAG_2', 'FLAG_3'))
  58. self.assertEquals(bool(bithandler.FLAG_0), False)
  59. self.assertEquals(bool(bithandler.FLAG_1), False)
  60. self.assertEquals(bool(bithandler.FLAG_2), False)
  61. self.assertEquals(bool(bithandler.FLAG_3), False)
  62. bithandler = BitHandler(bithandler | 1, bithandler._keys)
  63. self.assertEquals(bool(bithandler.FLAG_0), True)
  64. self.assertEquals(bool(bithandler.FLAG_1), False)
  65. self.assertEquals(bool(bithandler.FLAG_2), False)
  66. self.assertEquals(bool(bithandler.FLAG_3), False)
  67. bithandler ^= 3
  68. self.assertEquals(int(bithandler), 2)
  69. self.assertEquals(bool(bithandler & 1), False)
  70. bithandler.FLAG_0 = False
  71. self.assertEquals(bithandler.FLAG_0, False)
  72. bithandler.FLAG_1 = True
  73. self.assertEquals(bithandler.FLAG_0, False)
  74. self.assertEquals(bithandler.FLAG_1, True)
  75. bithandler.FLAG_2 = False
  76. self.assertEquals(bithandler.FLAG_0, False)
  77. self.assertEquals(bithandler.FLAG_1, True)
  78. self.assertEquals(bithandler.FLAG_2, False)
  79. class BitTest(TestCase):
  80. def test_int(self):
  81. bit = Bit(0)
  82. self.assertEquals(int(bit), 1)
  83. self.assertEquals(bool(bit), True)
  84. self.assertFalse(not bit)
  85. def test_comparison(self):
  86. self.assertEquals(Bit(0), Bit(0))
  87. self.assertNotEquals(Bit(1), Bit(0))
  88. self.assertNotEquals(Bit(0, 0), Bit(0, 1))
  89. self.assertEquals(Bit(0, 1), Bit(0, 1))
  90. self.assertEquals(Bit(0), 1)
  91. def test_and(self):
  92. self.assertEquals(1 & Bit(2), 0)
  93. self.assertEquals(1 & Bit(0), 1)
  94. self.assertEquals(1 & ~Bit(0), 0)
  95. self.assertEquals(Bit(0) & Bit(2), 0)
  96. self.assertEquals(Bit(0) & Bit(0), 1)
  97. self.assertEquals(Bit(0) & ~Bit(0), 0)
  98. def test_or(self):
  99. self.assertEquals(1 | Bit(2), 5)
  100. self.assertEquals(1 | Bit(5), 33)
  101. self.assertEquals(1 | ~Bit(2), -5)
  102. self.assertEquals(Bit(0) | Bit(2), 5)
  103. self.assertEquals(Bit(0) | Bit(5), 33)
  104. self.assertEquals(Bit(0) | ~Bit(2), -5)
  105. def test_xor(self):
  106. self.assertEquals(1 ^ Bit(2), 5)
  107. self.assertEquals(1 ^ Bit(0), 0)
  108. self.assertEquals(1 ^ Bit(1), 3)
  109. self.assertEquals(1 ^ Bit(5), 33)
  110. self.assertEquals(1 ^ ~Bit(2), -6)
  111. self.assertEquals(Bit(0) ^ Bit(2), 5)
  112. self.assertEquals(Bit(0) ^ Bit(0), 0)
  113. self.assertEquals(Bit(0) ^ Bit(1), 3)
  114. self.assertEquals(Bit(0) ^ Bit(5), 33)
  115. self.assertEquals(Bit(0) ^ ~Bit(2), -6)
  116. class BitFieldTest(TestCase):
  117. def test_basic(self):
  118. # Create instance and make sure flags are working properly.
  119. instance = BitFieldTestModel.objects.create(flags=1)
  120. self.assertTrue(instance.flags.FLAG_0)
  121. self.assertFalse(instance.flags.FLAG_1)
  122. self.assertFalse(instance.flags.FLAG_2)
  123. self.assertFalse(instance.flags.FLAG_3)
  124. def test_regression_1425(self):
  125. # Creating new instances shouldn't allow negative values.
  126. instance = BitFieldTestModel.objects.create(flags=-1)
  127. self.assertEqual(instance.flags._value, 15)
  128. self.assertTrue(instance.flags.FLAG_0)
  129. self.assertTrue(instance.flags.FLAG_1)
  130. self.assertTrue(instance.flags.FLAG_2)
  131. self.assertTrue(instance.flags.FLAG_3)
  132. cursor = connection.cursor()
  133. flags_field = BitFieldTestModel._meta.get_field('flags')
  134. flags_db_column = flags_field.db_column or flags_field.name
  135. cursor.execute(
  136. "INSERT INTO %s (%s) VALUES (-1)" % (BitFieldTestModel._meta.db_table, flags_db_column)
  137. )
  138. # There should only be the one row we inserted through the cursor.
  139. instance = BitFieldTestModel.objects.get(flags=-1)
  140. self.assertTrue(instance.flags.FLAG_0)
  141. self.assertTrue(instance.flags.FLAG_1)
  142. self.assertTrue(instance.flags.FLAG_2)
  143. self.assertTrue(instance.flags.FLAG_3)
  144. instance.save()
  145. self.assertEqual(BitFieldTestModel.objects.filter(flags=15).count(), 2)
  146. self.assertEqual(BitFieldTestModel.objects.filter(flags__lt=0).count(), 0)
  147. def test_select(self):
  148. BitFieldTestModel.objects.create(flags=3)
  149. self.assertTrue(
  150. BitFieldTestModel.objects.filter(flags=BitFieldTestModel.flags.FLAG_1).exists()
  151. )
  152. self.assertTrue(
  153. BitFieldTestModel.objects.filter(flags=BitFieldTestModel.flags.FLAG_0).exists()
  154. )
  155. self.assertFalse(
  156. BitFieldTestModel.objects.exclude(flags=BitFieldTestModel.flags.FLAG_0).exists()
  157. )
  158. self.assertFalse(
  159. BitFieldTestModel.objects.exclude(flags=BitFieldTestModel.flags.FLAG_1).exists()
  160. )
  161. def test_update(self):
  162. instance = BitFieldTestModel.objects.create(flags=0)
  163. self.assertFalse(instance.flags.FLAG_0)
  164. BitFieldTestModel.objects.filter(pk=instance.pk).update(
  165. flags=bitor(F('flags'), BitFieldTestModel.flags.FLAG_1)
  166. )
  167. instance = BitFieldTestModel.objects.get(pk=instance.pk)
  168. self.assertTrue(instance.flags.FLAG_1)
  169. BitFieldTestModel.objects.filter(pk=instance.pk).update(
  170. flags=bitor(
  171. F('flags'), ((~BitFieldTestModel.flags.FLAG_0 | BitFieldTestModel.flags.FLAG_3))
  172. )
  173. )
  174. instance = BitFieldTestModel.objects.get(pk=instance.pk)
  175. self.assertFalse(instance.flags.FLAG_0)
  176. self.assertTrue(instance.flags.FLAG_1)
  177. self.assertTrue(instance.flags.FLAG_3)
  178. self.assertFalse(
  179. BitFieldTestModel.objects.filter(flags=BitFieldTestModel.flags.FLAG_0).exists()
  180. )
  181. BitFieldTestModel.objects.filter(pk=instance.pk).update(
  182. flags=bitand(F('flags'), ~BitFieldTestModel.flags.FLAG_3)
  183. )
  184. instance = BitFieldTestModel.objects.get(pk=instance.pk)
  185. self.assertFalse(instance.flags.FLAG_0)
  186. self.assertTrue(instance.flags.FLAG_1)
  187. self.assertFalse(instance.flags.FLAG_3)
  188. def test_update_with_handler(self):
  189. instance = BitFieldTestModel.objects.create(flags=0)
  190. self.assertFalse(instance.flags.FLAG_0)
  191. instance.flags.FLAG_1 = True
  192. BitFieldTestModel.objects.filter(pk=instance.pk).update(
  193. flags=bitor(F('flags'), instance.flags)
  194. )
  195. instance = BitFieldTestModel.objects.get(pk=instance.pk)
  196. self.assertTrue(instance.flags.FLAG_1)
  197. def test_negate(self):
  198. BitFieldTestModel.objects.create(
  199. flags=BitFieldTestModel.flags.FLAG_0 | BitFieldTestModel.flags.FLAG_1
  200. )
  201. BitFieldTestModel.objects.create(flags=BitFieldTestModel.flags.FLAG_1)
  202. self.assertEqual(
  203. BitFieldTestModel.objects.filter(flags=~BitFieldTestModel.flags.FLAG_0).count(), 1
  204. )
  205. self.assertEqual(
  206. BitFieldTestModel.objects.filter(flags=~BitFieldTestModel.flags.FLAG_1).count(), 0
  207. )
  208. self.assertEqual(
  209. BitFieldTestModel.objects.filter(flags=~BitFieldTestModel.flags.FLAG_2).count(), 2
  210. )
  211. def test_default_value(self):
  212. instance = BitFieldTestModel.objects.create()
  213. self.assertTrue(instance.flags.FLAG_0)
  214. self.assertTrue(instance.flags.FLAG_1)
  215. self.assertFalse(instance.flags.FLAG_2)
  216. self.assertFalse(instance.flags.FLAG_3)
  217. def test_binary_capacity(self):
  218. import math
  219. from django.db.models.fields import BigIntegerField
  220. # Local maximum value, slow canonical algorithm
  221. MAX_COUNT = int(math.floor(math.log(BigIntegerField.MAX_BIGINT, 2)))
  222. # Big flags list
  223. flags = ['f' + six.text_type(i) for i in range(100)]
  224. try:
  225. BitField(flags=flags[:MAX_COUNT])
  226. except ValueError:
  227. self.fail("It should work well with these flags")
  228. self.assertRaises(ValueError, BitField, flags=flags[:(MAX_COUNT + 1)])
  229. def test_dictionary_init(self):
  230. flags = {
  231. 0: 'zero',
  232. 1: 'first',
  233. 10: 'tenth',
  234. 2: 'second',
  235. 'wrongkey': 'wrongkey',
  236. 100: 'bigkey',
  237. -100: 'smallkey',
  238. }
  239. try:
  240. bf = BitField(flags)
  241. except ValueError:
  242. self.fail("It should work well with these flags")
  243. self.assertEquals(
  244. bf.flags, ['zero', 'first', 'second', '', '', '', '', '', '', '', 'tenth']
  245. )
  246. self.assertRaises(ValueError, BitField, flags={})
  247. self.assertRaises(ValueError, BitField, flags={'wrongkey': 'wrongkey'})
  248. self.assertRaises(ValueError, BitField, flags={'1': 'non_int_key'})
  249. def test_defaults_as_key_names(self):
  250. class TestModel(models.Model):
  251. flags = BitField(
  252. flags=('FLAG_0', 'FLAG_1', 'FLAG_2', 'FLAG_3', ), default=('FLAG_1', 'FLAG_2')
  253. )
  254. field = TestModel._meta.get_field('flags')
  255. self.assertEquals(field.default, TestModel.flags.FLAG_1 | TestModel.flags.FLAG_2)
  256. class BitFieldSerializationTest(TestCase):
  257. def test_can_unserialize_bithandler(self):
  258. bf = BitFieldTestModel()
  259. bf.flags.FLAG_0 = 1
  260. bf.flags.FLAG_1 = 0
  261. data = pickle.dumps(bf)
  262. inst = pickle.loads(data)
  263. self.assertTrue(inst.flags.FLAG_0)
  264. self.assertFalse(inst.flags.FLAG_1)
  265. def test_pickle_integration(self):
  266. inst = BitFieldTestModel.objects.create(flags=1)
  267. data = pickle.dumps(inst)
  268. inst = pickle.loads(data)
  269. self.assertEquals(type(inst.flags), BitHandler)
  270. self.assertEquals(int(inst.flags), 1)
  271. def test_added_field(self):
  272. bf = BitFieldTestModel()
  273. bf.flags.FLAG_0 = 1
  274. bf.flags.FLAG_1 = 0
  275. bf.flags.FLAG_3 = 0
  276. data = pickle.dumps(bf)
  277. inst = pickle.loads(data)
  278. self.assertTrue('FLAG_3' in inst.flags.keys())
  279. class CompositeBitFieldTest(TestCase):
  280. def test_get_flag(self):
  281. inst = CompositeBitFieldTestModel()
  282. self.assertEqual(inst.flags.FLAG_0, inst.flags_1.FLAG_0)
  283. self.assertEqual(inst.flags.FLAG_4, inst.flags_2.FLAG_4)
  284. self.assertRaises(AttributeError, lambda: inst.flags.flag_NA)
  285. def test_set_flag(self):
  286. inst = CompositeBitFieldTestModel()
  287. flag_0_original = bool(inst.flags.FLAG_0)
  288. self.assertEqual(bool(inst.flags_1.FLAG_0), flag_0_original)
  289. flag_4_original = bool(inst.flags.FLAG_4)
  290. self.assertEqual(bool(inst.flags_2.FLAG_4), flag_4_original)
  291. # flip flags' bits
  292. inst.flags.FLAG_0 = not flag_0_original
  293. inst.flags.FLAG_4 = not flag_4_original
  294. # check to make sure the bit flips took effect
  295. self.assertNotEqual(bool(inst.flags.FLAG_0), flag_0_original)
  296. self.assertNotEqual(bool(inst.flags_1.FLAG_0), flag_0_original)
  297. self.assertNotEqual(bool(inst.flags.FLAG_4), flag_4_original)
  298. self.assertNotEqual(bool(inst.flags_2.FLAG_4), flag_4_original)
  299. def set_flag():
  300. inst.flags.flag_NA = False
  301. self.assertRaises(AttributeError, set_flag)
  302. def test_hasattr(self):
  303. inst = CompositeBitFieldTestModel()
  304. self.assertEqual(hasattr(inst.flags, 'flag_0'), hasattr(inst.flags_1, 'flag_0'))
  305. self.assertEqual(hasattr(inst.flags, 'flag_4'), hasattr(inst.flags_2, 'flag_4'))
  306. class BitFormFieldTest(TestCase):
  307. def test_form_new_invalid(self):
  308. invalid_data_dicts = [
  309. {
  310. 'flags': ['FLAG_0', 'FLAG_FLAG']
  311. }, {
  312. 'flags': ['FLAG_4']
  313. }, {
  314. 'flags': [1, 2]
  315. }
  316. ]
  317. for invalid_data in invalid_data_dicts:
  318. form = BitFieldTestModelForm(data=invalid_data)
  319. self.assertFalse(form.is_valid())
  320. def test_form_new(self):
  321. data_dicts = [{'flags': ['FLAG_0', 'FLAG_1']}, {'flags': ['FLAG_3']}, {'flags': []}, {}]
  322. for data in data_dicts:
  323. form = BitFieldTestModelForm(data=data)
  324. self.failUnless(form.is_valid())
  325. instance = form.save()
  326. flags = data['flags'] if 'flags' in data else []
  327. for k in BitFieldTestModel.flags:
  328. self.assertEquals(bool(getattr(instance.flags, k)), k in flags)
  329. def test_form_update(self):
  330. instance = BitFieldTestModel.objects.create(flags=0)
  331. for k in BitFieldTestModel.flags:
  332. self.assertFalse(bool(getattr(instance.flags, k)))
  333. data = {'flags': ['FLAG_0', 'FLAG_1']}
  334. form = BitFieldTestModelForm(data=data, instance=instance)
  335. self.failUnless(form.is_valid())
  336. instance = form.save()
  337. for k in BitFieldTestModel.flags:
  338. self.assertEquals(bool(getattr(instance.flags, k)), k in data['flags'])
  339. data = {'flags': ['FLAG_2', 'FLAG_3']}
  340. form = BitFieldTestModelForm(data=data, instance=instance)
  341. self.failUnless(form.is_valid())
  342. instance = form.save()
  343. for k in BitFieldTestModel.flags:
  344. self.assertEquals(bool(getattr(instance.flags, k)), k in data['flags'])
  345. data = {'flags': []}
  346. form = BitFieldTestModelForm(data=data, instance=instance)
  347. self.failUnless(form.is_valid())
  348. instance = form.save()
  349. for k in BitFieldTestModel.flags:
  350. self.assertFalse(bool(getattr(instance.flags, k)))