PageRenderTime 54ms CodeModel.GetById 15ms RepoModel.GetById 0ms app.codeStats 0ms

/rpython/rlib/test/test_rmmap.py

https://bitbucket.org/pypy/pypy/
Python | 502 lines | 472 code | 29 blank | 1 comment | 13 complexity | 7d2613175a08a186e2930fbdb3e30ac2 MD5 | raw file
Possible License(s): AGPL-3.0, BSD-3-Clause, Apache-2.0
  1. from rpython.tool.udir import udir
  2. import os, sys, py
  3. from rpython.rtyper.test.test_llinterp import interpret
  4. from rpython.rtyper.lltypesystem import rffi, lltype
  5. from rpython.rlib.rarithmetic import intmask
  6. from rpython.rlib import rmmap as mmap
  7. from rpython.rlib.rmmap import RTypeError, RValueError, alloc, free
  8. from rpython.rlib.rmmap import madvise_free
  9. class TestMMap:
  10. def setup_class(cls):
  11. cls.tmpname = str(udir.join('mmap-'))
  12. def test_page_size(self):
  13. def f():
  14. assert mmap.PAGESIZE > 0
  15. assert isinstance(mmap.PAGESIZE, int)
  16. interpret(f, [])
  17. def test_attributes(self):
  18. def f():
  19. assert isinstance(mmap.ACCESS_READ, int)
  20. assert isinstance(mmap.ACCESS_WRITE, int)
  21. assert isinstance(mmap.ACCESS_COPY, int)
  22. if os.name == "posix":
  23. assert isinstance(mmap.MAP_ANON, int)
  24. assert isinstance(mmap.MAP_ANONYMOUS, int)
  25. assert isinstance(mmap.MAP_PRIVATE, int)
  26. assert isinstance(mmap.MAP_SHARED, int)
  27. assert isinstance(mmap.PROT_EXEC, int)
  28. assert isinstance(mmap.PROT_READ, int)
  29. assert isinstance(mmap.PROT_WRITE, int)
  30. interpret(f, [])
  31. def test_file_size(self):
  32. def func(no):
  33. try:
  34. mmap.mmap(no, 123)
  35. except RValueError:
  36. pass
  37. else:
  38. raise Exception("didn't raise")
  39. f = open(self.tmpname + "a", "w+")
  40. f.write("c")
  41. f.flush()
  42. interpret(func, [f.fileno()])
  43. f.close()
  44. def test_create(self):
  45. f = open(self.tmpname + "b", "w+")
  46. f.write("c")
  47. f.flush()
  48. def func(no):
  49. m = mmap.mmap(no, 1)
  50. assert m.read(99) == "c"
  51. interpret(func, [f.fileno()])
  52. f.close()
  53. @py.test.mark.skipif("os.name != 'posix'")
  54. def test_unmap_range(self):
  55. f = open(self.tmpname + "-unmap-range", "w+")
  56. left, right, size = 100, 200, 500 # in pages
  57. f.write(size*4096*"c")
  58. f.flush()
  59. def func(no):
  60. m = mmap.mmap(no, size*4096)
  61. m.unmap_range(left*4096, (right-left)*4096)
  62. m.read(1)
  63. m.seek(right*4096)
  64. m.read(1)
  65. def in_map(m, offset):
  66. return rffi.ptradd(m.data, offset)
  67. def as_num(ptr):
  68. return rffi.cast(lltype.Unsigned, ptr)
  69. res = mmap.alloc_hinted(in_map(m, (left+right)/2 * 4096), 4096)
  70. assert as_num(in_map(m, left*4096)) <= as_num(res) < as_num(in_map(m, right*4096))
  71. interpret(func, [f.fileno()])
  72. f.close()
  73. def test_close(self):
  74. f = open(self.tmpname + "c", "w+")
  75. f.write("c")
  76. f.flush()
  77. def func(no):
  78. m = mmap.mmap(no, 1)
  79. m.close()
  80. try:
  81. m.check_valid()
  82. except RValueError:
  83. pass
  84. else:
  85. raise Exception("Did not raise")
  86. interpret(func, [f.fileno()])
  87. f.close()
  88. def test_read_byte(self):
  89. f = open(self.tmpname + "d", "w+")
  90. f.write("c")
  91. f.flush()
  92. def func(no):
  93. m = mmap.mmap(no, 1)
  94. assert m.read_byte() == "c"
  95. try:
  96. m.read_byte()
  97. except RValueError:
  98. pass
  99. else:
  100. raise Exception("Did not raise")
  101. m.close()
  102. interpret(func, [f.fileno()])
  103. f.close()
  104. def test_readline(self):
  105. import os
  106. f = open(self.tmpname + "e", "w+")
  107. f.write("foo\n")
  108. f.flush()
  109. def func(no):
  110. m = mmap.mmap(no, 4)
  111. if os.name == "nt":
  112. # windows replaces \n with \r. it's time to change to \n only MS!
  113. assert m.readline() == "foo\r"
  114. elif os.name == "posix":
  115. assert m.readline() == "foo\n"
  116. assert m.readline() == ""
  117. m.close()
  118. interpret(func, [f.fileno()])
  119. f.close()
  120. def test_read(self):
  121. f = open(self.tmpname + "f", "w+")
  122. f.write("foobar")
  123. f.flush()
  124. def func(no):
  125. m = mmap.mmap(no, 6)
  126. assert m.read(1) == "f"
  127. assert m.read(6) == "oobar"
  128. assert m.read(1) == ""
  129. m.close()
  130. interpret(func, [f.fileno()])
  131. f.close()
  132. def test_find_rfind(self):
  133. f = open(self.tmpname + "g", "w+")
  134. f.write("foobarfoobar\0")
  135. f.flush()
  136. m = mmap.mmap(f.fileno(), 13)
  137. for s1 in range(-20, 20):
  138. for e1 in range(-20, 20):
  139. expected = "foobarfoobar\0".find("ob", s1, e1)
  140. assert m.find("ob", s1, e1, False) == expected
  141. expected = "foobarfoobar\0".rfind("ob", s1, e1)
  142. assert m.find("ob", s1, e1, True) == expected
  143. m.close()
  144. f.close()
  145. def test_find(self):
  146. f = open(self.tmpname + "g", "w+")
  147. f.write("foobarfoobar\0")
  148. f.flush()
  149. def func(no):
  150. m = mmap.mmap(no, 12)
  151. assert m.find("\0", 0, 13) == -1 # no searching past the stop
  152. assert m.find("\0", 0, 13, True) == -1
  153. m.close()
  154. #
  155. m = mmap.mmap(no, 13)
  156. assert m.find("b", 0, 7) == 3
  157. assert m.find("z", 0, 7) == -1
  158. assert m.find("o", 11, 13) == -1
  159. assert m.find("ob", 0, 7) == 2
  160. assert m.find("\0", 0, 13) == 12
  161. assert m.find("o", 1, 4) == 1
  162. assert m.find("o", 2, 4) == 2
  163. assert m.find("o", 2, -4) == 2
  164. assert m.find("o", 8, -5) == -1
  165. m.close()
  166. func(f.fileno())
  167. interpret(func, [f.fileno()])
  168. f.close()
  169. def test_is_modifiable(self):
  170. f = open(self.tmpname + "h", "w+")
  171. f.write("foobar")
  172. f.flush()
  173. def func(no):
  174. m = mmap.mmap(no, 6, access=mmap.ACCESS_READ)
  175. try:
  176. m.check_writeable()
  177. except RTypeError:
  178. pass
  179. else:
  180. assert False
  181. try:
  182. m.check_resizeable()
  183. except RTypeError:
  184. pass
  185. else:
  186. assert False
  187. m.close()
  188. interpret(func, [f.fileno()])
  189. f.close()
  190. def test_seek(self):
  191. f = open(self.tmpname + "i", "w+")
  192. f.write("foobar")
  193. f.flush()
  194. def func(no):
  195. m = mmap.mmap(no, 6)
  196. m.seek(0)
  197. assert m.tell() == 0
  198. m.read(1)
  199. m.seek(1, 1)
  200. assert m.tell() == 2
  201. m.seek(0)
  202. m.seek(-1, 2)
  203. assert m.tell() == 5
  204. m.close()
  205. interpret(func, [f.fileno()])
  206. f.close()
  207. def test_write(self):
  208. f = open(self.tmpname + "j", "w+")
  209. f.write("foobar")
  210. f.flush()
  211. def func(no):
  212. m = mmap.mmap(no, 6, access=mmap.ACCESS_WRITE)
  213. m.write("ciao\n")
  214. m.seek(0)
  215. assert m.read(6) == "ciao\nr"
  216. m.close()
  217. interpret(func, [f.fileno()])
  218. f.close()
  219. def test_write_byte(self):
  220. f = open(self.tmpname + "k", "w+")
  221. f.write("foobar")
  222. f.flush()
  223. def func(no):
  224. m = mmap.mmap(no, 6, access=mmap.ACCESS_READ)
  225. m = mmap.mmap(no, 6, access=mmap.ACCESS_WRITE)
  226. m.write_byte("x")
  227. m.seek(0)
  228. assert m.read(6) == "xoobar"
  229. m.close()
  230. interpret(func, [f.fileno()])
  231. f.close()
  232. def test_write_readonly(self):
  233. if os.name == "nt":
  234. py.test.skip("Needs PROT_READ")
  235. f = open(self.tmpname + "l", "w+")
  236. f.write("foobar")
  237. f.flush()
  238. m = mmap.mmap(f.fileno(), 6, prot=mmap.PROT_READ)
  239. py.test.raises(RTypeError, m.check_writeable)
  240. m.close()
  241. f.close()
  242. def test_write_without_protwrite(self):
  243. if os.name == "nt":
  244. py.test.skip("Needs PROT_WRITE")
  245. f = open(self.tmpname + "l2", "w+")
  246. f.write("foobar")
  247. f.flush()
  248. m = mmap.mmap(f.fileno(), 6, prot=mmap.PROT_READ|mmap.PROT_EXEC)
  249. py.test.raises(RTypeError, m.check_writeable)
  250. py.test.raises(RTypeError, m.check_writeable)
  251. m.close()
  252. f.close()
  253. def test_size(self):
  254. f = open(self.tmpname + "l3", "w+")
  255. f.write("foobar")
  256. f.flush()
  257. def func(no):
  258. m = mmap.mmap(no, 5)
  259. assert m.file_size() == 6 # size of the underline file, not the mmap
  260. m.close()
  261. interpret(func, [f.fileno()])
  262. f.close()
  263. def test_tell(self):
  264. f = open(self.tmpname + "m", "w+")
  265. f.write("c")
  266. f.flush()
  267. def func(no):
  268. m = mmap.mmap(no, 1)
  269. assert m.tell() >= 0
  270. m.close()
  271. interpret(func, [f.fileno()])
  272. f.close()
  273. def test_move(self):
  274. f = open(self.tmpname + "o", "w+")
  275. f.write("foobar")
  276. f.flush()
  277. def func(no):
  278. m = mmap.mmap(no, 6, access=mmap.ACCESS_WRITE)
  279. m.move(1, 3, 3)
  280. assert m.read(6) == "fbarar"
  281. m.seek(0)
  282. m.move(1, 3, 2)
  283. a = m.read(6)
  284. assert a == "frarar"
  285. m.close()
  286. interpret(func, [f.fileno()])
  287. f.close()
  288. def test_resize(self):
  289. if ("darwin" in sys.platform) or ("freebsd" in sys.platform):
  290. py.test.skip("resize does not work under OSX or FreeBSD")
  291. import os
  292. f = open(self.tmpname + "p", "w+")
  293. f.write("foobar")
  294. f.flush()
  295. def func(no):
  296. m = mmap.mmap(no, 6, access=mmap.ACCESS_WRITE)
  297. f_size = os.fstat(no).st_size
  298. assert intmask(m.file_size()) == f_size == 6
  299. m.resize(10)
  300. f_size = os.fstat(no).st_size
  301. assert intmask(m.file_size()) == f_size == 10
  302. m.close()
  303. interpret(func, [f.fileno()])
  304. f.close()
  305. def test_len(self):
  306. f = open(self.tmpname + "q", "w+")
  307. f.write("foobar")
  308. f.flush()
  309. def func(no):
  310. m = mmap.mmap(no, 6)
  311. assert m.len() == 6
  312. m.close()
  313. interpret(func, [f.fileno()])
  314. f.close()
  315. def test_get_item(self):
  316. f = open(self.tmpname + "r", "w+")
  317. f.write("foobar")
  318. f.flush()
  319. def func(no):
  320. m = mmap.mmap(no, 6)
  321. assert m.getitem(0) == 'f'
  322. assert m.getitem(-1) == 'r'
  323. # sl = slice(1, 2)
  324. # assert m.get_item(sl) == 'o'
  325. m.close()
  326. interpret(func, [f.fileno()])
  327. f.close()
  328. def test_set_item(self):
  329. f = open(self.tmpname + "s", "w+")
  330. f.write("foobar")
  331. f.flush()
  332. def func(no):
  333. m = mmap.mmap(no, 6, access=mmap.ACCESS_WRITE)
  334. # def f(m): m[1:3] = u'xx'
  335. # py.test.raises(IndexError, f, m)
  336. # def f(m): m[1:4] = "zz"
  337. # py.test.raises(IndexError, f, m)
  338. # def f(m): m[1:6] = "z" * 6
  339. # py.test.raises(IndexError, f, m)
  340. # def f(m): m[:2] = "z" * 5
  341. # m[1:3] = 'xx'
  342. # assert m.read(6) == "fxxbar"
  343. # m.seek(0)
  344. m.setitem(0, 'x')
  345. assert m.getitem(0) == 'x'
  346. m.setitem(-6, 'y')
  347. data = m.read(6)
  348. assert data == "yoobar" # yxxbar with slice's stuff
  349. m.close()
  350. interpret(func, [f.fileno()])
  351. f.close()
  352. def test_double_close(self):
  353. f = open(self.tmpname + "s", "w+")
  354. f.write("foobar")
  355. f.flush()
  356. def func(no):
  357. m = mmap.mmap(no, 6, access=mmap.ACCESS_WRITE)
  358. m.close()
  359. m.close() # didn't explode
  360. interpret(func, [f.fileno()])
  361. f.close()
  362. def test_translated(self):
  363. from rpython.translator.c.test.test_genc import compile
  364. def func(no):
  365. m = mmap.mmap(no, 1)
  366. r = m.read_byte()
  367. m.close()
  368. return r
  369. compile(func, [int], gcpolicy='boehm')
  370. def test_windows_crasher_1(self):
  371. if sys.platform != "win32":
  372. py.test.skip("Windows-only test")
  373. def func():
  374. m = mmap.mmap(-1, 1000, tagname="foo")
  375. # same tagname, but larger size
  376. try:
  377. m2 = mmap.mmap(-1, 5000, tagname="foo")
  378. m2.getitem(4500)
  379. except WindowsError:
  380. pass
  381. m.close()
  382. interpret(func, [])
  383. def test_windows_crasher_2(self):
  384. if sys.platform != "win32":
  385. py.test.skip("Windows-only test")
  386. f = open(self.tmpname + "t", "w+")
  387. f.write("foobar")
  388. f.flush()
  389. f = open(self.tmpname + "t", "r+b")
  390. m = mmap.mmap(f.fileno(), 0)
  391. f.close()
  392. py.test.raises(WindowsError, m.resize, 0)
  393. py.test.raises(RValueError, m.getitem, 0)
  394. m.close()
  395. def test_alloc_free():
  396. map_size = 65536
  397. data = alloc(map_size)
  398. for i in range(0, map_size, 171):
  399. data[i] = chr(i & 0xff)
  400. for i in range(0, map_size, 171):
  401. assert data[i] == chr(i & 0xff)
  402. madvise_free(data, map_size)
  403. free(data, map_size)
  404. def test_compile_alloc_free():
  405. from rpython.translator.c.test.test_genc import compile
  406. fn = compile(test_alloc_free, [], gcpolicy='boehm')
  407. fn()