msgpack_functions_spec.lua 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820
  1. local t = require('test.testutil')
  2. local n = require('test.functional.testnvim')()
  3. local clear = n.clear
  4. local fn = n.fn
  5. local eval, eq = n.eval, t.eq
  6. local command = n.command
  7. local api = n.api
  8. local exc_exec = n.exc_exec
  9. local is_os = t.is_os
  10. describe('msgpack*() functions', function()
  11. before_each(clear)
  12. local obj_test = function(msg, obj)
  13. it(msg, function()
  14. api.nvim_set_var('obj', obj)
  15. eq(obj, eval('msgpackparse(msgpackdump(g:obj))'))
  16. eq(obj, eval('msgpackparse(msgpackdump(g:obj, "B"))'))
  17. end)
  18. end
  19. -- Regression test: msgpack_list_write was failing to write buffer with zero
  20. -- length.
  21. obj_test('are able to dump and restore {"file": ""}', { { file = '' } })
  22. -- Regression test: msgpack_list_write was failing to write buffer with NL at
  23. -- the end.
  24. obj_test('are able to dump and restore {0, "echo mpack"}', { { 0, 'echo mpack' } })
  25. obj_test('are able to dump and restore "Test\\n"', { 'Test\n' })
  26. -- Regression test: msgpack_list_write was failing to write buffer with NL
  27. -- inside.
  28. obj_test('are able to dump and restore "Test\\nTest 2"', { 'Test\nTest 2' })
  29. -- Test that big objects (requirement: dump to something that is bigger then
  30. -- IOSIZE) are also fine. This particular object is obtained by concatenating
  31. -- 5 identical shada files.
  32. -- stylua: ignore
  33. local big_obj = {
  34. 1, 1436711454, 78, {
  35. encoding="utf-8",
  36. max_kbyte=10,
  37. pid=19269,
  38. version="NVIM 0.0.0-alpha+201507121634"
  39. },
  40. 8, 1436711451, 40, { file="/home/zyx/.nvim/shada/main.shada" },
  41. 8, 1436711391, 8, { file="" },
  42. 4, 1436700940, 30, { 0, "call mkdir('/tmp/tty/tty')" },
  43. 4, 1436701355, 35, { 0, "call mkdir('/tmp/tty/tty', 'p')" },
  44. 4, 1436701368, 24, { 0, "call mkdir('/', 'p')" },
  45. 4, 1436701375, 26, { 0, "call mkdir('/tty/tty')" },
  46. 4, 1436701383, 30, { 0, "call mkdir('/tty/tty/tty')" },
  47. 4, 1436701407, 35, { 0, "call mkdir('/usr/tty/tty', 'p')" },
  48. 4, 1436701666, 35, { 0, "call mkdir('/tty/tty/tty', 'p')" },
  49. 4, 1436708101, 25, { 0, "echo msgpackdump([1])" },
  50. 4, 1436708966, 6, { 0, "cq" },
  51. 4, 1436709606, 25, { 0, "echo msgpackdump([5])" },
  52. 4, 1436709610, 26, { 0, "echo msgpackdump([10])" },
  53. 4, 1436709615, 31, { 0, "echo msgpackdump([5, 5, 5])" },
  54. 4, 1436709618, 35, { 0, "echo msgpackdump([5, 5, 5, 10])" },
  55. 4, 1436709634, 57, {
  56. 0,
  57. "echo msgpackdump([5, 5, 5, 10, [10, 20, {\"abc\": 1}]])"
  58. },
  59. 4, 1436709651, 67, {
  60. 0,
  61. "echo msgpackdump([5, 5, 5, 10, [10, 20, {\"abc\": 1, \"def\": 0}]])"
  62. },
  63. 4, 1436709660, 70, {
  64. 0,
  65. "echo msgpackdump([5, 5, 5, 10, [10, 20, {\"abc\": 1, \"def\": 0}], 0])"
  66. },
  67. 4, 1436710095, 29, { 0, "echo msgpackparse([\"\\n\"])" },
  68. 4, 1436710100, 28, { 0, "echo msgpackparse([\"j\"])" },
  69. 4, 1436710109, 31, { 0, "echo msgpackparse([\"\", \"\"])" },
  70. 4, 1436710424, 33, { 0, "echo msgpackparse([\"\", \"\\n\"])" },
  71. 4, 1436710428, 32, { 0, "echo msgpackparse([\"\", \"j\"])" },
  72. 4, 1436711142, 14, { 0, "echo mpack" },
  73. 4, 1436711196, 45, { 0, "let lengths = map(mpack[:], 'len(v:val)')" },
  74. 4, 1436711206, 16, { 0, "echo lengths" },
  75. 4, 1436711244, 92, {
  76. 0,
  77. ("let sum = len(lengths) - 1 | call map(copy(lengths), "
  78. .. "'extend(g:, {\"sum\": sum + v:val})')")
  79. },
  80. 4, 1436711245, 12, { 0, "echo sum" },
  81. 4, 1436711398, 10, { 0, "echo s" },
  82. 4, 1436711404, 41, { 0, "let mpack = readfile('/tmp/foo', 'b')" },
  83. 4, 1436711408, 41, { 0, "let shada_objects=msgpackparse(mpack)" },
  84. 4, 1436711415, 22, { 0, "echo shada_objects" },
  85. 4, 1436711451, 30, { 0, "e ~/.nvim/shada/main.shada" },
  86. 4, 1436711454, 6, { 0, "qa" },
  87. 4, 1436711442, 9, { 1, "test", 47 },
  88. 4, 1436711443, 15, { 1, "aontsuesan", 47 },
  89. 2, 1436711443, 38, { hlsearch=1, pat="aontsuesan", smartcase=1 },
  90. 2, 0, 31, { islast=0, pat="", smartcase=1, sub=1 },
  91. 3, 0, 3, { "" },
  92. 10, 1436711451, 40, { file="/home/zyx/.nvim/shada/main.shada" },
  93. 1, 1436711454, 78, {
  94. encoding="utf-8",
  95. max_kbyte=10,
  96. pid=19269,
  97. version="NVIM 0.0.0-alpha+201507121634"
  98. },
  99. 8, 1436711451, 40, { file="/home/zyx/.nvim/shada/main.shada" },
  100. 8, 1436711391, 8, { file="" },
  101. 4, 1436700940, 30, { 0, "call mkdir('/tmp/tty/tty')" },
  102. 4, 1436701355, 35, { 0, "call mkdir('/tmp/tty/tty', 'p')" },
  103. 4, 1436701368, 24, { 0, "call mkdir('/', 'p')" },
  104. 4, 1436701375, 26, { 0, "call mkdir('/tty/tty')" },
  105. 4, 1436701383, 30, { 0, "call mkdir('/tty/tty/tty')" },
  106. 4, 1436701407, 35, { 0, "call mkdir('/usr/tty/tty', 'p')" },
  107. 4, 1436701666, 35, { 0, "call mkdir('/tty/tty/tty', 'p')" },
  108. 4, 1436708101, 25, { 0, "echo msgpackdump([1])" },
  109. 4, 1436708966, 6, { 0, "cq" },
  110. 4, 1436709606, 25, { 0, "echo msgpackdump([5])" },
  111. 4, 1436709610, 26, { 0, "echo msgpackdump([10])" },
  112. 4, 1436709615, 31, { 0, "echo msgpackdump([5, 5, 5])" },
  113. 4, 1436709618, 35, { 0, "echo msgpackdump([5, 5, 5, 10])" },
  114. 4, 1436709634, 57, {
  115. 0,
  116. "echo msgpackdump([5, 5, 5, 10, [10, 20, {\"abc\": 1}]])"
  117. },
  118. 4, 1436709651, 67, {
  119. 0,
  120. "echo msgpackdump([5, 5, 5, 10, [10, 20, {\"abc\": 1, \"def\": 0}]])"
  121. },
  122. 4, 1436709660, 70, {
  123. 0,
  124. "echo msgpackdump([5, 5, 5, 10, [10, 20, {\"abc\": 1, \"def\": 0}], 0])"
  125. },
  126. 4, 1436710095, 29, { 0, "echo msgpackparse([\"\\n\"])" },
  127. 4, 1436710100, 28, { 0, "echo msgpackparse([\"j\"])" },
  128. 4, 1436710109, 31, { 0, "echo msgpackparse([\"\", \"\"])" },
  129. 4, 1436710424, 33, { 0, "echo msgpackparse([\"\", \"\\n\"])" },
  130. 4, 1436710428, 32, { 0, "echo msgpackparse([\"\", \"j\"])" },
  131. 4, 1436711142, 14, { 0, "echo mpack" },
  132. 4, 1436711196, 45, { 0, "let lengths = map(mpack[:], 'len(v:val)')" },
  133. 4, 1436711206, 16, { 0, "echo lengths" },
  134. 4, 1436711244, 92, {
  135. 0,
  136. ("let sum = len(lengths) - 1 | call map(copy(lengths), "
  137. .. "'extend(g:, {\"sum\": sum + v:val})')")
  138. },
  139. 4, 1436711245, 12, { 0, "echo sum" },
  140. 4, 1436711398, 10, { 0, "echo s" },
  141. 4, 1436711404, 41, { 0, "let mpack = readfile('/tmp/foo', 'b')" },
  142. 4, 1436711408, 41, { 0, "let shada_objects=msgpackparse(mpack)" },
  143. 4, 1436711415, 22, { 0, "echo shada_objects" },
  144. 4, 1436711451, 30, { 0, "e ~/.nvim/shada/main.shada" },
  145. 4, 1436711454, 6, { 0, "qa" },
  146. 4, 1436711442, 9, { 1, "test", 47 },
  147. 4, 1436711443, 15, { 1, "aontsuesan", 47 },
  148. 2, 1436711443, 38, { hlsearch=1, pat="aontsuesan", smartcase=1 },
  149. 2, 0, 31, { islast=0, pat="", smartcase=1, sub=1 },
  150. 3, 0, 3, { "" },
  151. 10, 1436711451, 40, { file="/home/zyx/.nvim/shada/main.shada" },
  152. 1, 1436711454, 78, {
  153. encoding="utf-8",
  154. max_kbyte=10,
  155. pid=19269,
  156. version="NVIM 0.0.0-alpha+201507121634"
  157. },
  158. 8, 1436711451, 40, { file="/home/zyx/.nvim/shada/main.shada" },
  159. 8, 1436711391, 8, { file="" },
  160. 4, 1436700940, 30, { 0, "call mkdir('/tmp/tty/tty')" },
  161. 4, 1436701355, 35, { 0, "call mkdir('/tmp/tty/tty', 'p')" },
  162. 4, 1436701368, 24, { 0, "call mkdir('/', 'p')" },
  163. 4, 1436701375, 26, { 0, "call mkdir('/tty/tty')" },
  164. 4, 1436701383, 30, { 0, "call mkdir('/tty/tty/tty')" },
  165. 4, 1436701407, 35, { 0, "call mkdir('/usr/tty/tty', 'p')" },
  166. 4, 1436701666, 35, { 0, "call mkdir('/tty/tty/tty', 'p')" },
  167. 4, 1436708101, 25, { 0, "echo msgpackdump([1])" },
  168. 4, 1436708966, 6, { 0, "cq" },
  169. 4, 1436709606, 25, { 0, "echo msgpackdump([5])" },
  170. 4, 1436709610, 26, { 0, "echo msgpackdump([10])" },
  171. 4, 1436709615, 31, { 0, "echo msgpackdump([5, 5, 5])" },
  172. 4, 1436709618, 35, { 0, "echo msgpackdump([5, 5, 5, 10])" },
  173. 4, 1436709634, 57, {
  174. 0,
  175. "echo msgpackdump([5, 5, 5, 10, [10, 20, {\"abc\": 1}]])"
  176. },
  177. 4, 1436709651, 67, {
  178. 0,
  179. "echo msgpackdump([5, 5, 5, 10, [10, 20, {\"abc\": 1, \"def\": 0}]])"
  180. },
  181. 4, 1436709660, 70, {
  182. 0,
  183. "echo msgpackdump([5, 5, 5, 10, [10, 20, {\"abc\": 1, \"def\": 0}], 0])"
  184. },
  185. 4, 1436710095, 29, { 0, "echo msgpackparse([\"\\n\"])" },
  186. 4, 1436710100, 28, { 0, "echo msgpackparse([\"j\"])" },
  187. 4, 1436710109, 31, { 0, "echo msgpackparse([\"\", \"\"])" },
  188. 4, 1436710424, 33, { 0, "echo msgpackparse([\"\", \"\\n\"])" },
  189. 4, 1436710428, 32, { 0, "echo msgpackparse([\"\", \"j\"])" },
  190. 4, 1436711142, 14, { 0, "echo mpack" },
  191. 4, 1436711196, 45, { 0, "let lengths = map(mpack[:], 'len(v:val)')" },
  192. 4, 1436711206, 16, { 0, "echo lengths" },
  193. 4, 1436711244, 92, {
  194. 0,
  195. ("let sum = len(lengths) - 1 | call map(copy(lengths), "
  196. .. "'extend(g:, {\"sum\": sum + v:val})')")
  197. },
  198. 4, 1436711245, 12, { 0, "echo sum" },
  199. 4, 1436711398, 10, { 0, "echo s" },
  200. 4, 1436711404, 41, { 0, "let mpack = readfile('/tmp/foo', 'b')" },
  201. 4, 1436711408, 41, { 0, "let shada_objects=msgpackparse(mpack)" },
  202. 4, 1436711415, 22, { 0, "echo shada_objects" },
  203. 4, 1436711451, 30, { 0, "e ~/.nvim/shada/main.shada" },
  204. 4, 1436711454, 6, { 0, "qa" },
  205. 4, 1436711442, 9, { 1, "test", 47 },
  206. 4, 1436711443, 15, { 1, "aontsuesan", 47 },
  207. 2, 1436711443, 38, { hlsearch=1, pat="aontsuesan", smartcase=1 },
  208. 2, 0, 31, { islast=0, pat="", smartcase=1, sub=1 },
  209. 3, 0, 3, { "" },
  210. 10, 1436711451, 40, { file="/home/zyx/.nvim/shada/main.shada" },
  211. 1, 1436711454, 78, {
  212. encoding="utf-8",
  213. max_kbyte=10,
  214. pid=19269,
  215. version="NVIM 0.0.0-alpha+201507121634"
  216. },
  217. 8, 1436711451, 40, { file="/home/zyx/.nvim/shada/main.shada" },
  218. 8, 1436711391, 8, { file="" },
  219. 4, 1436700940, 30, { 0, "call mkdir('/tmp/tty/tty')" },
  220. 4, 1436701355, 35, { 0, "call mkdir('/tmp/tty/tty', 'p')" },
  221. 4, 1436701368, 24, { 0, "call mkdir('/', 'p')" },
  222. 4, 1436701375, 26, { 0, "call mkdir('/tty/tty')" },
  223. 4, 1436701383, 30, { 0, "call mkdir('/tty/tty/tty')" },
  224. 4, 1436701407, 35, { 0, "call mkdir('/usr/tty/tty', 'p')" },
  225. 4, 1436701666, 35, { 0, "call mkdir('/tty/tty/tty', 'p')" },
  226. 4, 1436708101, 25, { 0, "echo msgpackdump([1])" },
  227. 4, 1436708966, 6, { 0, "cq" },
  228. 4, 1436709606, 25, { 0, "echo msgpackdump([5])" },
  229. 4, 1436709610, 26, { 0, "echo msgpackdump([10])" },
  230. 4, 1436709615, 31, { 0, "echo msgpackdump([5, 5, 5])" },
  231. 4, 1436709618, 35, { 0, "echo msgpackdump([5, 5, 5, 10])" },
  232. 4, 1436709634, 57, {
  233. 0,
  234. "echo msgpackdump([5, 5, 5, 10, [10, 20, {\"abc\": 1}]])"
  235. },
  236. 4, 1436709651, 67, {
  237. 0,
  238. "echo msgpackdump([5, 5, 5, 10, [10, 20, {\"abc\": 1, \"def\": 0}]])"
  239. },
  240. 4, 1436709660, 70, {
  241. 0,
  242. "echo msgpackdump([5, 5, 5, 10, [10, 20, {\"abc\": 1, \"def\": 0}], 0])"
  243. },
  244. 4, 1436710095, 29, { 0, "echo msgpackparse([\"\\n\"])" },
  245. 4, 1436710100, 28, { 0, "echo msgpackparse([\"j\"])" },
  246. 4, 1436710109, 31, { 0, "echo msgpackparse([\"\", \"\"])" },
  247. 4, 1436710424, 33, { 0, "echo msgpackparse([\"\", \"\\n\"])" },
  248. 4, 1436710428, 32, { 0, "echo msgpackparse([\"\", \"j\"])" },
  249. 4, 1436711142, 14, { 0, "echo mpack" },
  250. 4, 1436711196, 45, { 0, "let lengths = map(mpack[:], 'len(v:val)')" },
  251. 4, 1436711206, 16, { 0, "echo lengths" },
  252. 4, 1436711244, 92, {
  253. 0,
  254. ("let sum = len(lengths) - 1 | call map(copy(lengths), "
  255. .. "'extend(g:, {\"sum\": sum + v:val})')")
  256. },
  257. 4, 1436711245, 12, { 0, "echo sum" },
  258. 4, 1436711398, 10, { 0, "echo s" },
  259. 4, 1436711404, 41, { 0, "let mpack = readfile('/tmp/foo', 'b')" },
  260. 4, 1436711408, 41, { 0, "let shada_objects=msgpackparse(mpack)" },
  261. 4, 1436711415, 22, { 0, "echo shada_objects" },
  262. 4, 1436711451, 30, { 0, "e ~/.nvim/shada/main.shada" },
  263. 4, 1436711454, 6, { 0, "qa" },
  264. 4, 1436711442, 9, { 1, "test", 47 },
  265. 4, 1436711443, 15, { 1, "aontsuesan", 47 },
  266. 2, 1436711443, 38, { hlsearch=1, pat="aontsuesan", smartcase=1 },
  267. 2, 0, 31, { islast=0, pat="", smartcase=1, sub=1 },
  268. 3, 0, 3, { "" },
  269. 10, 1436711451, 40, { file="/home/zyx/.nvim/shada/main.shada" },
  270. 1, 1436711454, 78, {
  271. encoding="utf-8",
  272. max_kbyte=10,
  273. pid=19269,
  274. version="NVIM 0.0.0-alpha+201507121634"
  275. },
  276. 8, 1436711451, 40, { file="/home/zyx/.nvim/shada/main.shada" },
  277. 8, 1436711391, 8, { file="" },
  278. 4, 1436700940, 30, { 0, "call mkdir('/tmp/tty/tty')" },
  279. 4, 1436701355, 35, { 0, "call mkdir('/tmp/tty/tty', 'p')" },
  280. 4, 1436701368, 24, { 0, "call mkdir('/', 'p')" },
  281. 4, 1436701375, 26, { 0, "call mkdir('/tty/tty')" },
  282. 4, 1436701383, 30, { 0, "call mkdir('/tty/tty/tty')" },
  283. 4, 1436701407, 35, { 0, "call mkdir('/usr/tty/tty', 'p')" },
  284. 4, 1436701666, 35, { 0, "call mkdir('/tty/tty/tty', 'p')" },
  285. 4, 1436708101, 25, { 0, "echo msgpackdump([1])" },
  286. 4, 1436708966, 6, { 0, "cq" },
  287. 4, 1436709606, 25, { 0, "echo msgpackdump([5])" },
  288. 4, 1436709610, 26, { 0, "echo msgpackdump([10])" },
  289. 4, 1436709615, 31, { 0, "echo msgpackdump([5, 5, 5])" },
  290. 4, 1436709618, 35, { 0, "echo msgpackdump([5, 5, 5, 10])" },
  291. 4, 1436709634, 57, {
  292. 0,
  293. "echo msgpackdump([5, 5, 5, 10, [10, 20, {\"abc\": 1}]])"
  294. },
  295. 4, 1436709651, 67, {
  296. 0,
  297. "echo msgpackdump([5, 5, 5, 10, [10, 20, {\"abc\": 1, \"def\": 0}]])"
  298. },
  299. 4, 1436709660, 70, {
  300. 0,
  301. "echo msgpackdump([5, 5, 5, 10, [10, 20, {\"abc\": 1, \"def\": 0}], 0])"
  302. },
  303. 4, 1436710095, 29, { 0, "echo msgpackparse([\"\\n\"])" },
  304. 4, 1436710100, 28, { 0, "echo msgpackparse([\"j\"])" },
  305. 4, 1436710109, 31, { 0, "echo msgpackparse([\"\", \"\"])" },
  306. 4, 1436710424, 33, { 0, "echo msgpackparse([\"\", \"\\n\"])" },
  307. 4, 1436710428, 32, { 0, "echo msgpackparse([\"\", \"j\"])" },
  308. 4, 1436711142, 14, { 0, "echo mpack" },
  309. 4, 1436711196, 45, { 0, "let lengths = map(mpack[:], 'len(v:val)')" },
  310. 4, 1436711206, 16, { 0, "echo lengths" },
  311. 4, 1436711244, 92, {
  312. 0,
  313. ("let sum = len(lengths) - 1 | call map(copy(lengths), "
  314. .. "'extend(g:, {\"sum\": sum + v:val})')")
  315. },
  316. 4, 1436711245, 12, { 0, "echo sum" },
  317. 4, 1436711398, 10, { 0, "echo s" },
  318. 4, 1436711404, 41, { 0, "let mpack = readfile('/tmp/foo', 'b')" },
  319. 4, 1436711408, 41, { 0, "let shada_objects=msgpackparse(mpack)" },
  320. 4, 1436711415, 22, { 0, "echo shada_objects" },
  321. 4, 1436711451, 30, { 0, "e ~/.nvim/shada/main.shada" },
  322. 4, 1436711454, 6, { 0, "qa" },
  323. 4, 1436711442, 9, { 1, "test", 47 },
  324. 4, 1436711443, 15, { 1, "aontsuesan", 47 },
  325. 2, 1436711443, 38, { hlsearch=1, pat="aontsuesan", smartcase=1 },
  326. 2, 0, 31, { islast=0, pat="", smartcase=1, sub=1 },
  327. 3, 0, 3, { "" },
  328. 10, 1436711451, 40, { file="/home/zyx/.nvim/shada/main.shada" }
  329. }
  330. obj_test('are able to dump and restore rather big object', big_obj)
  331. obj_test('are able to dump and restore floating-point value', { 0.125 })
  332. it('can restore and dump UINT64_MAX', function()
  333. command('let dumped = ["\\xCF" . repeat("\\xFF", 8)]')
  334. command('let parsed = msgpackparse(dumped)')
  335. command('let dumped2 = msgpackdump(parsed)')
  336. eq(1, eval('type(parsed[0]) == type(0) ' .. '|| parsed[0]._TYPE is v:msgpack_types.integer'))
  337. if eval('type(parsed[0]) == type(0)') == 1 then
  338. command('call assert_equal(0xFFFFFFFFFFFFFFFF, parsed[0])')
  339. eq({}, eval('v:errors'))
  340. else
  341. eq({ _TYPE = {}, _VAL = { 1, 3, 0x7FFFFFFF, 0x7FFFFFFF } }, eval('parsed[0]'))
  342. end
  343. eq(1, eval('dumped ==# dumped2'))
  344. end)
  345. it('can restore and dump INT64_MIN', function()
  346. command('let dumped = ["\\xD3\\x80" . repeat("\\n", 7)]')
  347. command('let parsed = msgpackparse(dumped)')
  348. command('let dumped2 = msgpackdump(parsed)')
  349. eq(1, eval('type(parsed[0]) == type(0) ' .. '|| parsed[0]._TYPE is v:msgpack_types.integer'))
  350. if eval('type(parsed[0]) == type(0)') == 1 then
  351. command('call assert_equal(-0x7fffffffffffffff - 1, parsed[0])')
  352. eq({}, eval('v:errors'))
  353. else
  354. eq({ _TYPE = {}, _VAL = { -1, 2, 0, 0 } }, eval('parsed[0]'))
  355. end
  356. eq(1, eval('dumped ==# dumped2'))
  357. end)
  358. it('can restore and dump BIN string with zero byte', function()
  359. command('let dumped = ["\\xC4\\x01\\n"]')
  360. command('let parsed = msgpackparse(dumped)')
  361. command('let dumped2 = msgpackdump(parsed)')
  362. eq({ '\000' }, eval('parsed'))
  363. eq(1, eval('dumped ==# dumped2'))
  364. end)
  365. it('can restore and dump STR string contents with zero byte', function()
  366. command('let dumped = ["\\xA1\\n"]')
  367. command('let parsed = msgpackparse(dumped)')
  368. command('let dumped2 = msgpackdump(parsed)')
  369. eq({ '\000' }, eval('parsed'))
  370. eq(eval('v:t_blob'), eval('type(parsed[0])'))
  371. -- type is not preserved: prefer BIN for binary contents
  372. eq(0, eval('dumped ==# dumped2'))
  373. end)
  374. it('can restore and dump BIN string with NL', function()
  375. command('let dumped = ["\\xC4\\x01", ""]')
  376. command('let parsed = msgpackparse(dumped)')
  377. command('let dumped2 = msgpackdump(parsed)')
  378. eq({ '\n' }, eval('parsed'))
  379. eq(1, eval('dumped ==# dumped2'))
  380. end)
  381. it('dump and restore special mapping with floating-point value', function()
  382. command('let todump = {"_TYPE": v:msgpack_types.float, "_VAL": 0.125}')
  383. eq({ 0.125 }, eval('msgpackparse(msgpackdump([todump]))'))
  384. end)
  385. end)
  386. local blobstr = function(list)
  387. local l = {}
  388. for i, v in ipairs(list) do
  389. l[i] = v:gsub('\n', '\000')
  390. end
  391. return table.concat(l, '\n')
  392. end
  393. -- Test msgpackparse() with a readfile()-style list and a blob argument
  394. local parse_eq = function(expect, list_arg)
  395. local blob_expr = '0z'
  396. .. blobstr(list_arg):gsub('(.)', function(c)
  397. return ('%.2x'):format(c:byte())
  398. end)
  399. eq(expect, fn.msgpackparse(list_arg))
  400. command('let g:parsed = msgpackparse(' .. blob_expr .. ')')
  401. eq(expect, eval('g:parsed'))
  402. end
  403. describe('msgpackparse() function', function()
  404. before_each(clear)
  405. it('restores nil as v:null', function()
  406. parse_eq(eval('[v:null]'), { '\192' })
  407. end)
  408. it('restores boolean false as v:false', function()
  409. parse_eq({ false }, { '\194' })
  410. end)
  411. it('restores boolean true as v:true', function()
  412. parse_eq({ true }, { '\195' })
  413. end)
  414. it('restores FIXSTR as string', function()
  415. parse_eq({ 'ab' }, { '\162ab' })
  416. end)
  417. it('restores BIN 8 as string', function()
  418. parse_eq({ 'ab' }, { '\196\002ab' })
  419. end)
  420. it('restores FIXEXT1 as special dict', function()
  421. parse_eq({ { _TYPE = {}, _VAL = { 0x10, { '', '' } } } }, { '\212\016', '' })
  422. eq(1, eval('g:parsed[0]._TYPE is v:msgpack_types.ext'))
  423. end)
  424. it('restores MAP with BIN key as ordinary dict', function()
  425. parse_eq({ { a = '' } }, { '\129\196\001a\196\n' })
  426. end)
  427. it('restores MAP with duplicate STR keys as special dict', function()
  428. command('let dumped = ["\\x82\\xA1a\\xC4\\n\\xA1a\\xC4\\n"]')
  429. -- FIXME Internal error bug, can't use parse_eq() here
  430. command('silent! let parsed = msgpackparse(dumped)')
  431. eq({
  432. {
  433. _TYPE = {},
  434. _VAL = {
  435. { 'a', '' },
  436. { 'a', '' },
  437. },
  438. },
  439. }, eval('parsed'))
  440. eq(1, eval('g:parsed[0]._TYPE is v:msgpack_types.map'))
  441. eq(eval('v:t_string'), eval('type(g:parsed[0]._VAL[0][0])'))
  442. eq(eval('v:t_string'), eval('type(g:parsed[0]._VAL[1][0])'))
  443. end)
  444. it('restores MAP with MAP key as special dict', function()
  445. parse_eq({ { _TYPE = {}, _VAL = { { {}, '' } } } }, { '\129\128\196\n' })
  446. eq(1, eval('g:parsed[0]._TYPE is v:msgpack_types.map'))
  447. end)
  448. it('msgpackparse(systemlist(...)) does not segfault. #3135', function()
  449. local cmd = "sort(keys(msgpackparse(systemlist('" .. n.nvim_prog .. " --api-info'))[0]))"
  450. eval(cmd)
  451. eval(cmd) -- do it again (try to force segfault)
  452. local api_info = eval(cmd) -- do it again
  453. if is_os('win') then
  454. n.assert_alive()
  455. pending('msgpackparse() has a bug on windows')
  456. return
  457. end
  458. eq({ 'error_types', 'functions', 'types', 'ui_events', 'ui_options', 'version' }, api_info)
  459. end)
  460. it('fails when called with no arguments', function()
  461. eq(
  462. 'Vim(call):E119: Not enough arguments for function: msgpackparse',
  463. exc_exec('call msgpackparse()')
  464. )
  465. end)
  466. it('fails when called with two arguments', function()
  467. eq(
  468. 'Vim(call):E118: Too many arguments for function: msgpackparse',
  469. exc_exec('call msgpackparse(["", ""], 1)')
  470. )
  471. end)
  472. it('fails to parse a string', function()
  473. eq(
  474. 'Vim(call):E899: Argument of msgpackparse() must be a List or Blob',
  475. exc_exec('call msgpackparse("abcdefghijklmnopqrstuvwxyz")')
  476. )
  477. end)
  478. it('fails to parse a number', function()
  479. eq(
  480. 'Vim(call):E899: Argument of msgpackparse() must be a List or Blob',
  481. exc_exec('call msgpackparse(127)')
  482. )
  483. end)
  484. it('fails to parse a dict', function()
  485. eq(
  486. 'Vim(call):E899: Argument of msgpackparse() must be a List or Blob',
  487. exc_exec('call msgpackparse({})')
  488. )
  489. end)
  490. it('fails to parse a funcref', function()
  491. eq(
  492. 'Vim(call):E899: Argument of msgpackparse() must be a List or Blob',
  493. exc_exec('call msgpackparse(function("tr"))')
  494. )
  495. end)
  496. it('fails to parse a partial', function()
  497. command('function T() dict\nendfunction')
  498. eq(
  499. 'Vim(call):E899: Argument of msgpackparse() must be a List or Blob',
  500. exc_exec('call msgpackparse(function("T", [1, 2], {}))')
  501. )
  502. end)
  503. it('fails to parse a float', function()
  504. eq(
  505. 'Vim(call):E899: Argument of msgpackparse() must be a List or Blob',
  506. exc_exec('call msgpackparse(0.0)')
  507. )
  508. end)
  509. it('fails on incomplete msgpack string', function()
  510. local expected = 'Vim(call):E475: Invalid argument: Incomplete msgpack string'
  511. eq(expected, exc_exec([[call msgpackparse(["\xc4"])]]))
  512. eq(expected, exc_exec([[call msgpackparse(["\xca", "\x02\x03"])]]))
  513. eq(expected, exc_exec('call msgpackparse(0zc4)'))
  514. eq(expected, exc_exec('call msgpackparse(0zca0a0203)'))
  515. end)
  516. it('fails when unable to parse msgpack string', function()
  517. local expected = 'Vim(call):E475: Invalid argument: Failed to parse msgpack string'
  518. eq(expected, exc_exec([[call msgpackparse(["\xc1"])]]))
  519. eq(expected, exc_exec('call msgpackparse(0zc1)'))
  520. end)
  521. end)
  522. describe('msgpackdump() function', function()
  523. before_each(clear)
  524. local dump_eq = function(exp_list, arg_expr)
  525. eq(exp_list, eval('msgpackdump(' .. arg_expr .. ')'))
  526. eq(blobstr(exp_list), eval('msgpackdump(' .. arg_expr .. ', "B")'))
  527. end
  528. it('dumps string as BIN 8', function()
  529. dump_eq({ '\196\004Test' }, '["Test"]')
  530. end)
  531. it('dumps blob as BIN 8', function()
  532. dump_eq({ '\196\005Bl\nb!' }, '[0z426c006221]')
  533. end)
  534. it('can dump generic mapping with generic mapping keys and values', function()
  535. command('let todump = {"_TYPE": v:msgpack_types.map, "_VAL": []}')
  536. command('let todumpv1 = {"_TYPE": v:msgpack_types.map, "_VAL": []}')
  537. command('let todumpv2 = {"_TYPE": v:msgpack_types.map, "_VAL": []}')
  538. command('call add(todump._VAL, [todumpv1, todumpv2])')
  539. dump_eq({ '\129\128\128' }, '[todump]')
  540. end)
  541. it('can dump v:true', function()
  542. dump_eq({ '\195' }, '[v:true]')
  543. end)
  544. it('can dump v:false', function()
  545. dump_eq({ '\194' }, '[v:false]')
  546. end)
  547. it('can dump v:null', function()
  548. dump_eq({ '\192' }, '[v:null]')
  549. end)
  550. it('can dump special bool mapping (true)', function()
  551. command('let todump = {"_TYPE": v:msgpack_types.boolean, "_VAL": 1}')
  552. dump_eq({ '\195' }, '[todump]')
  553. end)
  554. it('can dump special bool mapping (false)', function()
  555. command('let todump = {"_TYPE": v:msgpack_types.boolean, "_VAL": 0}')
  556. dump_eq({ '\194' }, '[todump]')
  557. end)
  558. it('can dump special nil mapping', function()
  559. command('let todump = {"_TYPE": v:msgpack_types.nil, "_VAL": 0}')
  560. dump_eq({ '\192' }, '[todump]')
  561. end)
  562. it('can dump special ext mapping', function()
  563. command('let todump = {"_TYPE": v:msgpack_types.ext, "_VAL": [5, ["",""]]}')
  564. dump_eq({ '\212\005', '' }, '[todump]')
  565. end)
  566. it('can dump special array mapping', function()
  567. command('let todump = {"_TYPE": v:msgpack_types.array, "_VAL": [5, [""]]}')
  568. dump_eq({ '\146\005\145\196\n' }, '[todump]')
  569. end)
  570. it('can dump special UINT64_MAX mapping', function()
  571. command('let todump = {"_TYPE": v:msgpack_types.integer}')
  572. command('let todump._VAL = [1, 3, 0x7FFFFFFF, 0x7FFFFFFF]')
  573. dump_eq({ '\207\255\255\255\255\255\255\255\255' }, '[todump]')
  574. end)
  575. it('can dump special INT64_MIN mapping', function()
  576. command('let todump = {"_TYPE": v:msgpack_types.integer}')
  577. command('let todump._VAL = [-1, 2, 0, 0]')
  578. dump_eq({ '\211\128\n\n\n\n\n\n\n' }, '[todump]')
  579. end)
  580. it('fails to dump a function reference', function()
  581. command('let Todump = function("tr")')
  582. eq(
  583. 'Vim(call):E5004: Error while dumping msgpackdump() argument, index 0, itself: attempt to dump function reference',
  584. exc_exec('call msgpackdump([Todump])')
  585. )
  586. end)
  587. it('fails to dump a partial', function()
  588. command('function T() dict\nendfunction')
  589. command('let Todump = function("T", [1, 2], {})')
  590. eq(
  591. 'Vim(call):E5004: Error while dumping msgpackdump() argument, index 0, itself: attempt to dump function reference',
  592. exc_exec('call msgpackdump([Todump])')
  593. )
  594. end)
  595. it('fails to dump a function reference in a list', function()
  596. command('let todump = [function("tr")]')
  597. eq(
  598. 'Vim(call):E5004: Error while dumping msgpackdump() argument, index 0, index 0: attempt to dump function reference',
  599. exc_exec('call msgpackdump([todump])')
  600. )
  601. end)
  602. it('fails to dump a recursive list', function()
  603. command('let todump = [[[]]]')
  604. command('call add(todump[0][0], todump)')
  605. eq(
  606. 'Vim(call):E5005: Unable to dump msgpackdump() argument, index 0: container references itself in index 0, index 0, index 0',
  607. exc_exec('call msgpackdump([todump])')
  608. )
  609. end)
  610. it('fails to dump a recursive dict', function()
  611. command('let todump = {"d": {"d": {}}}')
  612. command('call extend(todump.d.d, {"d": todump})')
  613. eq(
  614. "Vim(call):E5005: Unable to dump msgpackdump() argument, index 0: container references itself in key 'd', key 'd', key 'd'",
  615. exc_exec('call msgpackdump([todump])')
  616. )
  617. end)
  618. it('can dump dict with two same dicts inside', function()
  619. command('let inter = {}')
  620. command('let todump = {"a": inter, "b": inter}')
  621. dump_eq({ '\130\161a\128\161b\128' }, '[todump]')
  622. end)
  623. it('can dump list with two same lists inside', function()
  624. command('let inter = []')
  625. command('let todump = [inter, inter]')
  626. dump_eq({ '\146\144\144' }, '[todump]')
  627. end)
  628. it('fails to dump a recursive list in a special dict', function()
  629. command('let todump = {"_TYPE": v:msgpack_types.array, "_VAL": []}')
  630. command('call add(todump._VAL, todump)')
  631. eq(
  632. 'Vim(call):E5005: Unable to dump msgpackdump() argument, index 0: container references itself in index 0',
  633. exc_exec('call msgpackdump([todump])')
  634. )
  635. end)
  636. it('fails to dump a recursive (key) map in a special dict', function()
  637. command('let todump = {"_TYPE": v:msgpack_types.map, "_VAL": []}')
  638. command('call add(todump._VAL, [todump, 0])')
  639. eq(
  640. 'Vim(call):E5005: Unable to dump msgpackdump() argument, index 0: container references itself in index 0',
  641. exc_exec('call msgpackdump([todump])')
  642. )
  643. end)
  644. it('fails to dump a recursive (val) map in a special dict', function()
  645. command('let todump = {"_TYPE": v:msgpack_types.map, "_VAL": []}')
  646. command('call add(todump._VAL, [0, todump])')
  647. eq(
  648. 'Vim(call):E5005: Unable to dump msgpackdump() argument, index 0: container references itself in key 0 at index 0 from special map',
  649. exc_exec('call msgpackdump([todump])')
  650. )
  651. end)
  652. it('fails to dump a recursive (key) map in a special dict, _VAL reference', function()
  653. command('let todump = {"_TYPE": v:msgpack_types.map, "_VAL": [[[], []]]}')
  654. command('call add(todump._VAL[0][0], todump._VAL)')
  655. eq(
  656. 'Vim(call):E5005: Unable to dump msgpackdump() argument, index 0: container references itself in key [[[[...@0], []]]] at index 0 from special map, index 0',
  657. exc_exec('call msgpackdump([todump])')
  658. )
  659. end)
  660. it('fails to dump a recursive (val) map in a special dict, _VAL reference', function()
  661. command('let todump = {"_TYPE": v:msgpack_types.map, "_VAL": [[[], []]]}')
  662. command('call add(todump._VAL[0][1], todump._VAL)')
  663. eq(
  664. 'Vim(call):E5005: Unable to dump msgpackdump() argument, index 0: container references itself in key [] at index 0 from special map, index 0',
  665. exc_exec('call msgpackdump([todump])')
  666. )
  667. end)
  668. it('fails to dump a recursive (val) special list in a special dict', function()
  669. command('let todump = {"_TYPE": v:msgpack_types.array, "_VAL": []}')
  670. command('call add(todump._VAL, [0, todump._VAL])')
  671. eq(
  672. 'Vim(call):E5005: Unable to dump msgpackdump() argument, index 0: container references itself in index 0, index 1',
  673. exc_exec('call msgpackdump([todump])')
  674. )
  675. end)
  676. it('fails when called with no arguments', function()
  677. eq(
  678. 'Vim(call):E119: Not enough arguments for function: msgpackdump',
  679. exc_exec('call msgpackdump()')
  680. )
  681. end)
  682. it('fails when called with three arguments', function()
  683. eq(
  684. 'Vim(call):E118: Too many arguments for function: msgpackdump',
  685. exc_exec('call msgpackdump(["", ""], 1, 2)')
  686. )
  687. end)
  688. it('fails to dump a string', function()
  689. eq(
  690. 'Vim(call):E686: Argument of msgpackdump() must be a List',
  691. exc_exec('call msgpackdump("abcdefghijklmnopqrstuvwxyz")')
  692. )
  693. end)
  694. it('fails to dump a number', function()
  695. eq(
  696. 'Vim(call):E686: Argument of msgpackdump() must be a List',
  697. exc_exec('call msgpackdump(127)')
  698. )
  699. end)
  700. it('fails to dump a dict', function()
  701. eq('Vim(call):E686: Argument of msgpackdump() must be a List', exc_exec('call msgpackdump({})'))
  702. end)
  703. it('fails to dump a funcref', function()
  704. eq(
  705. 'Vim(call):E686: Argument of msgpackdump() must be a List',
  706. exc_exec('call msgpackdump(function("tr"))')
  707. )
  708. end)
  709. it('fails to dump a partial', function()
  710. command('function T() dict\nendfunction')
  711. eq(
  712. 'Vim(call):E686: Argument of msgpackdump() must be a List',
  713. exc_exec('call msgpackdump(function("T", [1, 2], {}))')
  714. )
  715. end)
  716. it('fails to dump a float', function()
  717. eq(
  718. 'Vim(call):E686: Argument of msgpackdump() must be a List',
  719. exc_exec('call msgpackdump(0.0)')
  720. )
  721. end)
  722. it('fails to dump special value', function()
  723. for _, val in ipairs({ 'v:true', 'v:false', 'v:null' }) do
  724. eq(
  725. 'Vim(call):E686: Argument of msgpackdump() must be a List',
  726. exc_exec('call msgpackdump(' .. val .. ')')
  727. )
  728. end
  729. end)
  730. it('can dump NULL string', function()
  731. dump_eq({ '\196\n' }, '[$XXX_UNEXISTENT_VAR_XXX]')
  732. dump_eq({ '\196\n' }, '[v:_null_blob]')
  733. dump_eq({ '\160' }, '[{"_TYPE": v:msgpack_types.string, "_VAL": [$XXX_UNEXISTENT_VAR_XXX]}]')
  734. end)
  735. it('can dump NULL blob', function()
  736. eq({ '\196\n' }, eval('msgpackdump([v:_null_blob])'))
  737. end)
  738. it('can dump NULL list', function()
  739. eq({ '\144' }, eval('msgpackdump([v:_null_list])'))
  740. end)
  741. it('can dump NULL dict', function()
  742. eq({ '\128' }, eval('msgpackdump([v:_null_dict])'))
  743. end)
  744. end)