PageRenderTime 104ms CodeModel.GetById 12ms RepoModel.GetById 2ms app.codeStats 1ms

/pypy/rpython/test/test_rdict.py

https://bitbucket.org/pypy/pypy/
Python | 1070 lines | 1057 code | 11 blank | 2 comment | 6 complexity | abab77ce4d6edd247552229d4914b89a MD5 | raw file
Possible License(s): AGPL-3.0, BSD-3-Clause, Apache-2.0
  1. from pypy.translator.translator import TranslationContext
  2. from pypy.rpython.lltypesystem import lltype, rffi
  3. from pypy.rpython import rint
  4. from pypy.rpython.lltypesystem import rdict, rstr
  5. from pypy.rpython.test.tool import BaseRtypingTest, LLRtypeMixin, OORtypeMixin
  6. from pypy.rlib.objectmodel import r_dict
  7. from pypy.rlib.rarithmetic import r_int, r_uint, r_longlong, r_ulonglong
  8. import py
  9. py.log.setconsumer("rtyper", py.log.STDOUT)
  10. def not_really_random():
  11. """A random-ish generator, which also generates nice patterns from time to time.
  12. Could be useful to detect problems associated with specific usage patterns."""
  13. import random
  14. x = random.random()
  15. print 'random seed: %r' % (x,)
  16. for i in range(12000):
  17. r = 3.4 + i/20000.0
  18. x = r*x - x*x
  19. assert 0 <= x < 4
  20. yield x
  21. class BaseTestRdict(BaseRtypingTest):
  22. def test_dict_creation(self):
  23. def createdict(i):
  24. d = {'hello' : i}
  25. return d['hello']
  26. res = self.interpret(createdict, [42])
  27. assert res == 42
  28. def test_dict_getitem_setitem(self):
  29. def func(i):
  30. d = {'hello' : i}
  31. d['world'] = i + 1
  32. return d['hello'] * d['world']
  33. res = self.interpret(func, [6])
  34. assert res == 42
  35. def test_dict_getitem_keyerror(self):
  36. def func(i):
  37. d = {'hello' : i}
  38. try:
  39. return d['world']
  40. except KeyError:
  41. return 0
  42. res = self.interpret(func, [6])
  43. assert res == 0
  44. def test_dict_del_simple(self):
  45. def func(i):
  46. d = {'hello' : i}
  47. d['world'] = i + 1
  48. del d['hello']
  49. return len(d)
  50. res = self.interpret(func, [6])
  51. assert res == 1
  52. def test_dict_clear(self):
  53. def func(i):
  54. d = {'abc': i}
  55. d['def'] = i+1
  56. d.clear()
  57. d['ghi'] = i+2
  58. return ('abc' not in d and 'def' not in d
  59. and d['ghi'] == i+2 and len(d) == 1)
  60. res = self.interpret(func, [7])
  61. assert res == True
  62. def test_empty_strings(self):
  63. def func(i):
  64. d = {'' : i}
  65. del d['']
  66. try:
  67. d['']
  68. return 0
  69. except KeyError:
  70. pass
  71. return 1
  72. res = self.interpret(func, [6])
  73. assert res == 1
  74. def func(i):
  75. d = {'' : i}
  76. del d['']
  77. d[''] = i + 1
  78. return len(d)
  79. res = self.interpret(func, [6])
  80. assert res == 1
  81. def test_dict_is_true(self):
  82. def func(i):
  83. if i:
  84. d = {}
  85. else:
  86. d = {i: i+1}
  87. if d:
  88. return i
  89. else:
  90. return i+1
  91. assert self.interpret(func, [42]) == 43
  92. assert self.interpret(func, [0]) == 0
  93. def test_contains(self):
  94. def func(x, y):
  95. d = {x: x+1}
  96. return y in d
  97. assert self.interpret(func, [42, 0]) == False
  98. assert self.interpret(func, [42, 42]) == True
  99. def test_dict_iteration(self):
  100. def func(i, j):
  101. d = {}
  102. d['hello'] = i
  103. d['world'] = j
  104. k = 1
  105. for key in d:
  106. k = k * d[key]
  107. return k
  108. res = self.interpret(func, [6, 7])
  109. assert res == 42
  110. def test_dict_itermethods(self):
  111. def func():
  112. d = {}
  113. d['hello'] = 6
  114. d['world'] = 7
  115. k1 = k2 = k3 = 1
  116. for key in d.iterkeys():
  117. k1 = k1 * d[key]
  118. for value in d.itervalues():
  119. k2 = k2 * value
  120. for key, value in d.iteritems():
  121. assert d[key] == value
  122. k3 = k3 * value
  123. return k1 + k2 + k3
  124. res = self.interpret(func, [])
  125. assert res == 42 + 42 + 42
  126. def test_two_dicts_with_different_value_types(self):
  127. def func(i):
  128. d1 = {}
  129. d1['hello'] = i + 1
  130. d2 = {}
  131. d2['world'] = d1
  132. return d2['world']['hello']
  133. res = self.interpret(func, [5])
  134. assert res == 6
  135. def test_dict_get(self):
  136. def func():
  137. dic = {}
  138. x1 = dic.get('hi', 42)
  139. dic['blah'] = 1 # XXX this triggers type determination
  140. x2 = dic.get('blah', 2)
  141. return x1 * 10 + x2
  142. res = self.interpret(func, ())
  143. assert res == 421
  144. def test_dict_get_empty(self):
  145. def func():
  146. # this time without writing to the dict
  147. dic = {}
  148. x1 = dic.get('hi', 42)
  149. x2 = dic.get('blah', 2)
  150. return x1 * 10 + x2
  151. res = self.interpret(func, ())
  152. assert res == 422
  153. def test_dict_setdefault(self):
  154. def f():
  155. d = {}
  156. d.setdefault('a', 2)
  157. return d['a']
  158. res = self.interpret(f, ())
  159. assert res == 2
  160. def f():
  161. d = {}
  162. d.setdefault('a', 2)
  163. x = d.setdefault('a', -3)
  164. return x
  165. res = self.interpret(f, ())
  166. assert res == 2
  167. def test_dict_copy(self):
  168. def func():
  169. # XXX this does not work if we use chars, only!
  170. dic = {'ab':1, 'b':2}
  171. d2 = dic.copy()
  172. ok = 1
  173. for key in d2:
  174. if dic[key] != d2[key]:
  175. ok = 0
  176. ok &= len(dic) == len(d2)
  177. d2['c'] = 3
  178. ok &= len(dic) == len(d2) - 1
  179. return ok
  180. res = self.interpret(func, ())
  181. assert res == 1
  182. def test_dict_update(self):
  183. def func():
  184. dic = {'ab':1000, 'b':200}
  185. d2 = {'b':30, 'cb':4}
  186. dic.update(d2)
  187. ok = len(dic) == 3
  188. sum = ok
  189. for key in dic:
  190. sum += dic[key]
  191. return sum
  192. res = self.interpret(func, ())
  193. assert res == 1035
  194. def test_dict_keys(self):
  195. def func():
  196. dic = {' 4':1000, ' 8':200}
  197. keys = dic.keys()
  198. return ord(keys[0][1]) + ord(keys[1][1]) - 2*ord('0') + len(keys)
  199. res = self.interpret(func, ())#, view=True)
  200. assert res == 14
  201. def test_dict_inst_keys(self):
  202. class Empty:
  203. pass
  204. class A(Empty):
  205. pass
  206. def func():
  207. dic0 = {Empty(): 2}
  208. dic = {A(): 1, A(): 2}
  209. keys = dic.keys()
  210. return (isinstance(keys[1], A))*2+(isinstance(keys[0],A))
  211. res = self.interpret(func, [])
  212. assert res == 3
  213. def test_dict_inst_iterkeys(self):
  214. class Empty:
  215. pass
  216. class A(Empty):
  217. pass
  218. def func():
  219. dic0 = {Empty(): 2}
  220. dic = {A(): 1, A(): 2}
  221. a = 0
  222. for k in dic.iterkeys():
  223. a += isinstance(k, A)
  224. return a
  225. res = self.interpret(func, [])
  226. assert res == 2
  227. def test_dict_values(self):
  228. def func():
  229. dic = {' 4':1000, ' 8':200}
  230. values = dic.values()
  231. return values[0] + values[1] + len(values)
  232. res = self.interpret(func, ())
  233. assert res == 1202
  234. def test_dict_inst_values(self):
  235. class A:
  236. pass
  237. def func():
  238. dic = {1: A(), 2: A()}
  239. vals = dic.values()
  240. return (isinstance(vals[1], A))*2+(isinstance(vals[0],A))
  241. res = self.interpret(func, [])
  242. assert res == 3
  243. def test_dict_inst_itervalues(self):
  244. class A:
  245. pass
  246. def func():
  247. dic = {1: A(), 2: A()}
  248. a = 0
  249. for v in dic.itervalues():
  250. a += isinstance(v, A)
  251. return a
  252. res = self.interpret(func, [])
  253. assert res == 2
  254. def test_dict_inst_items(self):
  255. class Empty:
  256. pass
  257. class A:
  258. pass
  259. class B(Empty):
  260. pass
  261. def func():
  262. dic0 = {Empty(): 2}
  263. dic = {B(): A(), B(): A()}
  264. items = dic.items()
  265. b = 0
  266. a = 0
  267. for k, v in items:
  268. b += isinstance(k, B)
  269. a += isinstance(v, A)
  270. return 3*b+a
  271. res = self.interpret(func, [])
  272. assert res == 8
  273. def test_dict_inst_iteritems(self):
  274. class Empty:
  275. pass
  276. class A:
  277. pass
  278. class B(Empty):
  279. pass
  280. def func():
  281. dic0 = {Empty(): 2}
  282. dic = {B(): A(), B(): A()}
  283. b = 0
  284. a = 0
  285. for k, v in dic.iteritems():
  286. b += isinstance(k, B)
  287. a += isinstance(v, A)
  288. return 3*b+a
  289. res = self.interpret(func, [])
  290. assert res == 8
  291. def test_dict_items(self):
  292. def func():
  293. dic = {' 4':1000, ' 8':200}
  294. items = dic.items()
  295. res = len(items)
  296. for key, value in items:
  297. res += ord(key[1]) - ord('0') + value
  298. return res
  299. res = self.interpret(func, ())
  300. assert res == 1214
  301. def test_dict_contains(self):
  302. def func():
  303. dic = {' 4':1000, ' 8':200}
  304. return ' 4' in dic and ' 9' not in dic
  305. res = self.interpret(func, ())
  306. assert res is True
  307. def test_dict_contains_with_constant_dict(self):
  308. dic = {'4':1000, ' 8':200}
  309. def func(i):
  310. return chr(i) in dic
  311. res = self.interpret(func, [ord('4')])
  312. assert res is True
  313. res = self.interpret(func, [1])
  314. assert res is False
  315. def test_dict_or_none(self):
  316. class A:
  317. pass
  318. def negate(d):
  319. return not d
  320. def func(n):
  321. a = A()
  322. a.d = None
  323. if n > 0:
  324. a.d = {str(n): 1, "42": 2}
  325. del a.d["42"]
  326. return negate(a.d)
  327. res = self.interpret(func, [10])
  328. assert res is False
  329. res = self.interpret(func, [0])
  330. assert res is True
  331. res = self.interpret(func, [42])
  332. assert res is True
  333. def test_int_dict(self):
  334. def func(a, b):
  335. dic = {12: 34}
  336. dic[a] = 1000
  337. return dic.get(b, -123)
  338. res = self.interpret(func, [12, 12])
  339. assert res == 1000
  340. res = self.interpret(func, [12, 13])
  341. assert res == -123
  342. res = self.interpret(func, [524, 12])
  343. assert res == 34
  344. res = self.interpret(func, [524, 524])
  345. assert res == 1000
  346. res = self.interpret(func, [524, 1036])
  347. assert res == -123
  348. def test_id_instances_keys(self):
  349. class A:
  350. pass
  351. class B(A):
  352. pass
  353. def f():
  354. a = A()
  355. b = B()
  356. d = {}
  357. d[b] = 7
  358. d[a] = 3
  359. return len(d) + d[a] + d[b]
  360. res = self.interpret(f, [])
  361. assert res == 12
  362. def test_captured_get(self):
  363. get = {1:2}.get
  364. def f():
  365. return get(1, 3)+get(2, 4)
  366. res = self.interpret(f, [])
  367. assert res == 6
  368. def g(h):
  369. return h(1, 3)
  370. def f():
  371. return g(get)
  372. res = self.interpret(f, [])
  373. assert res == 2
  374. def test_specific_obscure_bug(self):
  375. class A: pass
  376. class B: pass # unrelated kinds of instances
  377. def f():
  378. lst = [A()]
  379. res1 = A() in lst
  380. d2 = {B(): None, B(): None}
  381. return res1+len(d2)
  382. res = self.interpret(f, [])
  383. assert res == 2
  384. def test_type_erase(self):
  385. class A(object):
  386. pass
  387. class B(object):
  388. pass
  389. def f():
  390. return {A(): B()}, {B(): A()}
  391. t = TranslationContext()
  392. s = t.buildannotator().build_types(f, [])
  393. rtyper = t.buildrtyper()
  394. rtyper.specialize()
  395. s_AB_dic = s.items[0]
  396. s_BA_dic = s.items[1]
  397. r_AB_dic = rtyper.getrepr(s_AB_dic)
  398. r_BA_dic = rtyper.getrepr(s_AB_dic)
  399. assert r_AB_dic.lowleveltype == r_BA_dic.lowleveltype
  400. def test_tuple_dict(self):
  401. def f(i):
  402. d = {}
  403. d[(1, 4.5, (str(i), 2), 2)] = 4
  404. d[(1, 4.5, (str(i), 2), 3)] = 6
  405. return d[(1, 4.5, (str(i), 2), i)]
  406. res = self.interpret(f, [2])
  407. assert res == f(2)
  408. def test_dict_of_dict(self):
  409. def f(n):
  410. d = {}
  411. d[5] = d
  412. d[6] = {}
  413. return len(d[n])
  414. res = self.interpret(f, [5])
  415. assert res == 2
  416. res = self.interpret(f, [6])
  417. assert res == 0
  418. def test_access_in_try(self):
  419. def f(d):
  420. try:
  421. return d[2]
  422. except ZeroDivisionError:
  423. return 42
  424. return -1
  425. def g(n):
  426. d = {1: n, 2: 2*n}
  427. return f(d)
  428. res = self.interpret(g, [3])
  429. assert res == 6
  430. def test_access_in_try_set(self):
  431. def f(d):
  432. try:
  433. d[2] = 77
  434. except ZeroDivisionError:
  435. return 42
  436. return -1
  437. def g(n):
  438. d = {1: n}
  439. f(d)
  440. return d[2]
  441. res = self.interpret(g, [3])
  442. assert res == 77
  443. def test_r_dict(self):
  444. class FooError(Exception):
  445. pass
  446. def myeq(n, m):
  447. return n == m
  448. def myhash(n):
  449. if n < 0:
  450. raise FooError
  451. return -n
  452. def f(n):
  453. d = r_dict(myeq, myhash)
  454. for i in range(10):
  455. d[i] = i*i
  456. try:
  457. value1 = d[n]
  458. except FooError:
  459. value1 = 99
  460. try:
  461. value2 = n in d
  462. except FooError:
  463. value2 = 99
  464. try:
  465. value3 = d[-n]
  466. except FooError:
  467. value3 = 99
  468. try:
  469. value4 = (-n) in d
  470. except FooError:
  471. value4 = 99
  472. return (value1 * 1000000 +
  473. value2 * 10000 +
  474. value3 * 100 +
  475. value4)
  476. res = self.interpret(f, [5])
  477. assert res == 25019999
  478. def test_resize_during_iteration(self):
  479. def func():
  480. d = {5: 1, 6: 2, 7: 3}
  481. try:
  482. for key, value in d.iteritems():
  483. d[key^16] = value*2
  484. except RuntimeError:
  485. pass
  486. total = 0
  487. for key in d:
  488. total += key
  489. return total
  490. res = self.interpret(func, [])
  491. assert 5 + 6 + 7 <= res <= 5 + 6 + 7 + (5^16) + (6^16) + (7^16)
  492. def test_change_during_iteration(self):
  493. def func():
  494. d = {'a': 1, 'b': 2}
  495. for key in d:
  496. d[key] = 42
  497. return d['a']
  498. assert self.interpret(func, []) == 42
  499. def test_dict_of_floats(self):
  500. d = {3.0: 42, 3.1: 43, 3.2: 44, 3.3: 45, 3.4: 46}
  501. def fn(f):
  502. return d[f]
  503. res = self.interpret(fn, [3.0])
  504. assert res == 42
  505. def test_dict_of_r_uint(self):
  506. for r_t in [r_uint, r_longlong, r_ulonglong]:
  507. if r_t is r_int:
  508. continue # for 64-bit platforms: skip r_longlong
  509. d = {r_t(2): 3, r_t(4): 5}
  510. def fn(x, y):
  511. d[r_t(x)] = 123
  512. return d[r_t(y)]
  513. res = self.interpret(fn, [4, 2])
  514. assert res == 3
  515. res = self.interpret(fn, [3, 3])
  516. assert res == 123
  517. def test_dict_popitem(self):
  518. def func():
  519. d = {}
  520. d[5] = 2
  521. d[6] = 3
  522. k1, v1 = d.popitem()
  523. assert len(d) == 1
  524. k2, v2 = d.popitem()
  525. try:
  526. d.popitem()
  527. except KeyError:
  528. pass
  529. else:
  530. assert 0, "should have raised KeyError"
  531. assert len(d) == 0
  532. return k1*1000 + v1*100 + k2*10 + v2
  533. res = self.interpret(func, [])
  534. assert res in [5263, 6352]
  535. def test_dict_popitem_hash(self):
  536. def deq(n, m):
  537. return n == m
  538. def dhash(n):
  539. return ~n
  540. def func():
  541. d = r_dict(deq, dhash)
  542. d[5] = 2
  543. d[6] = 3
  544. k1, v1 = d.popitem()
  545. assert len(d) == 1
  546. k2, v2 = d.popitem()
  547. try:
  548. d.popitem()
  549. except KeyError:
  550. pass
  551. else:
  552. assert 0, "should have raised KeyError"
  553. assert len(d) == 0
  554. return k1*1000 + v1*100 + k2*10 + v2
  555. res = self.interpret(func, [])
  556. assert res in [5263, 6352]
  557. def test_dict_pop(self):
  558. def f(n, default):
  559. d = {}
  560. d[2] = 3
  561. d[4] = 5
  562. if default == -1:
  563. try:
  564. x = d.pop(n)
  565. except KeyError:
  566. x = -1
  567. else:
  568. x = d.pop(n, default)
  569. return x * 10 + len(d)
  570. res = self.interpret(f, [2, -1])
  571. assert res == 31
  572. res = self.interpret(f, [3, -1])
  573. assert res == -8
  574. res = self.interpret(f, [2, 5])
  575. assert res == 31
  576. def test_dict_pop_instance(self):
  577. class A(object):
  578. pass
  579. def f(n):
  580. d = {}
  581. d[2] = A()
  582. x = d.pop(n, None)
  583. if x is None:
  584. return 12
  585. else:
  586. return 15
  587. res = self.interpret(f, [2])
  588. assert res == 15
  589. res = self.interpret(f, [700])
  590. assert res == 12
  591. class TestLLtype(BaseTestRdict, LLRtypeMixin):
  592. def test_dict_but_not_with_char_keys(self):
  593. def func(i):
  594. d = {'h': i}
  595. try:
  596. return d['hello']
  597. except KeyError:
  598. return 0
  599. res = self.interpret(func, [6])
  600. assert res == 0
  601. def test_deleted_entry_reusage_with_colliding_hashes(self):
  602. def lowlevelhash(value):
  603. p = rstr.mallocstr(len(value))
  604. for i in range(len(value)):
  605. p.chars[i] = value[i]
  606. return rstr.LLHelpers.ll_strhash(p)
  607. def func(c1, c2):
  608. c1 = chr(c1)
  609. c2 = chr(c2)
  610. d = {}
  611. d[c1] = 1
  612. d[c2] = 2
  613. del d[c1]
  614. return d[c2]
  615. char_by_hash = {}
  616. base = rdict.DICT_INITSIZE
  617. for y in range(0, 256):
  618. y = chr(y)
  619. y_hash = lowlevelhash(y) % base
  620. char_by_hash.setdefault(y_hash, []).append(y)
  621. x, y = char_by_hash[0][:2] # find a collision
  622. res = self.interpret(func, [ord(x), ord(y)])
  623. assert res == 2
  624. def func2(c1, c2):
  625. c1 = chr(c1)
  626. c2 = chr(c2)
  627. d = {}
  628. d[c1] = 1
  629. d[c2] = 2
  630. del d[c1]
  631. d[c1] = 3
  632. return d
  633. res = self.interpret(func2, [ord(x), ord(y)])
  634. for i in range(len(res.entries)):
  635. assert not (res.entries.everused(i) and not res.entries.valid(i))
  636. def func3(c0, c1, c2, c3, c4, c5, c6, c7):
  637. d = {}
  638. c0 = chr(c0) ; d[c0] = 1; del d[c0]
  639. c1 = chr(c1) ; d[c1] = 1; del d[c1]
  640. c2 = chr(c2) ; d[c2] = 1; del d[c2]
  641. c3 = chr(c3) ; d[c3] = 1; del d[c3]
  642. c4 = chr(c4) ; d[c4] = 1; del d[c4]
  643. c5 = chr(c5) ; d[c5] = 1; del d[c5]
  644. c6 = chr(c6) ; d[c6] = 1; del d[c6]
  645. c7 = chr(c7) ; d[c7] = 1; del d[c7]
  646. return d
  647. if rdict.DICT_INITSIZE != 8:
  648. py.test.skip("make dict tests more indepdent from initsize")
  649. res = self.interpret(func3, [ord(char_by_hash[i][0])
  650. for i in range(rdict.DICT_INITSIZE)])
  651. count_frees = 0
  652. for i in range(len(res.entries)):
  653. if not res.entries.everused(i):
  654. count_frees += 1
  655. assert count_frees >= 3
  656. def test_dict_resize(self):
  657. def func(want_empty):
  658. d = {}
  659. for i in range(rdict.DICT_INITSIZE):
  660. d[chr(ord('a') + i)] = i
  661. if want_empty:
  662. for i in range(rdict.DICT_INITSIZE):
  663. del d[chr(ord('a') + i)]
  664. return d
  665. res = self.interpret(func, [0])
  666. assert len(res.entries) > rdict.DICT_INITSIZE
  667. res = self.interpret(func, [1])
  668. assert len(res.entries) == rdict.DICT_INITSIZE
  669. def test_dict_valid_resize(self):
  670. # see if we find our keys after resize
  671. def func():
  672. d = {}
  673. # fill it up
  674. for i in range(10):
  675. d[str(i)] = 0
  676. # delete again
  677. for i in range(10):
  678. del d[str(i)]
  679. res = 0
  680. # if it does not crash, we are fine. It crashes if you forget the hash field.
  681. self.interpret(func, [])
  682. # ____________________________________________________________
  683. def test_opt_nullkeymarker(self):
  684. def f():
  685. d = {"hello": None}
  686. d["world"] = None
  687. return "hello" in d, d
  688. res = self.interpret(f, [])
  689. assert res.item0 == True
  690. DICT = lltype.typeOf(res.item1).TO
  691. assert not hasattr(DICT.entries.TO.OF, 'f_everused')# non-None string keys
  692. assert not hasattr(DICT.entries.TO.OF, 'f_valid') # strings have a dummy
  693. def test_opt_nullvaluemarker(self):
  694. def f(n):
  695. d = {-5: "abcd"}
  696. d[123] = "def"
  697. return len(d[n]), d
  698. res = self.interpret(f, [-5])
  699. assert res.item0 == 4
  700. DICT = lltype.typeOf(res.item1).TO
  701. assert not hasattr(DICT.entries.TO.OF, 'f_everused')# non-None str values
  702. assert not hasattr(DICT.entries.TO.OF, 'f_valid') # strs have a dummy
  703. def test_opt_nonullmarker(self):
  704. class A:
  705. pass
  706. def f(n):
  707. if n > 5:
  708. a = A()
  709. else:
  710. a = None
  711. d = {a: -5441}
  712. d[A()] = n+9872
  713. return d[a], d
  714. res = self.interpret(f, [-5])
  715. assert res.item0 == -5441
  716. DICT = lltype.typeOf(res.item1).TO
  717. assert hasattr(DICT.entries.TO.OF, 'f_everused') # can-be-None A instances
  718. assert not hasattr(DICT.entries.TO.OF, 'f_valid')# with a dummy A instance
  719. res = self.interpret(f, [6])
  720. assert res.item0 == -5441
  721. def test_opt_nonnegint_dummy(self):
  722. def f(n):
  723. d = {n: 12}
  724. d[-87] = 24
  725. del d[n]
  726. return len(d.copy()), d[-87], d
  727. res = self.interpret(f, [5])
  728. assert res.item0 == 1
  729. assert res.item1 == 24
  730. DICT = lltype.typeOf(res.item2).TO
  731. assert hasattr(DICT.entries.TO.OF, 'f_everused') # all ints can be zero
  732. assert not hasattr(DICT.entries.TO.OF, 'f_valid')# nonneg int: dummy -1
  733. def test_opt_no_dummy(self):
  734. def f(n):
  735. d = {n: 12}
  736. d[-87] = -24
  737. del d[n]
  738. return len(d.copy()), d[-87], d
  739. res = self.interpret(f, [5])
  740. assert res.item0 == 1
  741. assert res.item1 == -24
  742. DICT = lltype.typeOf(res.item2).TO
  743. assert hasattr(DICT.entries.TO.OF, 'f_everused') # all ints can be zero
  744. assert hasattr(DICT.entries.TO.OF, 'f_valid') # no dummy available
  745. def test_opt_boolean_has_no_dummy(self):
  746. def f(n):
  747. d = {n: True}
  748. d[-87] = True
  749. del d[n]
  750. return len(d.copy()), d[-87], d
  751. res = self.interpret(f, [5])
  752. assert res.item0 == 1
  753. assert res.item1 is True
  754. DICT = lltype.typeOf(res.item2).TO
  755. assert hasattr(DICT.entries.TO.OF, 'f_everused') # all ints can be zero
  756. assert hasattr(DICT.entries.TO.OF, 'f_valid') # no dummy available
  757. def test_opt_multiple_identical_dicts(self):
  758. def f(n):
  759. s = "x" * n
  760. d1 = {s: 12}
  761. d2 = {s: 24}
  762. d3 = {s: 36}
  763. d1["a"] = d2[s] # 24
  764. d3[s] += d1["a"] # 60
  765. d2["bc"] = d3[s] # 60
  766. return d2["bc"], d1, d2, d3
  767. res = self.interpret(f, [5])
  768. assert res.item0 == 60
  769. # all three dicts should use the same low-level type
  770. assert lltype.typeOf(res.item1) == lltype.typeOf(res.item2)
  771. assert lltype.typeOf(res.item1) == lltype.typeOf(res.item3)
  772. def test_dict_of_addresses(self):
  773. from pypy.rpython.lltypesystem import llmemory
  774. TP = lltype.Struct('x')
  775. a = lltype.malloc(TP, flavor='raw', immortal=True)
  776. b = lltype.malloc(TP, flavor='raw', immortal=True)
  777. def func(i):
  778. d = {}
  779. d[llmemory.cast_ptr_to_adr(a)] = 123
  780. d[llmemory.cast_ptr_to_adr(b)] = 456
  781. if i > 5:
  782. key = llmemory.cast_ptr_to_adr(a)
  783. else:
  784. key = llmemory.cast_ptr_to_adr(b)
  785. return d[key]
  786. assert self.interpret(func, [3]) == 456
  787. def test_prebuilt_list_of_addresses(self):
  788. from pypy.rpython.lltypesystem import llmemory
  789. TP = lltype.Struct('x', ('y', lltype.Signed))
  790. a = lltype.malloc(TP, flavor='raw', immortal=True)
  791. b = lltype.malloc(TP, flavor='raw', immortal=True)
  792. c = lltype.malloc(TP, flavor='raw', immortal=True)
  793. a_a = llmemory.cast_ptr_to_adr(a)
  794. a0 = llmemory.cast_ptr_to_adr(a)
  795. assert a_a is not a0
  796. assert a_a == a0
  797. a_b = llmemory.cast_ptr_to_adr(b)
  798. a_c = llmemory.cast_ptr_to_adr(c)
  799. d = {a_a: 3, a_b: 4, a_c: 5}
  800. d[a0] = 8
  801. def func(i):
  802. if i == 0:
  803. ptr = a
  804. else:
  805. ptr = b
  806. return d[llmemory.cast_ptr_to_adr(ptr)]
  807. py.test.raises(TypeError, self.interpret, func, [0])
  808. def test_dict_of_voidp(self):
  809. def func():
  810. d = {}
  811. handle = lltype.nullptr(rffi.VOIDP.TO)
  812. # Use a negative key, so the dict implementation uses
  813. # the value as a marker for empty entries
  814. d[-1] = handle
  815. return len(d)
  816. assert self.interpret(func, []) == 1
  817. from pypy.translator.c.test.test_genc import compile
  818. f = compile(func, [])
  819. res = f()
  820. assert res == 1
  821. def test_nonnull_hint(self):
  822. def eq(a, b):
  823. return a == b
  824. def rhash(a):
  825. return 3
  826. def func(i):
  827. d = r_dict(eq, rhash, force_non_null=True)
  828. if not i:
  829. d[None] = i
  830. else:
  831. d[str(i)] = i
  832. return "12" in d, d
  833. llres = self.interpret(func, [12])
  834. assert llres.item0 == 1
  835. DICT = lltype.typeOf(llres.item1)
  836. assert sorted(DICT.TO.entries.TO.OF._flds) == ['f_hash', 'key', 'value']
  837. # ____________________________________________________________
  838. class TestOOtype(BaseTestRdict, OORtypeMixin):
  839. def test_recursive(self):
  840. def func(i):
  841. dic = {i: {}}
  842. dic[i] = dic
  843. return dic[i]
  844. res = self.interpret(func, [5])
  845. assert res.ll_get(5) is res
  846. # ____________________________________________________________
  847. class TestStress:
  848. def test_stress(self):
  849. from pypy.annotation.dictdef import DictKey, DictValue
  850. from pypy.annotation import model as annmodel
  851. dictrepr = rdict.DictRepr(None, rint.signed_repr, rint.signed_repr,
  852. DictKey(None, annmodel.SomeInteger()),
  853. DictValue(None, annmodel.SomeInteger()))
  854. dictrepr.setup()
  855. l_dict = rdict.ll_newdict(dictrepr.DICT)
  856. referencetable = [None] * 400
  857. referencelength = 0
  858. value = 0
  859. def complete_check():
  860. for n, refvalue in zip(range(len(referencetable)), referencetable):
  861. try:
  862. gotvalue = rdict.ll_dict_getitem(l_dict, n)
  863. except KeyError:
  864. assert refvalue is None
  865. else:
  866. assert gotvalue == refvalue
  867. for x in not_really_random():
  868. n = int(x*100.0) # 0 <= x < 400
  869. op = repr(x)[-1]
  870. if op <= '2' and referencetable[n] is not None:
  871. rdict.ll_dict_delitem(l_dict, n)
  872. referencetable[n] = None
  873. referencelength -= 1
  874. elif op <= '6':
  875. rdict.ll_dict_setitem(l_dict, n, value)
  876. if referencetable[n] is None:
  877. referencelength += 1
  878. referencetable[n] = value
  879. value += 1
  880. else:
  881. try:
  882. gotvalue = rdict.ll_dict_getitem(l_dict, n)
  883. except KeyError:
  884. assert referencetable[n] is None
  885. else:
  886. assert gotvalue == referencetable[n]
  887. if 1.38 <= x <= 1.39:
  888. complete_check()
  889. print 'current dict length:', referencelength
  890. assert l_dict.num_items == referencelength
  891. complete_check()
  892. def test_stress_2(self):
  893. yield self.stress_combination, True, False
  894. yield self.stress_combination, False, True
  895. yield self.stress_combination, False, False
  896. yield self.stress_combination, True, True
  897. def stress_combination(self, key_can_be_none, value_can_be_none):
  898. from pypy.rpython.lltypesystem.rstr import string_repr
  899. from pypy.annotation.dictdef import DictKey, DictValue
  900. from pypy.annotation import model as annmodel
  901. print
  902. print "Testing combination with can_be_None: keys %s, values %s" % (
  903. key_can_be_none, value_can_be_none)
  904. class PseudoRTyper:
  905. cache_dummy_values = {}
  906. dictrepr = rdict.DictRepr(PseudoRTyper(), string_repr, string_repr,
  907. DictKey(None, annmodel.SomeString(key_can_be_none)),
  908. DictValue(None, annmodel.SomeString(value_can_be_none)))
  909. dictrepr.setup()
  910. print dictrepr.lowleveltype
  911. for key, value in dictrepr.DICTENTRY._adtmeths.items():
  912. print ' %s = %s' % (key, value)
  913. l_dict = rdict.ll_newdict(dictrepr.DICT)
  914. referencetable = [None] * 400
  915. referencelength = 0
  916. values = not_really_random()
  917. keytable = [string_repr.convert_const("foo%d" % n)
  918. for n in range(len(referencetable))]
  919. def complete_check():
  920. for n, refvalue in zip(range(len(referencetable)), referencetable):
  921. try:
  922. gotvalue = rdict.ll_dict_getitem(l_dict, keytable[n])
  923. except KeyError:
  924. assert refvalue is None
  925. else:
  926. assert gotvalue == refvalue
  927. for x in not_really_random():
  928. n = int(x*100.0) # 0 <= x < 400
  929. op = repr(x)[-1]
  930. if op <= '2' and referencetable[n] is not None:
  931. rdict.ll_dict_delitem(l_dict, keytable[n])
  932. referencetable[n] = None
  933. referencelength -= 1
  934. elif op <= '6':
  935. ll_value = string_repr.convert_const(str(values.next()))
  936. rdict.ll_dict_setitem(l_dict, keytable[n], ll_value)
  937. if referencetable[n] is None:
  938. referencelength += 1
  939. referencetable[n] = ll_value
  940. else:
  941. try:
  942. gotvalue = rdict.ll_dict_getitem(l_dict, keytable[n])
  943. except KeyError:
  944. assert referencetable[n] is None
  945. else:
  946. assert gotvalue == referencetable[n]
  947. if 1.38 <= x <= 1.39:
  948. complete_check()
  949. print 'current dict length:', referencelength
  950. assert l_dict.num_items == referencelength
  951. complete_check()