PageRenderTime 89ms CodeModel.GetById 20ms RepoModel.GetById 1ms app.codeStats 0ms

/rpython/rtyper/test/test_rdict.py

https://bitbucket.org/pypy/pypy/
Python | 1261 lines | 1245 code | 13 blank | 3 comment | 19 complexity | 65c02f3fe74d50ec2ceee9ddf63677dc MD5 | raw file
Possible License(s): AGPL-3.0, BSD-3-Clause, Apache-2.0
  1. import sys
  2. from contextlib import contextmanager
  3. import signal
  4. from rpython.translator.translator import TranslationContext
  5. from rpython.annotator.model import (
  6. SomeInteger, SomeString, SomeChar, SomeUnicodeString, SomeUnicodeCodePoint)
  7. from rpython.annotator.dictdef import DictKey, DictValue
  8. from rpython.rtyper.lltypesystem import lltype, rffi
  9. from rpython.rtyper.lltypesystem import rdict
  10. from rpython.rtyper.test.tool import BaseRtypingTest
  11. from rpython.rlib.objectmodel import r_dict
  12. from rpython.rlib.rarithmetic import r_int, r_uint, r_longlong, r_ulonglong
  13. import py
  14. from hypothesis import settings
  15. from hypothesis.strategies import (
  16. builds, sampled_from, binary, just, integers, text, characters, tuples)
  17. from hypothesis.stateful import GenericStateMachine, run_state_machine_as_test
  18. def ann2strategy(s_value):
  19. if isinstance(s_value, SomeChar):
  20. return builds(chr, integers(min_value=0, max_value=255))
  21. elif isinstance(s_value, SomeString):
  22. if s_value.can_be_None:
  23. return binary() | just(None)
  24. else:
  25. return binary()
  26. elif isinstance(s_value, SomeUnicodeCodePoint):
  27. return characters()
  28. elif isinstance(s_value, SomeUnicodeString):
  29. if s_value.can_be_None:
  30. return text() | just(None)
  31. else:
  32. return text()
  33. elif isinstance(s_value, SomeInteger):
  34. return integers(min_value=~sys.maxint, max_value=sys.maxint)
  35. else:
  36. raise TypeError("Cannot convert annotation %s to a strategy" % s_value)
  37. if hasattr(signal, 'alarm'):
  38. @contextmanager
  39. def signal_timeout(n):
  40. """A flaky context manager that throws an exception if the body of the
  41. `with` block runs for longer than `n` seconds.
  42. """
  43. def handler(signum, frame):
  44. raise RuntimeError('timeout')
  45. signal.signal(signal.SIGALRM, handler)
  46. signal.alarm(n)
  47. try:
  48. yield
  49. finally:
  50. signal.alarm(0)
  51. else:
  52. @contextmanager
  53. def signal_timeout(n):
  54. yield
  55. class BaseTestRDict(BaseRtypingTest):
  56. def test_dict_creation(self):
  57. def createdict(i):
  58. d = self.newdict()
  59. d['hello'] = i
  60. return d['hello']
  61. res = self.interpret(createdict, [42])
  62. assert res == 42
  63. def test_dict_getitem_setitem(self):
  64. def func(i):
  65. d = self.newdict()
  66. d['hello'] = i
  67. d['world'] = i + 1
  68. return d['hello'] * d['world']
  69. res = self.interpret(func, [6])
  70. assert res == 42
  71. def test_dict_getitem_keyerror(self):
  72. def func(i):
  73. d = self.newdict()
  74. d['hello'] = i
  75. try:
  76. return d['world']
  77. except KeyError:
  78. return 0
  79. res = self.interpret(func, [6])
  80. assert res == 0
  81. def test_dict_del_simple(self):
  82. def func(i):
  83. d = self.newdict()
  84. d['hello'] = i
  85. d['world'] = i + 1
  86. del d['hello']
  87. return len(d)
  88. res = self.interpret(func, [6])
  89. assert res == 1
  90. def test_dict_clear(self):
  91. def func(i):
  92. d = self.newdict()
  93. d['abc'] = i
  94. d['def'] = i+1
  95. d.clear()
  96. d['ghi'] = i+2
  97. return ('abc' not in d and 'def' not in d
  98. and d['ghi'] == i+2 and len(d) == 1)
  99. res = self.interpret(func, [7])
  100. assert res == True
  101. def test_empty_strings(self):
  102. def func(i):
  103. d = self.newdict()
  104. d[''] = i
  105. del d['']
  106. try:
  107. d['']
  108. return 0
  109. except KeyError:
  110. pass
  111. return 1
  112. res = self.interpret(func, [6])
  113. assert res == 1
  114. def func(i):
  115. d = self.newdict()
  116. d[''] = i
  117. del d['']
  118. d[''] = i + 1
  119. return len(d)
  120. res = self.interpret(func, [6])
  121. assert res == 1
  122. def test_dict_bool(self):
  123. def func(i):
  124. if i:
  125. d = self.newdict()
  126. else:
  127. d = self.newdict()
  128. d[i] = i+1
  129. if d:
  130. return i
  131. else:
  132. return i+1
  133. assert self.interpret(func, [42]) == 43
  134. assert self.interpret(func, [0]) == 0
  135. def test_contains(self):
  136. def func(x, y):
  137. d = self.newdict()
  138. d[x] = x+1
  139. return y in d
  140. assert self.interpret(func, [42, 0]) == False
  141. assert self.interpret(func, [42, 42]) == True
  142. def test_contains_2(self):
  143. d = self.newdict()
  144. d['5'] = None
  145. d['7'] = None
  146. def func(x):
  147. return chr(x) in d
  148. assert self.interpret(func, [ord('5')]) == True
  149. assert self.interpret(func, [ord('6')]) == False
  150. def func(n):
  151. return str(n) in d
  152. assert self.interpret(func, [512]) == False
  153. def test_dict_iteration(self):
  154. def func(i, j):
  155. d = self.newdict()
  156. d['hello'] = i
  157. d['world'] = j
  158. k = 1
  159. for key in d:
  160. k = k * d[key]
  161. return k
  162. res = self.interpret(func, [6, 7])
  163. assert res == 42
  164. def test_dict_itermethods(self):
  165. def func():
  166. d = self.newdict()
  167. d['hello'] = 6
  168. d['world'] = 7
  169. k1 = k2 = k3 = 1
  170. for key in d.iterkeys():
  171. k1 = k1 * d[key]
  172. for value in d.itervalues():
  173. k2 = k2 * value
  174. for key, value in d.iteritems():
  175. assert d[key] == value
  176. k3 = k3 * value
  177. return k1 + k2 + k3
  178. res = self.interpret(func, [])
  179. assert res == 42 + 42 + 42
  180. def test_dict_get(self):
  181. def func():
  182. dic = self.newdict()
  183. x1 = dic.get('hi', 42)
  184. dic['blah'] = 1 # XXX this triggers type determination
  185. x2 = dic.get('blah', 2)
  186. return x1 * 10 + x2
  187. res = self.interpret(func, ())
  188. assert res == 421
  189. def test_dict_get_empty(self):
  190. def func():
  191. # this time without writing to the dict
  192. dic = self.newdict()
  193. x1 = dic.get('hi', 42)
  194. x2 = dic.get('blah', 2)
  195. return x1 * 10 + x2
  196. res = self.interpret(func, ())
  197. assert res == 422
  198. def test_dict_setdefault(self):
  199. def f():
  200. d = self.newdict()
  201. d.setdefault('a', 2)
  202. return d['a']
  203. res = self.interpret(f, ())
  204. assert res == 2
  205. def f():
  206. d = self.newdict()
  207. d.setdefault('a', 2)
  208. x = d.setdefault('a', -3)
  209. return x
  210. res = self.interpret(f, ())
  211. assert res == 2
  212. def test_dict_copy(self):
  213. def func():
  214. dic = self.newdict()
  215. dic['a'] = 1
  216. dic['b'] = 2
  217. d2 = dic.copy()
  218. ok = 1
  219. for key in d2:
  220. if dic[key] != d2[key]:
  221. ok = 0
  222. ok &= len(dic) == len(d2)
  223. d2['c'] = 3
  224. ok &= len(dic) == len(d2) - 1
  225. return ok
  226. res = self.interpret(func, ())
  227. assert res == 1
  228. def test_dict_update(self):
  229. def func():
  230. dic = self.newdict()
  231. dic['ab'] = 1000
  232. dic['b'] = 200
  233. d2 = self.newdict()
  234. d2['b'] = 30
  235. d2['cb'] = 4
  236. dic.update(d2)
  237. ok = len(dic) == 3
  238. sum = ok
  239. for key in dic:
  240. sum += dic[key]
  241. return sum
  242. res = self.interpret(func, ())
  243. assert res == 1035
  244. def test_dict_keys(self):
  245. def func():
  246. dic = self.newdict()
  247. dic[' 4'] = 1000
  248. dic[' 8'] = 200
  249. keys = dic.keys()
  250. return ord(keys[0][1]) + ord(keys[1][1]) - 2*ord('0') + len(keys)
  251. res = self.interpret(func, ())#, view=True)
  252. assert res == 14
  253. def test_list_dict(self):
  254. def func():
  255. dic = self.newdict()
  256. dic[' 4'] = 1000
  257. dic[' 8'] = 200
  258. keys = list(dic)
  259. return ord(keys[0][1]) + ord(keys[1][1]) - 2*ord('0') + len(keys)
  260. res = self.interpret(func, ())#, view=True)
  261. assert res == 14
  262. def test_dict_inst_keys(self):
  263. class Empty:
  264. pass
  265. class A(Empty):
  266. pass
  267. def func():
  268. dic0 = self.newdict()
  269. dic0[Empty()] = 2
  270. dic = self.newdict()
  271. dic[A()] = 1
  272. dic[A()] = 2
  273. keys = dic.keys()
  274. return (isinstance(keys[1], A))*2+(isinstance(keys[0],A))
  275. res = self.interpret(func, [])
  276. assert res == 3
  277. def test_dict_inst_iterkeys(self):
  278. class Empty:
  279. pass
  280. class A(Empty):
  281. pass
  282. def func():
  283. dic0 = self.newdict()
  284. dic0[Empty()] = 2
  285. dic = self.newdict()
  286. dic[A()] = 1
  287. dic[A()] = 2
  288. a = 0
  289. for k in dic.iterkeys():
  290. a += isinstance(k, A)
  291. return a
  292. res = self.interpret(func, [])
  293. assert res == 2
  294. def test_dict_values(self):
  295. def func():
  296. dic = self.newdict()
  297. dic[' 4'] = 1000
  298. dic[' 8'] = 200
  299. values = dic.values()
  300. return values[0] + values[1] + len(values)
  301. res = self.interpret(func, ())
  302. assert res == 1202
  303. def test_dict_inst_values(self):
  304. class A:
  305. pass
  306. def func():
  307. dic = self.newdict()
  308. dic[1] = A()
  309. dic[2] = A()
  310. vals = dic.values()
  311. return (isinstance(vals[1], A))*2+(isinstance(vals[0],A))
  312. res = self.interpret(func, [])
  313. assert res == 3
  314. def test_dict_inst_itervalues(self):
  315. class A:
  316. pass
  317. def func():
  318. dic = self.newdict()
  319. dic[1] = A()
  320. dic[2] = A()
  321. a = 0
  322. for v in dic.itervalues():
  323. a += isinstance(v, A)
  324. return a
  325. res = self.interpret(func, [])
  326. assert res == 2
  327. def test_dict_inst_items(self):
  328. class Empty:
  329. pass
  330. class A:
  331. pass
  332. class B(Empty):
  333. pass
  334. def func():
  335. dic0 = self.newdict()
  336. dic0[Empty()] = A()
  337. dic = self.newdict()
  338. dic[B()] = A()
  339. dic[B()] = A()
  340. items = dic.items()
  341. b = 0
  342. a = 0
  343. for k, v in items:
  344. b += isinstance(k, B)
  345. a += isinstance(v, A)
  346. return 3*b+a
  347. res = self.interpret(func, [])
  348. assert res == 8
  349. def test_dict_inst_iteritems(self):
  350. class Empty:
  351. pass
  352. class A:
  353. pass
  354. class B(Empty):
  355. pass
  356. def func():
  357. dic0 = self.newdict()
  358. dic0[Empty()] = A()
  359. dic = self.newdict()
  360. dic[B()] = A()
  361. dic[B()] = A()
  362. b = 0
  363. a = 0
  364. for k, v in dic.iteritems():
  365. b += isinstance(k, B)
  366. a += isinstance(v, A)
  367. return 3*b+a
  368. res = self.interpret(func, [])
  369. assert res == 8
  370. def test_dict_items(self):
  371. def func():
  372. dic = self.newdict()
  373. dic[' 4'] = 1000
  374. dic[' 8'] = 200
  375. items = dic.items()
  376. res = len(items)
  377. for key, value in items:
  378. res += ord(key[1]) - ord('0') + value
  379. return res
  380. res = self.interpret(func, ())
  381. assert res == 1214
  382. def test_dict_contains(self):
  383. def func():
  384. dic = self.newdict()
  385. dic[' 4'] = 1000
  386. dic[' 8'] = 200
  387. return ' 4' in dic and ' 9' not in dic
  388. res = self.interpret(func, ())
  389. assert res is True
  390. def test_dict_contains_with_constant_dict(self):
  391. dic = self.newdict()
  392. dic['4'] = 1000
  393. dic['8'] = 200
  394. def func(i):
  395. return chr(i) in dic
  396. res = self.interpret(func, [ord('4')])
  397. assert res is True
  398. res = self.interpret(func, [1])
  399. assert res is False
  400. def test_dict_or_none(self):
  401. class A:
  402. pass
  403. def negate(d):
  404. return not d
  405. def func(n):
  406. a = A()
  407. a.d = None
  408. if n > 0:
  409. a.d = self.newdict()
  410. a.d[str(n)] = 1
  411. a.d["42"] = 2
  412. del a.d["42"]
  413. return negate(a.d)
  414. res = self.interpret(func, [10])
  415. assert res is False
  416. res = self.interpret(func, [0])
  417. assert res is True
  418. res = self.interpret(func, [42])
  419. assert res is True
  420. def test_int_dict(self):
  421. def func(a, b):
  422. dic = self.newdict()
  423. dic[12] = 34
  424. dic[a] = 1000
  425. return dic.get(b, -123)
  426. res = self.interpret(func, [12, 12])
  427. assert res == 1000
  428. res = self.interpret(func, [12, 13])
  429. assert res == -123
  430. res = self.interpret(func, [524, 12])
  431. assert res == 34
  432. res = self.interpret(func, [524, 524])
  433. assert res == 1000
  434. res = self.interpret(func, [524, 1036])
  435. assert res == -123
  436. def test_id_instances_keys(self):
  437. class A:
  438. pass
  439. class B(A):
  440. pass
  441. def f():
  442. a = A()
  443. b = B()
  444. d = self.newdict()
  445. d[b] = 7
  446. d[a] = 3
  447. return len(d) + d[a] + d[b]
  448. res = self.interpret(f, [])
  449. assert res == 12
  450. def test_captured_get(self):
  451. d = self.newdict()
  452. d[1] = 2
  453. get = d.get
  454. def f():
  455. return get(1, 3)+get(2, 4)
  456. res = self.interpret(f, [])
  457. assert res == 6
  458. def g(h):
  459. return h(1, 3)
  460. def f():
  461. return g(get)
  462. res = self.interpret(f, [])
  463. assert res == 2
  464. def test_specific_obscure_bug(self):
  465. class A: pass
  466. class B: pass # unrelated kinds of instances
  467. def f():
  468. lst = [A()]
  469. res1 = A() in lst
  470. d2 = self.newdict()
  471. d2[B()] = None
  472. d2[B()] = None
  473. return res1+len(d2)
  474. res = self.interpret(f, [])
  475. assert res == 2
  476. def test_identity_hash_is_fast(self):
  477. class A(object):
  478. pass
  479. def f():
  480. d = self.newdict()
  481. d[A()] = 1
  482. return d
  483. t = TranslationContext()
  484. s = t.buildannotator().build_types(f, [])
  485. rtyper = t.buildrtyper()
  486. rtyper.specialize()
  487. r_dict = rtyper.getrepr(s)
  488. assert not hasattr(r_dict.lowleveltype.TO.entries.TO.OF, "f_hash")
  489. def test_tuple_dict(self):
  490. def f(i):
  491. d = self.newdict()
  492. d[(1, 4.5, (str(i), 2), 2)] = 4
  493. d[(1, 4.5, (str(i), 2), 3)] = 6
  494. return d[(1, 4.5, (str(i), 2), i)]
  495. res = self.interpret(f, [2])
  496. assert res == f(2)
  497. def test_dict_of_dict(self):
  498. def f(n):
  499. d = self.newdict()
  500. d[5] = d
  501. d[6] = self.newdict()
  502. return len(d[n])
  503. res = self.interpret(f, [5])
  504. assert res == 2
  505. res = self.interpret(f, [6])
  506. assert res == 0
  507. def test_cls_dict(self):
  508. class A(object):
  509. pass
  510. class B(A):
  511. pass
  512. def f(i):
  513. d = self.newdict()
  514. d[A] = 3
  515. d[B] = 4
  516. if i:
  517. cls = A
  518. else:
  519. cls = B
  520. return d[cls]
  521. res = self.interpret(f, [1])
  522. assert res == 3
  523. res = self.interpret(f, [0])
  524. assert res == 4
  525. def test_prebuilt_cls_dict(self):
  526. class A(object):
  527. pass
  528. class B(A):
  529. pass
  530. d = self.newdict()
  531. d[(A, 3)] = 3
  532. d[(B, 0)] = 4
  533. def f(i):
  534. if i:
  535. cls = A
  536. else:
  537. cls = B
  538. try:
  539. return d[cls, i]
  540. except KeyError:
  541. return -99
  542. res = self.interpret(f, [0])
  543. assert res == 4
  544. res = self.interpret(f, [3])
  545. assert res == 3
  546. res = self.interpret(f, [10])
  547. assert res == -99
  548. def test_access_in_try(self):
  549. def f(d):
  550. try:
  551. return d[2]
  552. except ZeroDivisionError:
  553. return 42
  554. return -1
  555. def g(n):
  556. d = self.newdict()
  557. d[1] = n
  558. d[2] = 2*n
  559. return f(d)
  560. res = self.interpret(g, [3])
  561. assert res == 6
  562. def test_access_in_try_set(self):
  563. def f(d):
  564. try:
  565. d[2] = 77
  566. except ZeroDivisionError:
  567. return 42
  568. return -1
  569. def g(n):
  570. d = self.newdict()
  571. d[1] = n
  572. f(d)
  573. return d[2]
  574. res = self.interpret(g, [3])
  575. assert res == 77
  576. def test_resize_during_iteration(self):
  577. def func():
  578. d = self.newdict()
  579. d[5] = 1
  580. d[6] = 2
  581. d[7] = 3
  582. try:
  583. for key, value in d.iteritems():
  584. d[key^16] = value*2
  585. except RuntimeError:
  586. pass
  587. total = 0
  588. for key in d:
  589. total += key
  590. return total
  591. res = self.interpret(func, [])
  592. assert 5 + 6 + 7 <= res <= 5 + 6 + 7 + (5^16) + (6^16) + (7^16)
  593. def test_change_during_iteration(self):
  594. def func():
  595. d = self.newdict()
  596. d['a'] = 1
  597. d['b'] = 2
  598. for key in d:
  599. d[key] = 42
  600. return d['a']
  601. assert self.interpret(func, []) == 42
  602. def test_dict_of_floats(self):
  603. d = self.newdict()
  604. d[3.0] = 42
  605. d[3.1] = 43
  606. d[3.2] = 44
  607. d[3.3] = 45
  608. d[3.4] = 46
  609. def fn(f):
  610. return d[f]
  611. res = self.interpret(fn, [3.0])
  612. assert res == 42
  613. def test_dict_of_r_uint(self):
  614. for r_t in [r_uint, r_longlong, r_ulonglong]:
  615. if r_t is r_int:
  616. continue # for 64-bit platforms: skip r_longlong
  617. d = self.newdict()
  618. d[r_t(2)] = 3
  619. d[r_t(4)] = 5
  620. def fn(x, y):
  621. d[r_t(x)] = 123
  622. return d[r_t(y)]
  623. res = self.interpret(fn, [4, 2])
  624. assert res == 3
  625. res = self.interpret(fn, [3, 3])
  626. assert res == 123
  627. def test_dict_popitem(self):
  628. def func():
  629. d = self.newdict()
  630. d[5] = 2
  631. d[6] = 3
  632. k1, v1 = d.popitem()
  633. assert len(d) == 1
  634. k2, v2 = d.popitem()
  635. try:
  636. d.popitem()
  637. except KeyError:
  638. pass
  639. else:
  640. assert 0, "should have raised KeyError"
  641. assert len(d) == 0
  642. return k1*1000 + v1*100 + k2*10 + v2
  643. res = self.interpret(func, [])
  644. assert res in [5263, 6352]
  645. def test_dict_pop(self):
  646. def f(n, default):
  647. d = self.newdict()
  648. d[2] = 3
  649. d[4] = 5
  650. if default == -1:
  651. try:
  652. x = d.pop(n)
  653. except KeyError:
  654. x = -1
  655. else:
  656. x = d.pop(n, default)
  657. return x * 10 + len(d)
  658. res = self.interpret(f, [2, -1])
  659. assert res == 31
  660. res = self.interpret(f, [3, -1])
  661. assert res == -8
  662. res = self.interpret(f, [2, 5])
  663. assert res == 31
  664. def test_dict_pop_instance(self):
  665. class A(object):
  666. pass
  667. def f(n):
  668. d = self.newdict()
  669. d[2] = A()
  670. x = d.pop(n, None)
  671. if x is None:
  672. return 12
  673. else:
  674. return 15
  675. res = self.interpret(f, [2])
  676. assert res == 15
  677. res = self.interpret(f, [700])
  678. assert res == 12
  679. def test_dict_but_not_with_char_keys(self):
  680. def func(i):
  681. d = self.newdict()
  682. d['h'] = i
  683. try:
  684. return d['hello']
  685. except KeyError:
  686. return 0
  687. res = self.interpret(func, [6])
  688. assert res == 0
  689. def test_dict_valid_resize(self):
  690. # see if we find our keys after resize
  691. def func():
  692. d = self.newdict()
  693. # fill it up
  694. for i in range(10):
  695. d[str(i)] = 0
  696. # delete again
  697. for i in range(10):
  698. del d[str(i)]
  699. res = 0
  700. # if it does not crash, we are fine. It crashes if you forget the hash field.
  701. self.interpret(func, [])
  702. # ____________________________________________________________
  703. def test_dict_of_addresses(self):
  704. from rpython.rtyper.lltypesystem import llmemory
  705. TP = lltype.Struct('x')
  706. a = lltype.malloc(TP, flavor='raw', immortal=True)
  707. b = lltype.malloc(TP, flavor='raw', immortal=True)
  708. def func(i):
  709. d = self.newdict()
  710. d[llmemory.cast_ptr_to_adr(a)] = 123
  711. d[llmemory.cast_ptr_to_adr(b)] = 456
  712. if i > 5:
  713. key = llmemory.cast_ptr_to_adr(a)
  714. else:
  715. key = llmemory.cast_ptr_to_adr(b)
  716. return d[key]
  717. assert self.interpret(func, [3]) == 456
  718. def test_prebuilt_list_of_addresses(self):
  719. from rpython.rtyper.lltypesystem import llmemory
  720. TP = lltype.Struct('x', ('y', lltype.Signed))
  721. a = lltype.malloc(TP, flavor='raw', immortal=True)
  722. b = lltype.malloc(TP, flavor='raw', immortal=True)
  723. c = lltype.malloc(TP, flavor='raw', immortal=True)
  724. a_a = llmemory.cast_ptr_to_adr(a)
  725. a0 = llmemory.cast_ptr_to_adr(a)
  726. assert a_a is not a0
  727. assert a_a == a0
  728. a_b = llmemory.cast_ptr_to_adr(b)
  729. a_c = llmemory.cast_ptr_to_adr(c)
  730. d = self.newdict()
  731. d[a_a] = 3
  732. d[a_b] = 4
  733. d[a_c] = 5
  734. d[a0] = 8
  735. def func(i):
  736. if i == 0:
  737. ptr = a
  738. else:
  739. ptr = b
  740. return d[llmemory.cast_ptr_to_adr(ptr)]
  741. py.test.raises(TypeError, self.interpret, func, [0])
  742. def test_dict_of_voidp(self):
  743. def func():
  744. d = self.newdict()
  745. handle = lltype.nullptr(rffi.VOIDP.TO)
  746. # Use a negative key, so the dict implementation uses
  747. # the value as a marker for empty entries
  748. d[-1] = handle
  749. return len(d)
  750. assert self.interpret(func, []) == 1
  751. from rpython.translator.c.test.test_genc import compile
  752. f = compile(func, [])
  753. res = f()
  754. assert res == 1
  755. def test_dict_with_SHORT_keys(self):
  756. def func(x):
  757. d = self.newdict()
  758. d[rffi.cast(rffi.SHORT, 42)] = 123
  759. d[rffi.cast(rffi.SHORT, -43)] = 321
  760. return d[rffi.cast(rffi.SHORT, x)]
  761. assert self.interpret(func, [42]) == 123
  762. assert self.interpret(func, [2**16 - 43]) == 321
  763. def test_dict_with_bool_keys(self):
  764. def func(x):
  765. d = self.newdict()
  766. d[False] = 123
  767. d[True] = 321
  768. return d[x == 42]
  769. assert self.interpret(func, [5]) == 123
  770. assert self.interpret(func, [42]) == 321
  771. def test_memoryerror_should_not_insert(self):
  772. # This shows a misbehaviour that also exists in CPython 2.7, but not
  773. # any more in CPython 3.3. The behaviour is that even if a dict
  774. # insertion raises MemoryError, the new item is still inserted.
  775. # If we catch the MemoryError, we can keep inserting new items until
  776. # the dict table is completely full. Then the next insertion loops
  777. # forever. This test only checks that after a MemoryError the
  778. # new item was not inserted.
  779. def _check_small_range(self, n):
  780. if n >= 128:
  781. raise MemoryError
  782. return range(n)
  783. original_check_range = lltype._array._check_range
  784. try:
  785. lltype._array._check_range = _check_small_range
  786. #
  787. def do_insert(d, i):
  788. d[i] = i
  789. def func():
  790. d = self.newdict()
  791. i = 0
  792. while True:
  793. try:
  794. do_insert(d, i)
  795. except MemoryError:
  796. return (i in d)
  797. i += 1
  798. res = self.interpret(func, [])
  799. assert res == 0
  800. #
  801. finally:
  802. lltype._array._check_range = original_check_range
  803. def test_dict_with_none_key(self):
  804. def func(i):
  805. d = self.newdict()
  806. d[None] = i
  807. return d[None]
  808. res = self.interpret(func, [42])
  809. assert res == 42
  810. def test_externalvsinternal(self):
  811. class A: pass
  812. class B: pass
  813. class C: pass
  814. class D: pass
  815. def func():
  816. d1 = self.newdict(); d1[A()] = B()
  817. d2 = self.newdict2(); d2[C()] = D()
  818. return (d1, d2)
  819. res = self.interpret(func, [])
  820. assert lltype.typeOf(res.item0) == lltype.typeOf(res.item1)
  821. def test_r_dict(self):
  822. class FooError(Exception):
  823. pass
  824. def myeq(n, m):
  825. return n == m
  826. def myhash(n):
  827. if n < 0:
  828. raise FooError
  829. return -n
  830. def f(n):
  831. d = self.new_r_dict(myeq, myhash)
  832. for i in range(10):
  833. d[i] = i*i
  834. try:
  835. value1 = d[n]
  836. except FooError:
  837. value1 = 99
  838. try:
  839. value2 = n in d
  840. except FooError:
  841. value2 = 99
  842. try:
  843. value3 = d[-n]
  844. except FooError:
  845. value3 = 99
  846. try:
  847. value4 = (-n) in d
  848. except FooError:
  849. value4 = 99
  850. return (value1 * 1000000 +
  851. value2 * 10000 +
  852. value3 * 100 +
  853. value4)
  854. res = self.interpret(f, [5])
  855. assert res == 25019999
  856. def test_r_dict_popitem_hash(self):
  857. def deq(n, m):
  858. return n == m
  859. def dhash(n):
  860. return ~n
  861. def func():
  862. d = self.new_r_dict(deq, dhash)
  863. d[5] = 2
  864. d[6] = 3
  865. k1, v1 = d.popitem()
  866. assert len(d) == 1
  867. k2, v2 = d.popitem()
  868. try:
  869. d.popitem()
  870. except KeyError:
  871. pass
  872. else:
  873. assert 0, "should have raised KeyError"
  874. assert len(d) == 0
  875. return k1*1000 + v1*100 + k2*10 + v2
  876. res = self.interpret(func, [])
  877. assert res in [5263, 6352]
  878. def test_prebuilt_r_dict(self):
  879. def deq(n, m):
  880. return (n & 3) == (m & 3)
  881. def dhash(n):
  882. return n & 3
  883. d = self.new_r_dict(deq, dhash)
  884. d[0x123] = "abcd"
  885. d[0x231] = "efgh"
  886. def func():
  887. return d[0x348973] + d[0x12981]
  888. res = self.interpret(func, [])
  889. res = self.ll_to_string(res)
  890. assert res == "abcdefgh"
  891. class TestRDict(BaseTestRDict):
  892. @staticmethod
  893. def newdict():
  894. return {}
  895. @staticmethod
  896. def newdict2():
  897. return {}
  898. @staticmethod
  899. def new_r_dict(myeq, myhash):
  900. return r_dict(myeq, myhash)
  901. def test_two_dicts_with_different_value_types(self):
  902. def func(i):
  903. d1 = {}
  904. d1['hello'] = i + 1
  905. d2 = {}
  906. d2['world'] = d1
  907. return d2['world']['hello']
  908. res = self.interpret(func, [5])
  909. assert res == 6
  910. def test_type_erase(self):
  911. class A(object):
  912. pass
  913. class B(object):
  914. pass
  915. def f():
  916. d = {}
  917. d[A()] = B()
  918. d2 = {}
  919. d2[B()] = A()
  920. return d, d2
  921. t = TranslationContext()
  922. s = t.buildannotator().build_types(f, [])
  923. rtyper = t.buildrtyper()
  924. rtyper.specialize()
  925. s_AB_dic = s.items[0]
  926. s_BA_dic = s.items[1]
  927. r_AB_dic = rtyper.getrepr(s_AB_dic)
  928. r_BA_dic = rtyper.getrepr(s_BA_dic)
  929. assert r_AB_dic.lowleveltype == r_BA_dic.lowleveltype
  930. def test_opt_dummykeymarker(self):
  931. def f():
  932. d = {"hello": None}
  933. d["world"] = None
  934. return "hello" in d, d
  935. res = self.interpret(f, [])
  936. assert res.item0 == True
  937. DICT = lltype.typeOf(res.item1).TO
  938. assert not hasattr(DICT.entries.TO.OF, 'f_valid') # strs have a dummy
  939. def test_opt_dummyvaluemarker(self):
  940. def f(n):
  941. d = {-5: "abcd"}
  942. d[123] = "def"
  943. return len(d[n]), d
  944. res = self.interpret(f, [-5])
  945. assert res.item0 == 4
  946. DICT = lltype.typeOf(res.item1).TO
  947. assert not hasattr(DICT.entries.TO.OF, 'f_valid') # strs have a dummy
  948. def test_opt_nonnegint_dummy(self):
  949. def f(n):
  950. d = {n: 12}
  951. d[-87] = 24
  952. del d[n]
  953. return len(d.copy()), d[-87], d
  954. res = self.interpret(f, [5])
  955. assert res.item0 == 1
  956. assert res.item1 == 24
  957. DICT = lltype.typeOf(res.item2).TO
  958. assert not hasattr(DICT.entries.TO.OF, 'f_valid')# nonneg int: dummy -1
  959. def test_opt_no_dummy(self):
  960. def f(n):
  961. d = {n: 12}
  962. d[-87] = -24
  963. del d[n]
  964. return len(d.copy()), d[-87], d
  965. res = self.interpret(f, [5])
  966. assert res.item0 == 1
  967. assert res.item1 == -24
  968. DICT = lltype.typeOf(res.item2).TO
  969. assert hasattr(DICT.entries.TO.OF, 'f_valid') # no dummy available
  970. def test_opt_boolean_has_no_dummy(self):
  971. def f(n):
  972. d = {n: True}
  973. d[-87] = True
  974. del d[n]
  975. return len(d.copy()), d[-87], d
  976. res = self.interpret(f, [5])
  977. assert res.item0 == 1
  978. assert res.item1 is True
  979. DICT = lltype.typeOf(res.item2).TO
  980. assert hasattr(DICT.entries.TO.OF, 'f_valid') # no dummy available
  981. def test_opt_multiple_identical_dicts(self):
  982. def f(n):
  983. s = "x" * n
  984. d1 = {s: 12}
  985. d2 = {s: 24}
  986. d3 = {s: 36}
  987. d1["a"] = d2[s] # 24
  988. d3[s] += d1["a"] # 60
  989. d2["bc"] = d3[s] # 60
  990. return d2["bc"], d1, d2, d3
  991. res = self.interpret(f, [5])
  992. assert res.item0 == 60
  993. # all three dicts should use the same low-level type
  994. assert lltype.typeOf(res.item1) == lltype.typeOf(res.item2)
  995. assert lltype.typeOf(res.item1) == lltype.typeOf(res.item3)
  996. def test_nonnull_hint(self):
  997. def eq(a, b):
  998. return a == b
  999. def rhash(a):
  1000. return 3
  1001. def func(i):
  1002. d = r_dict(eq, rhash, force_non_null=True)
  1003. if not i:
  1004. d[None] = i
  1005. else:
  1006. d[str(i)] = i
  1007. return "12" in d, d
  1008. llres = self.interpret(func, [12])
  1009. assert llres.item0 == 1
  1010. DICT = lltype.typeOf(llres.item1)
  1011. assert sorted(DICT.TO.entries.TO.OF._flds) == ['f_hash', 'key', 'value']
  1012. class Action(object):
  1013. def __init__(self, method, args):
  1014. self.method = method
  1015. self.args = args
  1016. def execute(self, space):
  1017. getattr(space, self.method)(*self.args)
  1018. def __repr__(self):
  1019. return "space.%s(%s)" % (self.method, ', '.join(map(repr, self.args)))
  1020. class PseudoRTyper:
  1021. cache_dummy_values = {}
  1022. # XXX: None keys crash the test, but translation sort-of allows it
  1023. keytypes_s = [
  1024. SomeString(), SomeInteger(), SomeChar(),
  1025. SomeUnicodeString(), SomeUnicodeCodePoint()]
  1026. st_keys = sampled_from(keytypes_s)
  1027. st_values = sampled_from(keytypes_s + [SomeString(can_be_None=True)])
  1028. class MappingSpace(object):
  1029. def __init__(self, s_key, s_value):
  1030. self.s_key = s_key
  1031. self.s_value = s_value
  1032. rtyper = PseudoRTyper()
  1033. r_key = s_key.rtyper_makerepr(rtyper)
  1034. r_value = s_value.rtyper_makerepr(rtyper)
  1035. dictrepr = self.MappingRepr(rtyper, r_key, r_value,
  1036. DictKey(None, s_key),
  1037. DictValue(None, s_value))
  1038. dictrepr.setup()
  1039. self.l_dict = self.newdict(dictrepr)
  1040. self.reference = self.new_reference()
  1041. self.ll_key = r_key.convert_const
  1042. self.ll_value = r_value.convert_const
  1043. def setitem(self, key, value):
  1044. ll_key = self.ll_key(key)
  1045. ll_value = self.ll_value(value)
  1046. self.ll_setitem(self.l_dict, ll_key, ll_value)
  1047. self.reference[key] = value
  1048. assert self.ll_contains(self.l_dict, ll_key)
  1049. def delitem(self, key):
  1050. ll_key = self.ll_key(key)
  1051. self.ll_delitem(self.l_dict, ll_key)
  1052. del self.reference[key]
  1053. assert not self.ll_contains(self.l_dict, ll_key)
  1054. def copydict(self):
  1055. self.l_dict = self.ll_copy(self.l_dict)
  1056. assert self.ll_len(self.l_dict) == len(self.reference)
  1057. def cleardict(self):
  1058. self.ll_clear(self.l_dict)
  1059. self.reference.clear()
  1060. assert self.ll_len(self.l_dict) == 0
  1061. def fullcheck(self):
  1062. assert self.ll_len(self.l_dict) == len(self.reference)
  1063. for key, value in self.reference.iteritems():
  1064. assert (self.ll_getitem(self.l_dict, self.ll_key(key)) ==
  1065. self.ll_value(value))
  1066. class MappingSM(GenericStateMachine):
  1067. def __init__(self):
  1068. self.space = None
  1069. def st_setitem(self):
  1070. return builds(Action,
  1071. just('setitem'), tuples(self.st_keys, self.st_values))
  1072. def st_updateitem(self):
  1073. return builds(Action,
  1074. just('setitem'),
  1075. tuples(sampled_from(self.space.reference), self.st_values))
  1076. def st_delitem(self):
  1077. return builds(Action,
  1078. just('delitem'), tuples(sampled_from(self.space.reference)))
  1079. def steps(self):
  1080. if not self.space:
  1081. return builds(Action, just('setup'), tuples(st_keys, st_values))
  1082. global_actions = [Action('copydict', ()), Action('cleardict', ())]
  1083. if self.space.reference:
  1084. return (
  1085. self.st_setitem() | sampled_from(global_actions) |
  1086. self.st_updateitem() | self.st_delitem())
  1087. else:
  1088. return (self.st_setitem() | sampled_from(global_actions))
  1089. def execute_step(self, action):
  1090. if action.method == 'setup':
  1091. self.space = self.Space(*action.args)
  1092. self.st_keys = ann2strategy(self.space.s_key)
  1093. self.st_values = ann2strategy(self.space.s_value)
  1094. return
  1095. with signal_timeout(10): # catches infinite loops
  1096. action.execute(self.space)
  1097. def teardown(self):
  1098. if self.space:
  1099. self.space.fullcheck()
  1100. class DictSpace(MappingSpace):
  1101. MappingRepr = rdict.DictRepr
  1102. new_reference = dict
  1103. ll_getitem = staticmethod(rdict.ll_dict_getitem)
  1104. ll_setitem = staticmethod(rdict.ll_dict_setitem)
  1105. ll_delitem = staticmethod(rdict.ll_dict_delitem)
  1106. ll_len = staticmethod(rdict.ll_dict_len)
  1107. ll_contains = staticmethod(rdict.ll_contains)
  1108. ll_copy = staticmethod(rdict.ll_copy)
  1109. ll_clear = staticmethod(rdict.ll_clear)
  1110. def newdict(self, repr):
  1111. return rdict.ll_newdict(repr.DICT)
  1112. class DictSM(MappingSM):
  1113. Space = DictSpace
  1114. def test_hypothesis():
  1115. run_state_machine_as_test(
  1116. DictSM, settings(max_examples=500, stateful_step_count=100))