neovim

Neovim text editor
git clone https://git.dasho.dev/neovim.git
Log | Files | Refs | README

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)