/Lib/test/mapping_tests.py

http://unladen-swallow.googlecode.com/ · Python · 676 lines · 524 code · 104 blank · 48 comment · 31 complexity · 5cee0dafa29ae2e28fed912ac2537396 MD5 · raw file

  1. # tests common to dict and UserDict
  2. import unittest
  3. import UserDict
  4. class BasicTestMappingProtocol(unittest.TestCase):
  5. # This base class can be used to check that an object conforms to the
  6. # mapping protocol
  7. # Functions that can be useful to override to adapt to dictionary
  8. # semantics
  9. type2test = None # which class is being tested (overwrite in subclasses)
  10. def _reference(self):
  11. """Return a dictionary of values which are invariant by storage
  12. in the object under test."""
  13. return {1:2, "key1":"value1", "key2":(1,2,3)}
  14. def _empty_mapping(self):
  15. """Return an empty mapping object"""
  16. return self.type2test()
  17. def _full_mapping(self, data):
  18. """Return a mapping object with the value contained in data
  19. dictionary"""
  20. x = self._empty_mapping()
  21. for key, value in data.items():
  22. x[key] = value
  23. return x
  24. def __init__(self, *args, **kw):
  25. unittest.TestCase.__init__(self, *args, **kw)
  26. self.reference = self._reference().copy()
  27. # A (key, value) pair not in the mapping
  28. key, value = self.reference.popitem()
  29. self.other = {key:value}
  30. # A (key, value) pair in the mapping
  31. key, value = self.reference.popitem()
  32. self.inmapping = {key:value}
  33. self.reference[key] = value
  34. def test_read(self):
  35. # Test for read only operations on mapping
  36. p = self._empty_mapping()
  37. p1 = dict(p) #workaround for singleton objects
  38. d = self._full_mapping(self.reference)
  39. if d is p:
  40. p = p1
  41. #Indexing
  42. for key, value in self.reference.items():
  43. self.assertEqual(d[key], value)
  44. knownkey = self.other.keys()[0]
  45. self.failUnlessRaises(KeyError, lambda:d[knownkey])
  46. #len
  47. self.assertEqual(len(p), 0)
  48. self.assertEqual(len(d), len(self.reference))
  49. #has_key
  50. for k in self.reference:
  51. self.assert_(d.has_key(k))
  52. self.assert_(k in d)
  53. for k in self.other:
  54. self.failIf(d.has_key(k))
  55. self.failIf(k in d)
  56. #cmp
  57. self.assertEqual(cmp(p,p), 0)
  58. self.assertEqual(cmp(d,d), 0)
  59. self.assertEqual(cmp(p,d), -1)
  60. self.assertEqual(cmp(d,p), 1)
  61. #__non__zero__
  62. if p: self.fail("Empty mapping must compare to False")
  63. if not d: self.fail("Full mapping must compare to True")
  64. # keys(), items(), iterkeys() ...
  65. def check_iterandlist(iter, lst, ref):
  66. self.assert_(hasattr(iter, 'next'))
  67. self.assert_(hasattr(iter, '__iter__'))
  68. x = list(iter)
  69. self.assert_(set(x)==set(lst)==set(ref))
  70. check_iterandlist(d.iterkeys(), d.keys(), self.reference.keys())
  71. check_iterandlist(iter(d), d.keys(), self.reference.keys())
  72. check_iterandlist(d.itervalues(), d.values(), self.reference.values())
  73. check_iterandlist(d.iteritems(), d.items(), self.reference.items())
  74. #get
  75. key, value = d.iteritems().next()
  76. knownkey, knownvalue = self.other.iteritems().next()
  77. self.assertEqual(d.get(key, knownvalue), value)
  78. self.assertEqual(d.get(knownkey, knownvalue), knownvalue)
  79. self.failIf(knownkey in d)
  80. def test_write(self):
  81. # Test for write operations on mapping
  82. p = self._empty_mapping()
  83. #Indexing
  84. for key, value in self.reference.items():
  85. p[key] = value
  86. self.assertEqual(p[key], value)
  87. for key in self.reference.keys():
  88. del p[key]
  89. self.failUnlessRaises(KeyError, lambda:p[key])
  90. p = self._empty_mapping()
  91. #update
  92. p.update(self.reference)
  93. self.assertEqual(dict(p), self.reference)
  94. items = p.items()
  95. p = self._empty_mapping()
  96. p.update(items)
  97. self.assertEqual(dict(p), self.reference)
  98. d = self._full_mapping(self.reference)
  99. #setdefault
  100. key, value = d.iteritems().next()
  101. knownkey, knownvalue = self.other.iteritems().next()
  102. self.assertEqual(d.setdefault(key, knownvalue), value)
  103. self.assertEqual(d[key], value)
  104. self.assertEqual(d.setdefault(knownkey, knownvalue), knownvalue)
  105. self.assertEqual(d[knownkey], knownvalue)
  106. #pop
  107. self.assertEqual(d.pop(knownkey), knownvalue)
  108. self.failIf(knownkey in d)
  109. self.assertRaises(KeyError, d.pop, knownkey)
  110. default = 909
  111. d[knownkey] = knownvalue
  112. self.assertEqual(d.pop(knownkey, default), knownvalue)
  113. self.failIf(knownkey in d)
  114. self.assertEqual(d.pop(knownkey, default), default)
  115. #popitem
  116. key, value = d.popitem()
  117. self.failIf(key in d)
  118. self.assertEqual(value, self.reference[key])
  119. p=self._empty_mapping()
  120. self.assertRaises(KeyError, p.popitem)
  121. def test_constructor(self):
  122. self.assertEqual(self._empty_mapping(), self._empty_mapping())
  123. def test_bool(self):
  124. self.assert_(not self._empty_mapping())
  125. self.assert_(self.reference)
  126. self.assert_(bool(self._empty_mapping()) is False)
  127. self.assert_(bool(self.reference) is True)
  128. def test_keys(self):
  129. d = self._empty_mapping()
  130. self.assertEqual(d.keys(), [])
  131. d = self.reference
  132. self.assert_(self.inmapping.keys()[0] in d.keys())
  133. self.assert_(self.other.keys()[0] not in d.keys())
  134. self.assertRaises(TypeError, d.keys, None)
  135. def test_values(self):
  136. d = self._empty_mapping()
  137. self.assertEqual(d.values(), [])
  138. self.assertRaises(TypeError, d.values, None)
  139. def test_items(self):
  140. d = self._empty_mapping()
  141. self.assertEqual(d.items(), [])
  142. self.assertRaises(TypeError, d.items, None)
  143. def test_len(self):
  144. d = self._empty_mapping()
  145. self.assertEqual(len(d), 0)
  146. def test_getitem(self):
  147. d = self.reference
  148. self.assertEqual(d[self.inmapping.keys()[0]], self.inmapping.values()[0])
  149. self.assertRaises(TypeError, d.__getitem__)
  150. def test_update(self):
  151. # mapping argument
  152. d = self._empty_mapping()
  153. d.update(self.other)
  154. self.assertEqual(d.items(), self.other.items())
  155. # No argument
  156. d = self._empty_mapping()
  157. d.update()
  158. self.assertEqual(d, self._empty_mapping())
  159. # item sequence
  160. d = self._empty_mapping()
  161. d.update(self.other.items())
  162. self.assertEqual(d.items(), self.other.items())
  163. # Iterator
  164. d = self._empty_mapping()
  165. d.update(self.other.iteritems())
  166. self.assertEqual(d.items(), self.other.items())
  167. # FIXME: Doesn't work with UserDict
  168. # self.assertRaises((TypeError, AttributeError), d.update, None)
  169. self.assertRaises((TypeError, AttributeError), d.update, 42)
  170. outerself = self
  171. class SimpleUserDict:
  172. def __init__(self):
  173. self.d = outerself.reference
  174. def keys(self):
  175. return self.d.keys()
  176. def __getitem__(self, i):
  177. return self.d[i]
  178. d.clear()
  179. d.update(SimpleUserDict())
  180. i1 = d.items()
  181. i2 = self.reference.items()
  182. i1.sort()
  183. i2.sort()
  184. self.assertEqual(i1, i2)
  185. class Exc(Exception): pass
  186. d = self._empty_mapping()
  187. class FailingUserDict:
  188. def keys(self):
  189. raise Exc
  190. self.assertRaises(Exc, d.update, FailingUserDict())
  191. d.clear()
  192. class FailingUserDict:
  193. def keys(self):
  194. class BogonIter:
  195. def __init__(self):
  196. self.i = 1
  197. def __iter__(self):
  198. return self
  199. def next(self):
  200. if self.i:
  201. self.i = 0
  202. return 'a'
  203. raise Exc
  204. return BogonIter()
  205. def __getitem__(self, key):
  206. return key
  207. self.assertRaises(Exc, d.update, FailingUserDict())
  208. class FailingUserDict:
  209. def keys(self):
  210. class BogonIter:
  211. def __init__(self):
  212. self.i = ord('a')
  213. def __iter__(self):
  214. return self
  215. def next(self):
  216. if self.i <= ord('z'):
  217. rtn = chr(self.i)
  218. self.i += 1
  219. return rtn
  220. raise StopIteration
  221. return BogonIter()
  222. def __getitem__(self, key):
  223. raise Exc
  224. self.assertRaises(Exc, d.update, FailingUserDict())
  225. d = self._empty_mapping()
  226. class badseq(object):
  227. def __iter__(self):
  228. return self
  229. def next(self):
  230. raise Exc()
  231. self.assertRaises(Exc, d.update, badseq())
  232. self.assertRaises(ValueError, d.update, [(1, 2, 3)])
  233. # no test_fromkeys or test_copy as both os.environ and selves don't support it
  234. def test_get(self):
  235. d = self._empty_mapping()
  236. self.assert_(d.get(self.other.keys()[0]) is None)
  237. self.assertEqual(d.get(self.other.keys()[0], 3), 3)
  238. d = self.reference
  239. self.assert_(d.get(self.other.keys()[0]) is None)
  240. self.assertEqual(d.get(self.other.keys()[0], 3), 3)
  241. self.assertEqual(d.get(self.inmapping.keys()[0]), self.inmapping.values()[0])
  242. self.assertEqual(d.get(self.inmapping.keys()[0], 3), self.inmapping.values()[0])
  243. self.assertRaises(TypeError, d.get)
  244. self.assertRaises(TypeError, d.get, None, None, None)
  245. def test_setdefault(self):
  246. d = self._empty_mapping()
  247. self.assertRaises(TypeError, d.setdefault)
  248. def test_popitem(self):
  249. d = self._empty_mapping()
  250. self.assertRaises(KeyError, d.popitem)
  251. self.assertRaises(TypeError, d.popitem, 42)
  252. def test_pop(self):
  253. d = self._empty_mapping()
  254. k, v = self.inmapping.items()[0]
  255. d[k] = v
  256. self.assertRaises(KeyError, d.pop, self.other.keys()[0])
  257. self.assertEqual(d.pop(k), v)
  258. self.assertEqual(len(d), 0)
  259. self.assertRaises(KeyError, d.pop, k)
  260. class TestMappingProtocol(BasicTestMappingProtocol):
  261. def test_constructor(self):
  262. BasicTestMappingProtocol.test_constructor(self)
  263. self.assert_(self._empty_mapping() is not self._empty_mapping())
  264. self.assertEqual(self.type2test(x=1, y=2), {"x": 1, "y": 2})
  265. def test_bool(self):
  266. BasicTestMappingProtocol.test_bool(self)
  267. self.assert_(not self._empty_mapping())
  268. self.assert_(self._full_mapping({"x": "y"}))
  269. self.assert_(bool(self._empty_mapping()) is False)
  270. self.assert_(bool(self._full_mapping({"x": "y"})) is True)
  271. def test_keys(self):
  272. BasicTestMappingProtocol.test_keys(self)
  273. d = self._empty_mapping()
  274. self.assertEqual(d.keys(), [])
  275. d = self._full_mapping({'a': 1, 'b': 2})
  276. k = d.keys()
  277. self.assert_('a' in k)
  278. self.assert_('b' in k)
  279. self.assert_('c' not in k)
  280. def test_values(self):
  281. BasicTestMappingProtocol.test_values(self)
  282. d = self._full_mapping({1:2})
  283. self.assertEqual(d.values(), [2])
  284. def test_items(self):
  285. BasicTestMappingProtocol.test_items(self)
  286. d = self._full_mapping({1:2})
  287. self.assertEqual(d.items(), [(1, 2)])
  288. def test_has_key(self):
  289. d = self._empty_mapping()
  290. self.assert_(not d.has_key('a'))
  291. d = self._full_mapping({'a': 1, 'b': 2})
  292. k = d.keys()
  293. k.sort()
  294. self.assertEqual(k, ['a', 'b'])
  295. self.assertRaises(TypeError, d.has_key)
  296. def test_contains(self):
  297. d = self._empty_mapping()
  298. self.assert_(not ('a' in d))
  299. self.assert_('a' not in d)
  300. d = self._full_mapping({'a': 1, 'b': 2})
  301. self.assert_('a' in d)
  302. self.assert_('b' in d)
  303. self.assert_('c' not in d)
  304. self.assertRaises(TypeError, d.__contains__)
  305. def test_len(self):
  306. BasicTestMappingProtocol.test_len(self)
  307. d = self._full_mapping({'a': 1, 'b': 2})
  308. self.assertEqual(len(d), 2)
  309. def test_getitem(self):
  310. BasicTestMappingProtocol.test_getitem(self)
  311. d = self._full_mapping({'a': 1, 'b': 2})
  312. self.assertEqual(d['a'], 1)
  313. self.assertEqual(d['b'], 2)
  314. d['c'] = 3
  315. d['a'] = 4
  316. self.assertEqual(d['c'], 3)
  317. self.assertEqual(d['a'], 4)
  318. del d['b']
  319. self.assertEqual(d, {'a': 4, 'c': 3})
  320. self.assertRaises(TypeError, d.__getitem__)
  321. def test_clear(self):
  322. d = self._full_mapping({1:1, 2:2, 3:3})
  323. d.clear()
  324. self.assertEqual(d, {})
  325. self.assertRaises(TypeError, d.clear, None)
  326. def test_update(self):
  327. BasicTestMappingProtocol.test_update(self)
  328. # mapping argument
  329. d = self._empty_mapping()
  330. d.update({1:100})
  331. d.update({2:20})
  332. d.update({1:1, 2:2, 3:3})
  333. self.assertEqual(d, {1:1, 2:2, 3:3})
  334. # no argument
  335. d.update()
  336. self.assertEqual(d, {1:1, 2:2, 3:3})
  337. # keyword arguments
  338. d = self._empty_mapping()
  339. d.update(x=100)
  340. d.update(y=20)
  341. d.update(x=1, y=2, z=3)
  342. self.assertEqual(d, {"x":1, "y":2, "z":3})
  343. # item sequence
  344. d = self._empty_mapping()
  345. d.update([("x", 100), ("y", 20)])
  346. self.assertEqual(d, {"x":100, "y":20})
  347. # Both item sequence and keyword arguments
  348. d = self._empty_mapping()
  349. d.update([("x", 100), ("y", 20)], x=1, y=2)
  350. self.assertEqual(d, {"x":1, "y":2})
  351. # iterator
  352. d = self._full_mapping({1:3, 2:4})
  353. d.update(self._full_mapping({1:2, 3:4, 5:6}).iteritems())
  354. self.assertEqual(d, {1:2, 2:4, 3:4, 5:6})
  355. class SimpleUserDict:
  356. def __init__(self):
  357. self.d = {1:1, 2:2, 3:3}
  358. def keys(self):
  359. return self.d.keys()
  360. def __getitem__(self, i):
  361. return self.d[i]
  362. d.clear()
  363. d.update(SimpleUserDict())
  364. self.assertEqual(d, {1:1, 2:2, 3:3})
  365. def test_fromkeys(self):
  366. self.assertEqual(self.type2test.fromkeys('abc'), {'a':None, 'b':None, 'c':None})
  367. d = self._empty_mapping()
  368. self.assert_(not(d.fromkeys('abc') is d))
  369. self.assertEqual(d.fromkeys('abc'), {'a':None, 'b':None, 'c':None})
  370. self.assertEqual(d.fromkeys((4,5),0), {4:0, 5:0})
  371. self.assertEqual(d.fromkeys([]), {})
  372. def g():
  373. yield 1
  374. self.assertEqual(d.fromkeys(g()), {1:None})
  375. self.assertRaises(TypeError, {}.fromkeys, 3)
  376. class dictlike(self.type2test): pass
  377. self.assertEqual(dictlike.fromkeys('a'), {'a':None})
  378. self.assertEqual(dictlike().fromkeys('a'), {'a':None})
  379. self.assert_(dictlike.fromkeys('a').__class__ is dictlike)
  380. self.assert_(dictlike().fromkeys('a').__class__ is dictlike)
  381. # FIXME: the following won't work with UserDict, because it's an old style class
  382. # self.assert_(type(dictlike.fromkeys('a')) is dictlike)
  383. class mydict(self.type2test):
  384. def __new__(cls):
  385. return UserDict.UserDict()
  386. ud = mydict.fromkeys('ab')
  387. self.assertEqual(ud, {'a':None, 'b':None})
  388. # FIXME: the following won't work with UserDict, because it's an old style class
  389. # self.assert_(isinstance(ud, UserDict.UserDict))
  390. self.assertRaises(TypeError, dict.fromkeys)
  391. class Exc(Exception): pass
  392. class baddict1(self.type2test):
  393. def __init__(self):
  394. raise Exc()
  395. self.assertRaises(Exc, baddict1.fromkeys, [1])
  396. class BadSeq(object):
  397. def __iter__(self):
  398. return self
  399. def next(self):
  400. raise Exc()
  401. self.assertRaises(Exc, self.type2test.fromkeys, BadSeq())
  402. class baddict2(self.type2test):
  403. def __setitem__(self, key, value):
  404. raise Exc()
  405. self.assertRaises(Exc, baddict2.fromkeys, [1])
  406. def test_copy(self):
  407. d = self._full_mapping({1:1, 2:2, 3:3})
  408. self.assertEqual(d.copy(), {1:1, 2:2, 3:3})
  409. d = self._empty_mapping()
  410. self.assertEqual(d.copy(), d)
  411. self.assert_(isinstance(d.copy(), d.__class__))
  412. self.assertRaises(TypeError, d.copy, None)
  413. def test_get(self):
  414. BasicTestMappingProtocol.test_get(self)
  415. d = self._empty_mapping()
  416. self.assert_(d.get('c') is None)
  417. self.assertEqual(d.get('c', 3), 3)
  418. d = self._full_mapping({'a' : 1, 'b' : 2})
  419. self.assert_(d.get('c') is None)
  420. self.assertEqual(d.get('c', 3), 3)
  421. self.assertEqual(d.get('a'), 1)
  422. self.assertEqual(d.get('a', 3), 1)
  423. def test_setdefault(self):
  424. BasicTestMappingProtocol.test_setdefault(self)
  425. d = self._empty_mapping()
  426. self.assert_(d.setdefault('key0') is None)
  427. d.setdefault('key0', [])
  428. self.assert_(d.setdefault('key0') is None)
  429. d.setdefault('key', []).append(3)
  430. self.assertEqual(d['key'][0], 3)
  431. d.setdefault('key', []).append(4)
  432. self.assertEqual(len(d['key']), 2)
  433. def test_popitem(self):
  434. BasicTestMappingProtocol.test_popitem(self)
  435. for copymode in -1, +1:
  436. # -1: b has same structure as a
  437. # +1: b is a.copy()
  438. for log2size in range(12):
  439. size = 2**log2size
  440. a = self._empty_mapping()
  441. b = self._empty_mapping()
  442. for i in range(size):
  443. a[repr(i)] = i
  444. if copymode < 0:
  445. b[repr(i)] = i
  446. if copymode > 0:
  447. b = a.copy()
  448. for i in range(size):
  449. ka, va = ta = a.popitem()
  450. self.assertEqual(va, int(ka))
  451. kb, vb = tb = b.popitem()
  452. self.assertEqual(vb, int(kb))
  453. self.assert_(not(copymode < 0 and ta != tb))
  454. self.assert_(not a)
  455. self.assert_(not b)
  456. def test_pop(self):
  457. BasicTestMappingProtocol.test_pop(self)
  458. # Tests for pop with specified key
  459. d = self._empty_mapping()
  460. k, v = 'abc', 'def'
  461. # verify longs/ints get same value when key > 32 bits (for 64-bit archs)
  462. # see SF bug #689659
  463. x = 4503599627370496L
  464. y = 4503599627370496
  465. h = self._full_mapping({x: 'anything', y: 'something else'})
  466. self.assertEqual(h[x], h[y])
  467. self.assertEqual(d.pop(k, v), v)
  468. d[k] = v
  469. self.assertEqual(d.pop(k, 1), v)
  470. class TestHashMappingProtocol(TestMappingProtocol):
  471. def test_getitem(self):
  472. TestMappingProtocol.test_getitem(self)
  473. class Exc(Exception): pass
  474. class BadEq(object):
  475. def __eq__(self, other):
  476. raise Exc()
  477. def __hash__(self):
  478. return 24
  479. d = self._empty_mapping()
  480. d[BadEq()] = 42
  481. self.assertRaises(KeyError, d.__getitem__, 23)
  482. class BadHash(object):
  483. fail = False
  484. def __hash__(self):
  485. if self.fail:
  486. raise Exc()
  487. else:
  488. return 42
  489. d = self._empty_mapping()
  490. x = BadHash()
  491. d[x] = 42
  492. x.fail = True
  493. self.assertRaises(Exc, d.__getitem__, x)
  494. def test_fromkeys(self):
  495. TestMappingProtocol.test_fromkeys(self)
  496. class mydict(self.type2test):
  497. def __new__(cls):
  498. return UserDict.UserDict()
  499. ud = mydict.fromkeys('ab')
  500. self.assertEqual(ud, {'a':None, 'b':None})
  501. self.assert_(isinstance(ud, UserDict.UserDict))
  502. def test_pop(self):
  503. TestMappingProtocol.test_pop(self)
  504. class Exc(Exception): pass
  505. class BadHash(object):
  506. fail = False
  507. def __hash__(self):
  508. if self.fail:
  509. raise Exc()
  510. else:
  511. return 42
  512. d = self._empty_mapping()
  513. x = BadHash()
  514. d[x] = 42
  515. x.fail = True
  516. self.assertRaises(Exc, d.pop, x)
  517. def test_mutatingiteration(self):
  518. d = self._empty_mapping()
  519. d[1] = 1
  520. try:
  521. for i in d:
  522. d[i+1] = 1
  523. except RuntimeError:
  524. pass
  525. else:
  526. self.fail("changing dict size during iteration doesn't raise Error")
  527. def test_repr(self):
  528. d = self._empty_mapping()
  529. self.assertEqual(repr(d), '{}')
  530. d[1] = 2
  531. self.assertEqual(repr(d), '{1: 2}')
  532. d = self._empty_mapping()
  533. d[1] = d
  534. self.assertEqual(repr(d), '{1: {...}}')
  535. class Exc(Exception): pass
  536. class BadRepr(object):
  537. def __repr__(self):
  538. raise Exc()
  539. d = self._full_mapping({1: BadRepr()})
  540. self.assertRaises(Exc, repr, d)
  541. def test_le(self):
  542. self.assert_(not (self._empty_mapping() < self._empty_mapping()))
  543. self.assert_(not (self._full_mapping({1: 2}) < self._full_mapping({1L: 2L})))
  544. class Exc(Exception): pass
  545. class BadCmp(object):
  546. def __eq__(self, other):
  547. raise Exc()
  548. def __hash__(self):
  549. return 42
  550. d1 = self._full_mapping({BadCmp(): 1})
  551. d2 = self._full_mapping({1: 1})
  552. try:
  553. d1 < d2
  554. except Exc:
  555. pass
  556. else:
  557. self.fail("< didn't raise Exc")
  558. def test_setdefault(self):
  559. TestMappingProtocol.test_setdefault(self)
  560. class Exc(Exception): pass
  561. class BadHash(object):
  562. fail = False
  563. def __hash__(self):
  564. if self.fail:
  565. raise Exc()
  566. else:
  567. return 42
  568. d = self._empty_mapping()
  569. x = BadHash()
  570. d[x] = 42
  571. x.fail = True
  572. self.assertRaises(Exc, d.setdefault, x, [])