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