msgpack_spec.lua (29696B)
1 local t = require('test.testutil') 2 local n = require('test.functional.testnvim')() 3 4 local clear = n.clear 5 local api = n.api 6 local eq = t.eq 7 local nvim_eval = n.eval 8 local nvim_command = n.command 9 local exc_exec = n.exc_exec 10 local ok = t.ok 11 local NIL = vim.NIL 12 13 describe('autoload/msgpack.vim', function() 14 setup(function() 15 clear { args = { '-u', 'NORC' } } 16 end) 17 18 local sp = function(typ, val) 19 return ('{"_TYPE": v:msgpack_types.%s, "_VAL": %s}'):format(typ, val) 20 end 21 local mapsp = function(...) 22 local val = '' 23 for i = 1, (select('#', ...) / 2) do 24 val = ('%s[%s,%s],'):format(val, select(i * 2 - 1, ...), select(i * 2, ...)) 25 end 26 return sp('map', '[' .. val .. ']') 27 end 28 29 local nan = -(1.0 / 0.0 - 1.0 / 0.0) 30 local inf = 1.0 / 0.0 31 local minus_inf = -(1.0 / 0.0) 32 33 describe('function msgpack#equal', function() 34 local msgpack_eq = function(expected, a, b) 35 eq(expected, nvim_eval(('msgpack#equal(%s, %s)'):format(a, b))) 36 if a ~= b then 37 eq(expected, nvim_eval(('msgpack#equal(%s, %s)'):format(b, a))) 38 end 39 end 40 it('compares raw integers correctly', function() 41 msgpack_eq(1, '1', '1') 42 msgpack_eq(0, '1', '0') 43 end) 44 it('compares integer specials correctly', function() 45 msgpack_eq(1, sp('integer', '[-1, 1, 0, 0]'), sp('integer', '[-1, 1, 0, 0]')) 46 msgpack_eq(0, sp('integer', '[-1, 1, 0, 0]'), sp('integer', '[ 1, 1, 0, 0]')) 47 end) 48 it('compares integer specials with raw integer correctly', function() 49 msgpack_eq(1, sp('integer', '[-1, 0, 0, 1]'), '-1') 50 msgpack_eq(0, sp('integer', '[-1, 0, 0, 1]'), '1') 51 msgpack_eq(0, sp('integer', '[ 1, 0, 0, 1]'), '-1') 52 msgpack_eq(1, sp('integer', '[ 1, 0, 0, 1]'), '1') 53 end) 54 it('compares integer with float correctly', function() 55 msgpack_eq(0, '0', '0.0') 56 end) 57 it('compares raw binaries correctly', function() 58 msgpack_eq(1, '"abc\\ndef"', '"abc\\ndef"') 59 msgpack_eq(0, '"abc\\ndef"', '"abc\\nghi"') 60 end) 61 it('compares string specials correctly', function() 62 msgpack_eq(1, sp('string', '["abc\\n", "def"]'), sp('string', '["abc\\n", "def"]')) 63 msgpack_eq(0, sp('string', '["abc", "def"]'), sp('string', '["abc\\n", "def"]')) 64 msgpack_eq(1, sp('string', '["abc", "def"]'), '"abc\\ndef"') 65 msgpack_eq(1, '"abc\\ndef"', sp('string', '["abc", "def"]')) 66 end) 67 it('compares ext specials correctly', function() 68 msgpack_eq(1, sp('ext', '[1, ["", "ac"]]'), sp('ext', '[1, ["", "ac"]]')) 69 msgpack_eq(0, sp('ext', '[2, ["", "ac"]]'), sp('ext', '[1, ["", "ac"]]')) 70 msgpack_eq(0, sp('ext', '[1, ["", "ac"]]'), sp('ext', '[1, ["", "abc"]]')) 71 end) 72 it('compares raw maps correctly', function() 73 msgpack_eq(1, '{"a": 1, "b": 2}', '{"b": 2, "a": 1}') 74 msgpack_eq(1, '{}', '{}') 75 msgpack_eq(0, '{}', '{"a": 1}') 76 msgpack_eq(0, '{"a": 2}', '{"a": 1}') 77 msgpack_eq(0, '{"a": 1}', '{"b": 1}') 78 msgpack_eq(0, '{"a": 1}', '{"a": 1, "b": 1}') 79 msgpack_eq(0, '{"a": 1, "b": 1}', '{"b": 1}') 80 end) 81 it('compares map specials correctly', function() 82 msgpack_eq(1, mapsp(), mapsp()) 83 msgpack_eq( 84 1, 85 mapsp(mapsp('1', '1'), mapsp('1', '1')), 86 mapsp(mapsp('1', '1'), mapsp('1', '1')) 87 ) 88 msgpack_eq(0, mapsp(), mapsp('1', '1')) 89 msgpack_eq( 90 0, 91 mapsp(mapsp('1', '1'), mapsp('1', '1')), 92 mapsp(sp('string', '[""]'), mapsp('1', '1')) 93 ) 94 msgpack_eq( 95 0, 96 mapsp(mapsp('1', '1'), mapsp('1', '1')), 97 mapsp(mapsp('2', '1'), mapsp('1', '1')) 98 ) 99 msgpack_eq( 100 0, 101 mapsp(mapsp('1', '1'), mapsp('1', '1')), 102 mapsp(mapsp('1', '2'), mapsp('1', '1')) 103 ) 104 msgpack_eq( 105 0, 106 mapsp(mapsp('1', '1'), mapsp('1', '1')), 107 mapsp(mapsp('1', '1'), mapsp('2', '1')) 108 ) 109 msgpack_eq( 110 0, 111 mapsp(mapsp('1', '1'), mapsp('1', '1')), 112 mapsp(mapsp('1', '1'), mapsp('1', '2')) 113 ) 114 msgpack_eq( 115 1, 116 mapsp(mapsp('2', '1'), mapsp('1', '1'), mapsp('1', '1'), mapsp('1', '1')), 117 mapsp(mapsp('1', '1'), mapsp('1', '1'), mapsp('2', '1'), mapsp('1', '1')) 118 ) 119 end) 120 it('compares map specials with raw maps correctly', function() 121 msgpack_eq(1, mapsp(), '{}') 122 msgpack_eq(1, mapsp(sp('string', '["1"]'), '1'), '{"1": 1}') 123 msgpack_eq(1, mapsp(sp('string', '["1"]'), sp('integer', '[1, 0, 0, 1]')), '{"1": 1}') 124 msgpack_eq(0, mapsp(sp('integer', '[1, 0, 0, 1]'), sp('string', '["1"]')), '{1: "1"}') 125 msgpack_eq(1, mapsp('"1"', sp('integer', '[1, 0, 0, 1]')), '{"1": 1}') 126 msgpack_eq(0, mapsp(sp('string', '["1"]'), '1', sp('string', '["2"]'), '2'), '{"1": 1}') 127 msgpack_eq(0, mapsp(sp('string', '["1"]'), '1'), '{"1": 1, "2": 2}') 128 end) 129 it('compares raw arrays correctly', function() 130 msgpack_eq(1, '[]', '[]') 131 msgpack_eq(0, '[]', '[1]') 132 msgpack_eq(1, '[1]', '[1]') 133 msgpack_eq(1, '[[[1]]]', '[[[1]]]') 134 msgpack_eq(0, '[[[2]]]', '[[[1]]]') 135 end) 136 it('compares array specials correctly', function() 137 msgpack_eq(1, sp('array', '[]'), sp('array', '[]')) 138 msgpack_eq(0, sp('array', '[]'), sp('array', '[1]')) 139 msgpack_eq(1, sp('array', '[1]'), sp('array', '[1]')) 140 msgpack_eq(1, sp('array', '[[[1]]]'), sp('array', '[[[1]]]')) 141 msgpack_eq(0, sp('array', '[[[1]]]'), sp('array', '[[[2]]]')) 142 end) 143 it('compares array specials with raw arrays correctly', function() 144 msgpack_eq(1, sp('array', '[]'), '[]') 145 msgpack_eq(0, sp('array', '[]'), '[1]') 146 msgpack_eq(1, sp('array', '[1]'), '[1]') 147 msgpack_eq(1, sp('array', '[[[1]]]'), '[[[1]]]') 148 msgpack_eq(0, sp('array', '[[[1]]]'), '[[[2]]]') 149 end) 150 it('compares raw floats correctly', function() 151 msgpack_eq(1, '0.0', '0.0') 152 msgpack_eq(1, '(1.0/0.0-1.0/0.0)', '(1.0/0.0-1.0/0.0)') 153 -- both (1.0/0.0-1.0/0.0) and -(1.0/0.0-1.0/0.0) now return 154 -- str2float('nan'). ref: @18d1ba3422d 155 msgpack_eq(1, '(1.0/0.0-1.0/0.0)', '-(1.0/0.0-1.0/0.0)') 156 msgpack_eq(1, '-(1.0/0.0-1.0/0.0)', '-(1.0/0.0-1.0/0.0)') 157 msgpack_eq(1, '1.0/0.0', '1.0/0.0') 158 msgpack_eq(1, '-(1.0/0.0)', '-(1.0/0.0)') 159 msgpack_eq(1, '0.0', '0.0') 160 msgpack_eq(0, '0.0', '1.0') 161 msgpack_eq(0, '0.0', '(1.0/0.0-1.0/0.0)') 162 msgpack_eq(0, '0.0', '1.0/0.0') 163 msgpack_eq(0, '0.0', '-(1.0/0.0)') 164 msgpack_eq(0, '1.0/0.0', '-(1.0/0.0)') 165 msgpack_eq(0, '(1.0/0.0-1.0/0.0)', '-(1.0/0.0)') 166 msgpack_eq(0, '(1.0/0.0-1.0/0.0)', '1.0/0.0') 167 end) 168 it('compares float specials with raw floats correctly', function() 169 msgpack_eq(1, sp('float', '0.0'), '0.0') 170 msgpack_eq(1, sp('float', '(1.0/0.0-1.0/0.0)'), '(1.0/0.0-1.0/0.0)') 171 msgpack_eq(1, sp('float', '(1.0/0.0-1.0/0.0)'), '-(1.0/0.0-1.0/0.0)') 172 msgpack_eq(1, sp('float', '-(1.0/0.0-1.0/0.0)'), '(1.0/0.0-1.0/0.0)') 173 msgpack_eq(1, sp('float', '-(1.0/0.0-1.0/0.0)'), '-(1.0/0.0-1.0/0.0)') 174 msgpack_eq(1, sp('float', '1.0/0.0'), '1.0/0.0') 175 msgpack_eq(1, sp('float', '-(1.0/0.0)'), '-(1.0/0.0)') 176 msgpack_eq(1, sp('float', '0.0'), '0.0') 177 msgpack_eq(0, sp('float', '0.0'), '1.0') 178 msgpack_eq(0, sp('float', '0.0'), '(1.0/0.0-1.0/0.0)') 179 msgpack_eq(0, sp('float', '0.0'), '1.0/0.0') 180 msgpack_eq(0, sp('float', '0.0'), '-(1.0/0.0)') 181 msgpack_eq(0, sp('float', '1.0/0.0'), '-(1.0/0.0)') 182 msgpack_eq(0, sp('float', '(1.0/0.0-1.0/0.0)'), '-(1.0/0.0)') 183 msgpack_eq(0, sp('float', '(1.0/0.0-1.0/0.0)'), '1.0/0.0') 184 end) 185 it('compares float specials correctly', function() 186 msgpack_eq(1, sp('float', '0.0'), sp('float', '0.0')) 187 msgpack_eq(1, sp('float', '(1.0/0.0-1.0/0.0)'), sp('float', '(1.0/0.0-1.0/0.0)')) 188 msgpack_eq(1, sp('float', '1.0/0.0'), sp('float', '1.0/0.0')) 189 msgpack_eq(1, sp('float', '-(1.0/0.0)'), sp('float', '-(1.0/0.0)')) 190 msgpack_eq(1, sp('float', '0.0'), sp('float', '0.0')) 191 msgpack_eq(0, sp('float', '0.0'), sp('float', '1.0')) 192 msgpack_eq(0, sp('float', '0.0'), sp('float', '(1.0/0.0-1.0/0.0)')) 193 msgpack_eq(0, sp('float', '0.0'), sp('float', '1.0/0.0')) 194 msgpack_eq(0, sp('float', '0.0'), sp('float', '-(1.0/0.0)')) 195 msgpack_eq(0, sp('float', '1.0/0.0'), sp('float', '-(1.0/0.0)')) 196 msgpack_eq(0, sp('float', '(1.0/0.0-1.0/0.0)'), sp('float', '-(1.0/0.0)')) 197 msgpack_eq(1, sp('float', '(1.0/0.0-1.0/0.0)'), sp('float', '-(1.0/0.0-1.0/0.0)')) 198 msgpack_eq(1, sp('float', '-(1.0/0.0-1.0/0.0)'), sp('float', '-(1.0/0.0-1.0/0.0)')) 199 msgpack_eq(0, sp('float', '(1.0/0.0-1.0/0.0)'), sp('float', '1.0/0.0')) 200 end) 201 it('compares boolean specials correctly', function() 202 msgpack_eq(1, sp('boolean', '1'), sp('boolean', '1')) 203 msgpack_eq(0, sp('boolean', '1'), sp('boolean', '0')) 204 end) 205 it('compares nil specials correctly', function() 206 msgpack_eq(1, sp('nil', '1'), sp('nil', '0')) 207 end) 208 it('compares nil, boolean and integer values with each other correctly', function() 209 msgpack_eq(0, sp('boolean', '1'), '1') 210 msgpack_eq(0, sp('boolean', '1'), sp('nil', '0')) 211 msgpack_eq(0, sp('boolean', '1'), sp('nil', '1')) 212 msgpack_eq(0, sp('boolean', '0'), sp('nil', '0')) 213 msgpack_eq(0, sp('boolean', '0'), '0') 214 msgpack_eq(0, sp('boolean', '0'), sp('integer', '[1, 0, 0, 0]')) 215 msgpack_eq(0, sp('boolean', '0'), sp('integer', '[1, 0, 0, 1]')) 216 msgpack_eq(0, sp('boolean', '1'), sp('integer', '[1, 0, 0, 1]')) 217 msgpack_eq(0, sp('nil', '0'), sp('integer', '[1, 0, 0, 0]')) 218 msgpack_eq(0, sp('nil', '0'), '0') 219 end) 220 end) 221 222 describe('function msgpack#is_int', function() 223 it('works', function() 224 eq(1, nvim_eval('msgpack#is_int(1)')) 225 eq(1, nvim_eval('msgpack#is_int(-1)')) 226 eq(1, nvim_eval(('msgpack#is_int(%s)'):format(sp('integer', '[1, 0, 0, 1]')))) 227 eq(1, nvim_eval(('msgpack#is_int(%s)'):format(sp('integer', '[-1, 0, 0, 1]')))) 228 eq(0, nvim_eval(('msgpack#is_int(%s)'):format(sp('float', '0.0')))) 229 eq(0, nvim_eval(('msgpack#is_int(%s)'):format(sp('boolean', '0')))) 230 eq(0, nvim_eval(('msgpack#is_int(%s)'):format(sp('nil', '0')))) 231 eq(0, nvim_eval('msgpack#is_int("")')) 232 end) 233 end) 234 235 describe('function msgpack#is_uint', function() 236 it('works', function() 237 eq(1, nvim_eval('msgpack#is_uint(1)')) 238 eq(0, nvim_eval('msgpack#is_uint(-1)')) 239 eq(1, nvim_eval(('msgpack#is_uint(%s)'):format(sp('integer', '[1, 0, 0, 1]')))) 240 eq(0, nvim_eval(('msgpack#is_uint(%s)'):format(sp('integer', '[-1, 0, 0, 1]')))) 241 eq(0, nvim_eval(('msgpack#is_uint(%s)'):format(sp('float', '0.0')))) 242 eq(0, nvim_eval(('msgpack#is_uint(%s)'):format(sp('boolean', '0')))) 243 eq(0, nvim_eval(('msgpack#is_uint(%s)'):format(sp('nil', '0')))) 244 eq(0, nvim_eval('msgpack#is_uint("")')) 245 end) 246 end) 247 248 describe('function msgpack#strftime', function() 249 it('works', function() 250 local epoch = os.date('%Y-%m-%dT%H:%M:%S', 0) 251 eq(epoch, nvim_eval('msgpack#strftime("%Y-%m-%dT%H:%M:%S", 0)')) 252 eq( 253 epoch, 254 nvim_eval( 255 ('msgpack#strftime("%%Y-%%m-%%dT%%H:%%M:%%S", %s)'):format(sp('integer', '[1, 0, 0, 0]')) 256 ) 257 ) 258 end) 259 end) 260 261 describe('function msgpack#strptime', function() 262 it('works', function() 263 for _, v in ipairs({ 0, 10, 100000, 204, 1000000000 }) do 264 local time = os.date('%Y-%m-%dT%H:%M:%S', v) 265 eq(v, nvim_eval('msgpack#strptime("%Y-%m-%dT%H:%M:%S", ' .. '"' .. time .. '")')) 266 end 267 end) 268 end) 269 270 describe('function msgpack#type', function() 271 local type_eq = function(expected, val) 272 eq(expected, nvim_eval(('msgpack#type(%s)'):format(val))) 273 end 274 275 it('works for special dictionaries', function() 276 type_eq('string', sp('string', '[""]')) 277 type_eq('ext', sp('ext', '[1, [""]]')) 278 type_eq('array', sp('array', '[]')) 279 type_eq('map', sp('map', '[]')) 280 type_eq('integer', sp('integer', '[1, 0, 0, 0]')) 281 type_eq('float', sp('float', '0.0')) 282 type_eq('boolean', sp('boolean', '0')) 283 type_eq('nil', sp('nil', '0')) 284 end) 285 286 it('works for regular values', function() 287 type_eq('string', '""') 288 type_eq('array', '[]') 289 type_eq('map', '{}') 290 type_eq('integer', '1') 291 type_eq('float', '0.0') 292 type_eq('float', '(1.0/0.0)') 293 type_eq('float', '-(1.0/0.0)') 294 type_eq('float', '(1.0/0.0-1.0/0.0)') 295 end) 296 end) 297 298 describe('function msgpack#special_type', function() 299 local sp_type_eq = function(expected, val) 300 eq(expected, nvim_eval(('msgpack#special_type(%s)'):format(val))) 301 end 302 303 it('works for special dictionaries', function() 304 sp_type_eq('string', sp('string', '[""]')) 305 sp_type_eq('ext', sp('ext', '[1, [""]]')) 306 sp_type_eq('array', sp('array', '[]')) 307 sp_type_eq('map', sp('map', '[]')) 308 sp_type_eq('integer', sp('integer', '[1, 0, 0, 0]')) 309 sp_type_eq('float', sp('float', '0.0')) 310 sp_type_eq('boolean', sp('boolean', '0')) 311 sp_type_eq('nil', sp('nil', '0')) 312 end) 313 314 it('works for regular values', function() 315 sp_type_eq(0, '""') 316 sp_type_eq(0, '[]') 317 sp_type_eq(0, '{}') 318 sp_type_eq(0, '1') 319 sp_type_eq(0, '0.0') 320 sp_type_eq(0, '(1.0/0.0)') 321 sp_type_eq(0, '-(1.0/0.0)') 322 sp_type_eq(0, '(1.0/0.0-1.0/0.0)') 323 end) 324 end) 325 326 describe('function msgpack#string', function() 327 local string_eq = function(expected, val) 328 eq(expected, nvim_eval(('msgpack#string(%s)'):format(val))) 329 end 330 331 it('works for special dictionaries', function() 332 string_eq('""', sp('string', '[""]')) 333 string_eq('"\\n"', sp('string', '["", ""]')) 334 string_eq('"ab\\0c\\nde"', sp('string', '["ab\\nc", "de"]')) 335 string_eq('+(2)""', sp('ext', '[2, [""]]')) 336 string_eq('+(2)"\\n"', sp('ext', '[2, ["", ""]]')) 337 string_eq('+(2)"ab\\0c\\nde"', sp('ext', '[2, ["ab\\nc", "de"]]')) 338 string_eq('[]', sp('array', '[]')) 339 string_eq('[[[[{}]]]]', sp('array', '[[[[{}]]]]')) 340 string_eq('{}', sp('map', '[]')) 341 string_eq('{2: 10}', sp('map', '[[2, 10]]')) 342 string_eq( 343 '{{1: 1}: {1: 1}, {2: 1}: {1: 1}}', 344 mapsp(mapsp('2', '1'), mapsp('1', '1'), mapsp('1', '1'), mapsp('1', '1')) 345 ) 346 string_eq( 347 '{{1: 1}: {1: 1}, {2: 1}: {1: 1}}', 348 mapsp(mapsp('1', '1'), mapsp('1', '1'), mapsp('2', '1'), mapsp('1', '1')) 349 ) 350 string_eq( 351 '{[1, 2, {{1: 2}: 1}]: [1, 2, {{1: 2}: 1}]}', 352 mapsp( 353 ('[1, 2, %s]'):format(mapsp(mapsp('1', '2'), '1')), 354 ('[1, 2, %s]'):format(mapsp(mapsp('1', '2'), '1')) 355 ) 356 ) 357 string_eq('0x0000000000000000', sp('integer', '[1, 0, 0, 0]')) 358 string_eq('-0x0000000100000000', sp('integer', '[-1, 0, 2, 0]')) 359 string_eq('0x123456789abcdef0', sp('integer', '[ 1, 0, 610839793, 448585456]')) 360 string_eq('-0x123456789abcdef0', sp('integer', '[-1, 0, 610839793, 448585456]')) 361 string_eq('0xf23456789abcdef0', sp('integer', '[ 1, 3, 1684581617, 448585456]')) 362 string_eq('-0x723456789abcdef0', sp('integer', '[-1, 1, 1684581617, 448585456]')) 363 string_eq('0.0', sp('float', '0.0')) 364 string_eq('inf', sp('float', '(1.0/0.0)')) 365 string_eq('-inf', sp('float', '-(1.0/0.0)')) 366 string_eq('nan', sp('float', '(1.0/0.0-1.0/0.0)')) 367 string_eq('nan', sp('float', '-(1.0/0.0-1.0/0.0)')) 368 string_eq('FALSE', sp('boolean', '0')) 369 string_eq('TRUE', sp('boolean', '1')) 370 string_eq('NIL', sp('nil', '0')) 371 end) 372 373 it('works for regular values', function() 374 string_eq('""', '""') 375 string_eq('"\\n"', '"\\n"') 376 string_eq('[]', '[]') 377 string_eq('[[[{}]]]', '[[[{}]]]') 378 string_eq('{}', '{}') 379 string_eq('{"2": 10}', '{2: 10}') 380 string_eq('{"2": [{}]}', '{2: [{}]}') 381 string_eq('1', '1') 382 string_eq('0.0', '0.0') 383 string_eq('inf', '(1.0/0.0)') 384 string_eq('-inf', '-(1.0/0.0)') 385 string_eq('nan', '(1.0/0.0-1.0/0.0)') 386 string_eq('nan', '-(1.0/0.0-1.0/0.0)') 387 end) 388 389 it('works for special v: values like v:true', function() 390 string_eq('TRUE', 'v:true') 391 string_eq('FALSE', 'v:false') 392 string_eq('NIL', 'v:null') 393 end) 394 end) 395 396 describe('function msgpack#deepcopy', function() 397 it('works for special dictionaries', function() 398 nvim_command('let sparr = ' .. sp('array', '[[[]]]')) 399 nvim_command('let spmap = ' .. mapsp('"abc"', '[[]]')) 400 nvim_command('let spint = ' .. sp('integer', '[1, 0, 0, 0]')) 401 nvim_command('let spflt = ' .. sp('float', '1.0')) 402 nvim_command('let spext = ' .. sp('ext', '[2, ["abc", "def"]]')) 403 nvim_command('let spstr = ' .. sp('string', '["abc", "def"]')) 404 nvim_command('let spbln = ' .. sp('boolean', '0')) 405 nvim_command('let spnil = ' .. sp('nil', '0')) 406 407 nvim_command('let sparr2 = msgpack#deepcopy(sparr)') 408 nvim_command('let spmap2 = msgpack#deepcopy(spmap)') 409 nvim_command('let spint2 = msgpack#deepcopy(spint)') 410 nvim_command('let spflt2 = msgpack#deepcopy(spflt)') 411 nvim_command('let spext2 = msgpack#deepcopy(spext)') 412 nvim_command('let spstr2 = msgpack#deepcopy(spstr)') 413 nvim_command('let spbln2 = msgpack#deepcopy(spbln)') 414 nvim_command('let spnil2 = msgpack#deepcopy(spnil)') 415 416 eq('array', nvim_eval('msgpack#type(sparr2)')) 417 eq('map', nvim_eval('msgpack#type(spmap2)')) 418 eq('integer', nvim_eval('msgpack#type(spint2)')) 419 eq('float', nvim_eval('msgpack#type(spflt2)')) 420 eq('ext', nvim_eval('msgpack#type(spext2)')) 421 eq('string', nvim_eval('msgpack#type(spstr2)')) 422 eq('boolean', nvim_eval('msgpack#type(spbln2)')) 423 eq('nil', nvim_eval('msgpack#type(spnil2)')) 424 425 nvim_command('call add(sparr._VAL, 0)') 426 nvim_command('call add(sparr._VAL[0], 0)') 427 nvim_command('call add(sparr._VAL[0][0], 0)') 428 nvim_command('call add(spmap._VAL, [0, 0])') 429 nvim_command('call add(spmap._VAL[0][1], 0)') 430 nvim_command('call add(spmap._VAL[0][1][0], 0)') 431 nvim_command('let spint._VAL[1] = 1') 432 nvim_command('let spflt._VAL = 0.0') 433 nvim_command('let spext._VAL[0] = 3') 434 nvim_command('let spext._VAL[1][0] = "gh"') 435 nvim_command('let spstr._VAL[0] = "gh"') 436 nvim_command('let spbln._VAL = 1') 437 nvim_command('let spnil._VAL = 1') 438 439 eq({ _TYPE = {}, _VAL = { { {} } } }, nvim_eval('sparr2')) 440 eq({ _TYPE = {}, _VAL = { { 'abc', { {} } } } }, nvim_eval('spmap2')) 441 eq({ _TYPE = {}, _VAL = { 1, 0, 0, 0 } }, nvim_eval('spint2')) 442 eq({ _TYPE = {}, _VAL = 1.0 }, nvim_eval('spflt2')) 443 eq({ _TYPE = {}, _VAL = { 2, { 'abc', 'def' } } }, nvim_eval('spext2')) 444 eq({ _TYPE = {}, _VAL = { 'abc', 'def' } }, nvim_eval('spstr2')) 445 eq({ _TYPE = {}, _VAL = 0 }, nvim_eval('spbln2')) 446 eq({ _TYPE = {}, _VAL = 0 }, nvim_eval('spnil2')) 447 448 nvim_command('let sparr._TYPE = []') 449 nvim_command('let spmap._TYPE = []') 450 nvim_command('let spint._TYPE = []') 451 nvim_command('let spflt._TYPE = []') 452 nvim_command('let spext._TYPE = []') 453 nvim_command('let spstr._TYPE = []') 454 nvim_command('let spbln._TYPE = []') 455 nvim_command('let spnil._TYPE = []') 456 457 eq('array', nvim_eval('msgpack#special_type(sparr2)')) 458 eq('map', nvim_eval('msgpack#special_type(spmap2)')) 459 eq('integer', nvim_eval('msgpack#special_type(spint2)')) 460 eq('float', nvim_eval('msgpack#special_type(spflt2)')) 461 eq('ext', nvim_eval('msgpack#special_type(spext2)')) 462 eq('string', nvim_eval('msgpack#special_type(spstr2)')) 463 eq('boolean', nvim_eval('msgpack#special_type(spbln2)')) 464 eq('nil', nvim_eval('msgpack#special_type(spnil2)')) 465 end) 466 467 it('works for regular values', function() 468 nvim_command('let arr = [[[]]]') 469 nvim_command('let map = {1: {}}') 470 nvim_command('let int = 1') 471 nvim_command('let flt = 2.0') 472 nvim_command('let bin = "abc"') 473 474 nvim_command('let arr2 = msgpack#deepcopy(arr)') 475 nvim_command('let map2 = msgpack#deepcopy(map)') 476 nvim_command('let int2 = msgpack#deepcopy(int)') 477 nvim_command('let flt2 = msgpack#deepcopy(flt)') 478 nvim_command('let bin2 = msgpack#deepcopy(bin)') 479 480 eq('array', nvim_eval('msgpack#type(arr2)')) 481 eq('map', nvim_eval('msgpack#type(map2)')) 482 eq('integer', nvim_eval('msgpack#type(int2)')) 483 eq('float', nvim_eval('msgpack#type(flt2)')) 484 eq('string', nvim_eval('msgpack#type(bin2)')) 485 486 nvim_command('call add(arr, 0)') 487 nvim_command('call add(arr[0], 0)') 488 nvim_command('call add(arr[0][0], 0)') 489 nvim_command('let map.a = 1') 490 nvim_command('let map.1.a = 1') 491 nvim_command('let int = 2') 492 nvim_command('let flt = 3.0') 493 nvim_command('let bin = ""') 494 495 eq({ { {} } }, nvim_eval('arr2')) 496 eq({ ['1'] = {} }, nvim_eval('map2')) 497 eq(1, nvim_eval('int2')) 498 eq(2.0, nvim_eval('flt2')) 499 eq('abc', nvim_eval('bin2')) 500 end) 501 502 it('works for special v: values like v:true', function() 503 api.nvim_set_var('true', true) 504 api.nvim_set_var('false', false) 505 api.nvim_set_var('nil', NIL) 506 507 nvim_command('let true2 = msgpack#deepcopy(true)') 508 nvim_command('let false2 = msgpack#deepcopy(false)') 509 nvim_command('let nil2 = msgpack#deepcopy(nil)') 510 511 eq(true, api.nvim_get_var('true')) 512 eq(false, api.nvim_get_var('false')) 513 eq(NIL, api.nvim_get_var('nil')) 514 end) 515 end) 516 517 describe('function msgpack#eval', function() 518 local eval_eq = function(expected_type, expected_val, str, ...) 519 nvim_command( 520 ("let g:__val = msgpack#eval('%s', %s)"):format(str:gsub("'", "''"), select(1, ...) or '{}') 521 ) 522 eq(expected_type, nvim_eval('msgpack#type(g:__val)')) 523 local expected_val_full = expected_val 524 if 525 not (({ float = true, integer = true })[expected_type] and type(expected_val) ~= 'table') 526 and expected_type ~= 'array' 527 then 528 expected_val_full = { _TYPE = {}, _VAL = expected_val_full } 529 end 530 if expected_val_full == expected_val_full then 531 eq(expected_val_full, nvim_eval('g:__val')) 532 else -- NaN 533 local nvim_nan = tostring(nvim_eval('g:__val')) 534 -- -NaN is a hardware-specific detail, there's no need to test for it. 535 -- Accept ether 'nan' or '-nan' as the response. 536 ok(nvim_nan == 'nan' or nvim_nan == '-nan') 537 end 538 nvim_command('unlet g:__val') 539 end 540 541 it('correctly loads strings', function() 542 eval_eq('string', { 'abcdef' }, '="abcdef"') 543 eval_eq('string', { 'abc', 'def' }, '="abc\\ndef"') 544 eval_eq('string', { 'abc\ndef' }, '="abc\\0def"') 545 eval_eq('string', { '\nabc\ndef\n' }, '="\\0abc\\0def\\0"') 546 eval_eq('string', { 'abc\n\n\ndef' }, '="abc\\0\\0\\0def"') 547 eval_eq('string', { 'abc\n', '\ndef' }, '="abc\\0\\n\\0def"') 548 eval_eq('string', { 'abc', '', '', 'def' }, '="abc\\n\\n\\ndef"') 549 eval_eq('string', { 'abc', '', '', 'def', '' }, '="abc\\n\\n\\ndef\\n"') 550 eval_eq('string', { '', 'abc', '', '', 'def' }, '="\\nabc\\n\\n\\ndef"') 551 eval_eq('string', { '' }, '=""') 552 eval_eq('string', { '"' }, '="\\""') 553 eval_eq('string', { 'py3 print(sys.version_info)' }, '="py3 print(sys.version_info)"') 554 end) 555 556 it('correctly loads ext values', function() 557 eval_eq('ext', { 0, { 'abcdef' } }, '+(0)"abcdef"') 558 eval_eq('ext', { 0, { 'abc', 'def' } }, '+(0)"abc\\ndef"') 559 eval_eq('ext', { 0, { 'abc\ndef' } }, '+(0)"abc\\0def"') 560 eval_eq('ext', { 0, { '\nabc\ndef\n' } }, '+(0)"\\0abc\\0def\\0"') 561 eval_eq('ext', { 0, { 'abc\n\n\ndef' } }, '+(0)"abc\\0\\0\\0def"') 562 eval_eq('ext', { 0, { 'abc\n', '\ndef' } }, '+(0)"abc\\0\\n\\0def"') 563 eval_eq('ext', { 0, { 'abc', '', '', 'def' } }, '+(0)"abc\\n\\n\\ndef"') 564 eval_eq('ext', { 0, { 'abc', '', '', 'def', '' } }, '+(0)"abc\\n\\n\\ndef\\n"') 565 eval_eq('ext', { 0, { '', 'abc', '', '', 'def' } }, '+(0)"\\nabc\\n\\n\\ndef"') 566 eval_eq('ext', { 0, { '' } }, '+(0)""') 567 eval_eq('ext', { 0, { '"' } }, '+(0)"\\""') 568 569 eval_eq('ext', { -1, { 'abcdef' } }, '+(-1)"abcdef"') 570 eval_eq('ext', { -1, { 'abc', 'def' } }, '+(-1)"abc\\ndef"') 571 eval_eq('ext', { -1, { 'abc\ndef' } }, '+(-1)"abc\\0def"') 572 eval_eq('ext', { -1, { '\nabc\ndef\n' } }, '+(-1)"\\0abc\\0def\\0"') 573 eval_eq('ext', { -1, { 'abc\n\n\ndef' } }, '+(-1)"abc\\0\\0\\0def"') 574 eval_eq('ext', { -1, { 'abc\n', '\ndef' } }, '+(-1)"abc\\0\\n\\0def"') 575 eval_eq('ext', { -1, { 'abc', '', '', 'def' } }, '+(-1)"abc\\n\\n\\ndef"') 576 eval_eq('ext', { -1, { 'abc', '', '', 'def', '' } }, '+(-1)"abc\\n\\n\\ndef\\n"') 577 eval_eq('ext', { -1, { '', 'abc', '', '', 'def' } }, '+(-1)"\\nabc\\n\\n\\ndef"') 578 eval_eq('ext', { -1, { '' } }, '+(-1)""') 579 eval_eq('ext', { -1, { '"' } }, '+(-1)"\\""') 580 581 eval_eq( 582 'ext', 583 { 42, { 'py3 print(sys.version_info)' } }, 584 '+(42)"py3 print(sys.version_info)"' 585 ) 586 end) 587 588 it('correctly loads floats', function() 589 eval_eq('float', inf, 'inf') 590 eval_eq('float', minus_inf, '-inf') 591 eval_eq('float', nan, 'nan') 592 eval_eq('float', 1.0e10, '1.0e10') 593 eval_eq('float', 1.0e10, '1.0e+10') 594 eval_eq('float', -1.0e10, '-1.0e+10') 595 eval_eq('float', 1.0, '1.0') 596 eval_eq('float', -1.0, '-1.0') 597 eval_eq('float', 1.0e-10, '1.0e-10') 598 eval_eq('float', -1.0e-10, '-1.0e-10') 599 end) 600 601 it('correctly loads integers', function() 602 eval_eq('integer', 10, '10') 603 eval_eq('integer', -10, '-10') 604 eval_eq('integer', { 1, 0, 610839793, 448585456 }, ' 0x123456789ABCDEF0') 605 eval_eq('integer', { -1, 0, 610839793, 448585456 }, '-0x123456789ABCDEF0') 606 eval_eq('integer', { 1, 3, 1684581617, 448585456 }, ' 0xF23456789ABCDEF0') 607 eval_eq('integer', { -1, 1, 1684581617, 448585456 }, '-0x723456789ABCDEF0') 608 eval_eq('integer', { 1, 0, 0, 0x100 }, '0x100') 609 eval_eq('integer', { -1, 0, 0, 0x100 }, '-0x100') 610 611 eval_eq('integer', ('a'):byte(), "'a'") 612 eval_eq('integer', 0xAB, "'«'") 613 eval_eq('integer', 0, "'\\0'") 614 eval_eq('integer', 10246567, "'\\10246567'") 615 end) 616 617 it('correctly loads constants', function() 618 eval_eq('boolean', 1, 'TRUE') 619 eval_eq('boolean', 0, 'FALSE') 620 eval_eq('nil', 0, 'NIL') 621 eval_eq('nil', 0, 'NIL', '{"NIL": 1, "nan": 2, "T": 3}') 622 eval_eq('float', nan, 'nan', '{"NIL": "1", "nan": "2", "T": "3"}') 623 eval_eq('integer', 3, 'T', '{"NIL": "1", "nan": "2", "T": "3"}') 624 eval_eq( 625 'integer', 626 { 1, 0, 0, 0 }, 627 'T', 628 ('{"NIL": "1", "nan": "2", "T": \'%s\'}'):format(sp('integer', '[1, 0, 0, 0]')) 629 ) 630 end) 631 632 it('correctly loads maps', function() 633 eval_eq('map', {}, '{}') 634 eval_eq( 635 'map', 636 { { { _TYPE = {}, _VAL = { { 1, 2 } } }, { _TYPE = {}, _VAL = { { 3, 4 } } } } }, 637 '{{1: 2}: {3: 4}}' 638 ) 639 eval_eq( 640 'map', 641 { { { _TYPE = {}, _VAL = { { 1, 2 } } }, { _TYPE = {}, _VAL = { { 3, 4 } } } }, { 1, 2 } }, 642 '{{1: 2}: {3: 4}, 1: 2}' 643 ) 644 645 eval_eq('map', { 646 { 647 { 648 _TYPE = {}, 649 _VAL = { 650 { { _TYPE = {}, _VAL = { 'py3 print(sys.version_info)' } }, 2 }, 651 }, 652 }, 653 { _TYPE = {}, _VAL = { { 3, 4 } } }, 654 }, 655 { 1, 2 }, 656 }, '{{"py3 print(sys.version_info)": 2}: {3: 4}, 1: 2}') 657 end) 658 659 it('correctly loads arrays', function() 660 eval_eq('array', {}, '[]') 661 eval_eq('array', { 1 }, '[1]') 662 eval_eq('array', { { _TYPE = {}, _VAL = 1 } }, '[TRUE]') 663 eval_eq( 664 'array', 665 { { { _TYPE = {}, _VAL = { { 1, 2 } } } }, { _TYPE = {}, _VAL = { { 3, 4 } } } }, 666 '[[{1: 2}], {3: 4}]' 667 ) 668 669 eval_eq( 670 'array', 671 { { _TYPE = {}, _VAL = { 'py3 print(sys.version_info)' } } }, 672 '["py3 print(sys.version_info)"]' 673 ) 674 end) 675 676 it('errors out when needed', function() 677 eq('empty:Parsed string is empty', exc_exec('call msgpack#eval("", {})')) 678 eq('unknown:Invalid non-space character: ^', exc_exec('call msgpack#eval("^", {})')) 679 eq( 680 "char-invalid:Invalid integer character literal format: ''", 681 exc_exec('call msgpack#eval("\'\'", {})') 682 ) 683 eq( 684 "char-invalid:Invalid integer character literal format: 'ab'", 685 exc_exec('call msgpack#eval("\'ab\'", {})') 686 ) 687 eq( 688 "char-invalid:Invalid integer character literal format: '", 689 exc_exec('call msgpack#eval("\'", {})') 690 ) 691 eq('"-invalid:Invalid string: "', exc_exec('call msgpack#eval("\\"", {})')) 692 eq('"-invalid:Invalid string: ="', exc_exec('call msgpack#eval("=\\"", {})')) 693 eq('"-invalid:Invalid string: +(0)"', exc_exec('call msgpack#eval("+(0)\\"", {})')) 694 eq( 695 '0.-nodigits:Decimal dot must be followed by digit(s): .e1', 696 exc_exec('call msgpack#eval("0.e1", {})') 697 ) 698 eq( 699 '0x-long:Must have at most 16 hex digits: FEDCBA98765432100', 700 exc_exec('call msgpack#eval("0xFEDCBA98765432100", {})') 701 ) 702 eq('0x-empty:Must have number after 0x: ', exc_exec('call msgpack#eval("0x", {})')) 703 eq('name-unknown:Unknown name FOO: FOO', exc_exec('call msgpack#eval("FOO", {})')) 704 705 eq( 706 'name-unknown:Unknown name py3: py3 print(sys.version_info)', 707 exc_exec('call msgpack#eval("py3 print(sys.version_info)", {})') 708 ) 709 eq('name-unknown:Unknown name o: o', exc_exec('call msgpack#eval("-info", {})')) 710 end) 711 end) 712 end)