shada_spec.lua (117866B)
1 local t = require('test.testutil') 2 local n = require('test.functional.testnvim')() 3 local Screen = require('test.functional.ui.screen') 4 local t_shada = require('test.functional.shada.testutil') 5 6 local clear = n.clear 7 local eq, api, nvim_eval, nvim_command, exc_exec, fn, nvim_feed = 8 t.eq, n.api, n.eval, n.command, n.exc_exec, n.fn, n.feed 9 local neq = t.neq 10 local read_file = t.read_file 11 12 local get_shada_rw = t_shada.get_shada_rw 13 14 local function reset(shada_file) 15 clear { args = { '-u', 'NORC', '-i', shada_file or 'NONE' } } 16 end 17 18 local mpack_eq = function(expected, mpack_result) 19 local mpack_keys = { 'type', 'timestamp', 'length', 'value' } 20 21 local unpack = vim.mpack.Unpacker() 22 local actual = {} 23 local cur, val 24 local i = 0 25 local off = 1 26 while off <= #mpack_result do 27 val, off = unpack(mpack_result, off) 28 if i % 4 == 0 then 29 cur = {} 30 actual[#actual + 1] = cur 31 end 32 local key = mpack_keys[(i % 4) + 1] 33 if key ~= 'length' then 34 if key == 'timestamp' and math.abs(val - os.time()) < 2 then 35 val = 'current' 36 end 37 cur[key] = val 38 end 39 i = i + 1 40 end 41 eq(expected, actual) 42 end 43 44 local wshada, _, fname = get_shada_rw('Xtest-functional-plugin-shada.shada') 45 46 local wshada_tmp, _, fname_tmp = get_shada_rw('Xtest-functional-plugin-shada.shada.tmp.f') 47 48 describe('autoload/shada.vim', function() 49 local epoch = os.date('%Y-%m-%dT%H:%M:%S', 0) 50 setup(function() 51 reset() 52 nvim_command([[ 53 function ModifyVal(val) 54 if type(a:val) == type([]) 55 if len(a:val) == 2 && type(a:val[0]) == type('') && a:val[0][0] is# '!' && has_key(v:msgpack_types, a:val[0][1:]) 56 return {'_TYPE': v:msgpack_types[ a:val[0][1:] ], '_VAL': a:val[1]} 57 else 58 return map(copy(a:val), 'ModifyVal(v:val)') 59 endif 60 elseif type(a:val) == type({}) 61 let keys = sort(keys(a:val)) 62 let ret = {'_TYPE': v:msgpack_types.map, '_VAL': []} 63 for key in keys 64 let k = {'_TYPE': v:msgpack_types.string, '_VAL': split(key, "\n", 1)} 65 let v = ModifyVal(a:val[key]) 66 call add(ret._VAL, [k, v]) 67 unlet v 68 endfor 69 return ret 70 elseif type(a:val) == type('') 71 return {'_TYPE': v:msgpack_types.string, '_VAL': split(a:val, "\n", 1)} 72 else 73 return a:val 74 endif 75 endfunction 76 ]]) 77 end) 78 79 local sp = function(typ, val) 80 return ('{"_TYPE": v:msgpack_types.%s, "_VAL": %s}'):format(typ, val) 81 end 82 83 describe('function shada#mpack_to_sd', function() 84 local mpack2sd = function(arg) 85 return ('shada#mpack_to_sd(%s)'):format(arg) 86 end 87 88 it('works', function() 89 eq({}, nvim_eval(mpack2sd('[]'))) 90 eq({ { type = 1, timestamp = 5, length = 1, data = 7 } }, nvim_eval(mpack2sd('[1, 5, 1, 7]'))) 91 eq({ 92 { type = 1, timestamp = 5, length = 1, data = 7 }, 93 { type = 1, timestamp = 10, length = 1, data = 5 }, 94 }, nvim_eval(mpack2sd('[1, 5, 1, 7, 1, 10, 1, 5]'))) 95 eq( 96 'zero-uint:Entry 1 has type element which is zero', 97 exc_exec('call ' .. mpack2sd('[0, 5, 1, 7]')) 98 ) 99 eq( 100 'zero-uint:Entry 1 has type element which is zero', 101 exc_exec('call ' .. mpack2sd(('[%s, 5, 1, 7]'):format(sp('integer', '[1, 0, 0, 0]')))) 102 ) 103 eq( 104 'not-uint:Entry 1 has timestamp element which is not an unsigned integer', 105 exc_exec('call ' .. mpack2sd('[1, -1, 1, 7]')) 106 ) 107 eq( 108 'not-uint:Entry 1 has length element which is not an unsigned integer', 109 exc_exec('call ' .. mpack2sd('[1, 1, -1, 7]')) 110 ) 111 eq( 112 'not-uint:Entry 1 has type element which is not an unsigned integer', 113 exc_exec('call ' .. mpack2sd('["", 1, -1, 7]')) 114 ) 115 end) 116 end) 117 118 describe('function shada#sd_to_strings', function() 119 local sd2strings_eq = function(expected, arg) 120 if type(arg) == 'table' then 121 eq(expected, fn['shada#sd_to_strings'](arg)) 122 else 123 eq(expected, nvim_eval(('shada#sd_to_strings(%s)'):format(arg))) 124 end 125 end 126 127 it('works with empty input', function() 128 sd2strings_eq({}, '[]') 129 end) 130 131 it('works with unknown items', function() 132 sd2strings_eq({ 133 'Unknown (0x64) with timestamp ' .. epoch .. ':', 134 ' = 100', 135 }, { { type = 100, timestamp = 0, length = 1, data = 100 } }) 136 137 sd2strings_eq( 138 { 139 'Unknown (0x4000001180000006) with timestamp ' .. epoch .. ':', 140 ' = 100', 141 }, 142 ('[{"type": %s, "timestamp": 0, "length": 1, "data": 100}]'):format( 143 sp('integer', '[1, 1, 35, 6]') 144 ) 145 ) 146 end) 147 148 it('works with multiple unknown items', function() 149 sd2strings_eq({ 150 'Unknown (0x64) with timestamp ' .. epoch .. ':', 151 ' = 100', 152 'Unknown (0x65) with timestamp ' .. epoch .. ':', 153 ' = 500', 154 }, { 155 { type = 100, timestamp = 0, length = 1, data = 100 }, 156 { type = 101, timestamp = 0, length = 1, data = 500 }, 157 }) 158 end) 159 160 it('works with header items', function() 161 sd2strings_eq({ 162 'Header with timestamp ' .. epoch .. ':', 163 ' % Key______ Value', 164 ' + generator "test"', 165 }, { { type = 1, timestamp = 0, data = { generator = 'test' } } }) 166 sd2strings_eq({ 167 'Header with timestamp ' .. epoch .. ':', 168 ' % Key Description Value', 169 ' + a 1', 170 ' + b 2', 171 ' + c column 3', 172 ' + d 4', 173 }, { { type = 1, timestamp = 0, data = { a = 1, b = 2, c = 3, d = 4 } } }) 174 sd2strings_eq({ 175 'Header with timestamp ' .. epoch .. ':', 176 ' % Key Value', 177 ' + t "test"', 178 }, { { type = 1, timestamp = 0, data = { t = 'test' } } }) 179 sd2strings_eq({ 180 'Header with timestamp ' .. epoch .. ':', 181 ' # Unexpected type: array instead of map', 182 ' = [1, 2, 3]', 183 }, { { type = 1, timestamp = 0, data = { 1, 2, 3 } } }) 184 end) 185 186 it('processes standard keys correctly, even in header', function() 187 sd2strings_eq( 188 { 189 'Header with timestamp ' .. epoch .. ':', 190 ' % Key Description________ Value', 191 ' + c column 0', 192 ' + f file name "/tmp/foo"', 193 ' + l line number 10', 194 " + n name '@'", 195 ' + rc contents ["abc", "def"]', 196 ' + rt type CHARACTERWISE', 197 ' + ru is_unnamed FALSE', 198 ' + rw block width 10', 199 ' + sb search backward TRUE', 200 ' + sc smartcase value FALSE', 201 ' + se place cursor at end TRUE', 202 ' + sh v:hlsearch value TRUE', 203 ' + sl has line offset FALSE', 204 ' + sm magic value TRUE', 205 ' + so offset value 10', 206 ' + sp pattern "100"', 207 ' + ss is :s pattern TRUE', 208 ' + su is last used FALSE', 209 }, 210 ([[ [{'type': 1, 'timestamp': 0, 'data': { 211 'sm': {'_TYPE': v:msgpack_types.boolean, '_VAL': 1}, 212 'sc': {'_TYPE': v:msgpack_types.boolean, '_VAL': 0}, 213 'sl': {'_TYPE': v:msgpack_types.boolean, '_VAL': 0}, 214 'se': {'_TYPE': v:msgpack_types.boolean, '_VAL': 1}, 215 'sb': {'_TYPE': v:msgpack_types.boolean, '_VAL': 1}, 216 'so': 10, 217 'su': {'_TYPE': v:msgpack_types.boolean, '_VAL': 0}, 218 'ss': {'_TYPE': v:msgpack_types.boolean, '_VAL': 1}, 219 'sh': {'_TYPE': v:msgpack_types.boolean, '_VAL': 1}, 220 'sp': '100', 221 'rt': 0, 222 'rw': 10, 223 'rc': ['abc', 'def'], 224 'ru': {'_TYPE': v:msgpack_types.boolean, '_VAL': 0}, 225 'n': 0x40, 226 'l': 10, 227 'c': 0, 228 'f': '/tmp/foo', 229 }}] ]]):gsub('\n', '') 230 ) 231 sd2strings_eq( 232 { 233 'Header with timestamp ' .. epoch .. ':', 234 ' % Key Description____ Value', 235 ' # Expected integer', 236 ' + c column "abc"', 237 ' # Expected no NUL bytes', 238 ' + f file name "abc\\0def"', 239 ' # Value is negative', 240 ' + l line number -10', 241 ' # Value is negative', 242 ' + n name -64', 243 ' # Expected array value', 244 ' + rc contents "10"', 245 ' # Unexpected enum value: expected one of ' 246 .. '0 (CHARACTERWISE), 1 (LINEWISE), 2 (BLOCKWISE)', 247 ' + rt type 10', 248 ' # Expected boolean', 249 ' + ru is_unnamed 10', 250 ' # Expected boolean', 251 ' + sc smartcase value NIL', 252 ' # Expected boolean', 253 ' + sm magic value "TRUE"', 254 ' # Expected integer', 255 ' + so offset value "TRUE"', 256 ' + sp pattern "abc"', 257 }, 258 ([[ [{'type': 1, 'timestamp': 0, 'data': { 259 'sm': 'TRUE', 260 'sc': {'_TYPE': v:msgpack_types.nil, '_VAL': 0}, 261 'so': 'TRUE', 262 'sp': {'_TYPE': v:msgpack_types.string, '_VAL': ["abc"]}, 263 'rt': 10, 264 'rc': '10', 265 'ru': 10, 266 'n': -0x40, 267 'l': -10, 268 'c': 'abc', 269 'f': {'_TYPE': v:msgpack_types.string, '_VAL': ["abc\ndef"]}, 270 }}] ]]):gsub('\n', '') 271 ) 272 sd2strings_eq( 273 { 274 'Header with timestamp ' .. epoch .. ':', 275 ' % Key Description Value', 276 ' # Expected no NUL bytes', 277 ' + f file name "abc\\0def"', 278 ' + rc contents ["abc", "abc"]', 279 ' # Expected integer', 280 ' + rt type "ABC"', 281 }, 282 ([[ [{'type': 1, 'timestamp': 0, 'data': { 283 'rt': 'ABC', 284 'rc': ["abc", {'_TYPE': v:msgpack_types.string, '_VAL': ["abc"]}], 285 'f': {'_TYPE': v:msgpack_types.string, '_VAL': ["abc\ndef"]}, 286 }}] ]]):gsub('\n', '') 287 ) 288 sd2strings_eq( 289 { 290 'Header with timestamp ' .. epoch .. ':', 291 ' % Key Description Value', 292 ' # Expected no NUL bytes', 293 ' + rc contents ["abc", "a\\nd\\0"]', 294 }, 295 ([[ [{'type': 1, 'timestamp': 0, 'data': { 296 'rc': ["abc", {'_TYPE': v:msgpack_types.string, '_VAL': ["a", "d\n"]}], 297 }}] ]]):gsub('\n', '') 298 ) 299 end) 300 301 it('works with search pattern items', function() 302 sd2strings_eq({ 303 'Search pattern with timestamp ' .. epoch .. ':', 304 ' # Unexpected type: array instead of map', 305 ' = [1, 2, 3]', 306 }, { { type = 2, timestamp = 0, data = { 1, 2, 3 } } }) 307 sd2strings_eq( 308 { 309 'Search pattern with timestamp ' .. epoch .. ':', 310 ' % Key Description________ Value', 311 ' + sp pattern "abc"', 312 ' + sh v:hlsearch value FALSE', 313 ' + ss is :s pattern FALSE', 314 ' + sb search backward FALSE', 315 ' + sm magic value TRUE', 316 ' + sc smartcase value FALSE', 317 ' + sl has line offset FALSE', 318 ' + se place cursor at end FALSE', 319 ' + so offset value 0', 320 ' + su is last used TRUE', 321 }, 322 ([[ [{'type': 2, 'timestamp': 0, 'data': { 323 'sp': 'abc', 324 }}] ]]):gsub('\n', '') 325 ) 326 sd2strings_eq( 327 { 328 'Search pattern with timestamp ' .. epoch .. ':', 329 ' % Key Description________ Value', 330 ' + sp pattern "abc"', 331 ' + sh v:hlsearch value FALSE', 332 ' + ss is :s pattern FALSE', 333 ' + sb search backward FALSE', 334 ' + sm magic value TRUE', 335 ' + sc smartcase value FALSE', 336 ' + sl has line offset FALSE', 337 ' + se place cursor at end FALSE', 338 ' + so offset value 0', 339 ' + su is last used TRUE', 340 ' + sX NIL', 341 ' + sY NIL', 342 ' + sZ NIL', 343 }, 344 ([[ [{'type': 2, 'timestamp': 0, 'data': { 345 'sp': 'abc', 346 'sZ': {'_TYPE': v:msgpack_types.nil, '_VAL': 0}, 347 'sY': {'_TYPE': v:msgpack_types.nil, '_VAL': 0}, 348 'sX': {'_TYPE': v:msgpack_types.nil, '_VAL': 0}, 349 }}] ]]):gsub('\n', '') 350 ) 351 sd2strings_eq( 352 { 353 'Search pattern with timestamp ' .. epoch .. ':', 354 ' % Key Description________ Value', 355 ' + sp pattern "abc"', 356 ' + sh v:hlsearch value FALSE', 357 ' + ss is :s pattern FALSE', 358 ' + sb search backward FALSE', 359 ' + sm magic value TRUE', 360 ' + sc smartcase value FALSE', 361 ' + sl has line offset FALSE', 362 ' + se place cursor at end FALSE', 363 ' + so offset value 0', 364 ' + su is last used TRUE', 365 }, 366 ([[ [{'type': 2, 'timestamp': 0, 'data': { 367 'sp': 'abc', 368 'sh': {'_TYPE': v:msgpack_types.boolean, '_VAL': 0}, 369 'ss': {'_TYPE': v:msgpack_types.boolean, '_VAL': 0}, 370 'sb': {'_TYPE': v:msgpack_types.boolean, '_VAL': 0}, 371 'sm': {'_TYPE': v:msgpack_types.boolean, '_VAL': 1}, 372 'sc': {'_TYPE': v:msgpack_types.boolean, '_VAL': 0}, 373 'sl': {'_TYPE': v:msgpack_types.boolean, '_VAL': 0}, 374 'se': {'_TYPE': v:msgpack_types.boolean, '_VAL': 0}, 375 'so': 0, 376 'su': {'_TYPE': v:msgpack_types.boolean, '_VAL': 1}, 377 }}] ]]):gsub('\n', '') 378 ) 379 sd2strings_eq( 380 { 381 'Search pattern with timestamp ' .. epoch .. ':', 382 ' % Key Description________ Value', 383 ' # Required key missing: sp', 384 ' + sh v:hlsearch value FALSE', 385 ' + ss is :s pattern FALSE', 386 ' + sb search backward FALSE', 387 ' + sm magic value TRUE', 388 ' + sc smartcase value FALSE', 389 ' + sl has line offset FALSE', 390 ' + se place cursor at end FALSE', 391 ' + so offset value 0', 392 ' + su is last used TRUE', 393 }, 394 ([[ [{'type': 2, 'timestamp': 0, 'data': { 395 }}] ]]):gsub('\n', '') 396 ) 397 sd2strings_eq( 398 { 399 'Search pattern with timestamp ' .. epoch .. ':', 400 ' % Key Description________ Value', 401 ' + sp pattern ""', 402 ' + sh v:hlsearch value TRUE', 403 ' + ss is :s pattern TRUE', 404 ' + sb search backward TRUE', 405 ' + sm magic value FALSE', 406 ' + sc smartcase value TRUE', 407 ' + sl has line offset TRUE', 408 ' + se place cursor at end TRUE', 409 ' + so offset value -10', 410 ' + su is last used FALSE', 411 }, 412 ([[ [{'type': 2, 'timestamp': 0, 'data': { 413 'sp': '', 414 'sh': {'_TYPE': v:msgpack_types.boolean, '_VAL': 1}, 415 'ss': {'_TYPE': v:msgpack_types.boolean, '_VAL': 1}, 416 'sb': {'_TYPE': v:msgpack_types.boolean, '_VAL': 1}, 417 'sm': {'_TYPE': v:msgpack_types.boolean, '_VAL': 0}, 418 'sc': {'_TYPE': v:msgpack_types.boolean, '_VAL': 1}, 419 'sl': {'_TYPE': v:msgpack_types.boolean, '_VAL': 1}, 420 'se': {'_TYPE': v:msgpack_types.boolean, '_VAL': 1}, 421 'so': -10, 422 'su': {'_TYPE': v:msgpack_types.boolean, '_VAL': 0}, 423 }}] ]]):gsub('\n', '') 424 ) 425 sd2strings_eq( 426 { 427 'Search pattern with timestamp ' .. epoch .. ':', 428 ' % Key Description________ Value', 429 ' # Expected binary string', 430 ' + sp pattern 0', 431 ' # Expected boolean', 432 ' + sh v:hlsearch value 0', 433 ' # Expected boolean', 434 ' + ss is :s pattern 0', 435 ' # Expected boolean', 436 ' + sb search backward 0', 437 ' # Expected boolean', 438 ' + sm magic value 0', 439 ' # Expected boolean', 440 ' + sc smartcase value 0', 441 ' # Expected boolean', 442 ' + sl has line offset 0', 443 ' # Expected boolean', 444 ' + se place cursor at end 0', 445 ' # Expected integer', 446 ' + so offset value ""', 447 ' # Expected boolean', 448 ' + su is last used 0', 449 }, 450 ([[ [{'type': 2, 'timestamp': 0, 'data': { 451 'sp': 0, 452 'sh': 0, 453 'ss': 0, 454 'sb': 0, 455 'sm': 0, 456 'sc': 0, 457 'sl': 0, 458 'se': 0, 459 'so': '', 460 'su': 0, 461 }}] ]]):gsub('\n', '') 462 ) 463 end) 464 465 it('works with replacement string items', function() 466 sd2strings_eq({ 467 'Replacement string with timestamp ' .. epoch .. ':', 468 ' # Unexpected type: map instead of array', 469 ' = {"a": [10]}', 470 }, { { type = 3, timestamp = 0, data = { a = { 10 } } } }) 471 sd2strings_eq( 472 { 473 'Replacement string with timestamp ' .. epoch .. ':', 474 ' @ Description__________ Value', 475 ' # Expected more elements in list', 476 }, 477 ([[ [{'type': 3, 'timestamp': 0, 'data': [ 478 ]}] ]]):gsub('\n', '') 479 ) 480 sd2strings_eq( 481 { 482 'Replacement string with timestamp ' .. epoch .. ':', 483 ' @ Description__________ Value', 484 ' # Expected binary string', 485 ' - :s replacement string 0', 486 }, 487 ([[ [{'type': 3, 'timestamp': 0, 'data': [ 488 0, 489 ]}] ]]):gsub('\n', '') 490 ) 491 sd2strings_eq( 492 { 493 'Replacement string with timestamp ' .. epoch .. ':', 494 ' @ Description__________ Value', 495 ' # Expected no NUL bytes', 496 ' - :s replacement string "abc\\0def"', 497 }, 498 ([[ [{'type': 3, 'timestamp': 0, 'data': [ 499 {'_TYPE': v:msgpack_types.string, '_VAL': ["abc\ndef"]}, 500 ]}] ]]):gsub('\n', '') 501 ) 502 sd2strings_eq( 503 { 504 'Replacement string with timestamp ' .. epoch .. ':', 505 ' @ Description__________ Value', 506 ' - :s replacement string "abc\\ndef"', 507 }, 508 ([[ [{'type': 3, 'timestamp': 0, 'data': [ 509 {'_TYPE': v:msgpack_types.string, '_VAL': ["abc", "def"]}, 510 ]}] ]]):gsub('\n', '') 511 ) 512 sd2strings_eq( 513 { 514 'Replacement string with timestamp ' .. epoch .. ':', 515 ' @ Description__________ Value', 516 ' - :s replacement string "abc\\ndef"', 517 ' - 0', 518 }, 519 ([[ [{'type': 3, 'timestamp': 0, 'data': [ 520 {'_TYPE': v:msgpack_types.string, '_VAL': ["abc", "def"]}, 521 0, 522 ]}] ]]):gsub('\n', '') 523 ) 524 end) 525 526 it('works with history entry items', function() 527 sd2strings_eq({ 528 'History entry with timestamp ' .. epoch .. ':', 529 ' # Unexpected type: map instead of array', 530 ' = {"a": [10]}', 531 }, { { type = 4, timestamp = 0, data = { a = { 10 } } } }) 532 sd2strings_eq( 533 { 534 'History entry with timestamp ' .. epoch .. ':', 535 ' @ Description_ Value', 536 ' # Expected more elements in list', 537 }, 538 ([[ [{'type': 4, 'timestamp': 0, 'data': [ 539 ]}] ]]):gsub('\n', '') 540 ) 541 sd2strings_eq( 542 { 543 'History entry with timestamp ' .. epoch .. ':', 544 ' @ Description_ Value', 545 ' # Expected integer', 546 ' - history type ""', 547 ' # Expected more elements in list', 548 }, 549 ([[ [{'type': 4, 'timestamp': 0, 'data': [ 550 '', 551 ]}] ]]):gsub('\n', '') 552 ) 553 sd2strings_eq( 554 { 555 'History entry with timestamp ' .. epoch .. ':', 556 ' @ Description_ Value', 557 ' # Unexpected enum value: expected one of 0 (CMD), 1 (SEARCH), ' 558 .. '2 (EXPR), 3 (INPUT), 4 (DEBUG)', 559 ' - history type 5', 560 ' - contents ""', 561 }, 562 ([[ [{'type': 4, 'timestamp': 0, 'data': [ 563 5, 564 '' 565 ]}] ]]):gsub('\n', '') 566 ) 567 sd2strings_eq( 568 { 569 'History entry with timestamp ' .. epoch .. ':', 570 ' @ Description_ Value', 571 ' # Unexpected enum value: expected one of 0 (CMD), 1 (SEARCH), ' 572 .. '2 (EXPR), 3 (INPUT), 4 (DEBUG)', 573 ' - history type 5', 574 ' - contents ""', 575 ' - 32', 576 }, 577 ([[ [{'type': 4, 'timestamp': 0, 'data': [ 578 5, 579 '', 580 0x20 581 ]}] ]]):gsub('\n', '') 582 ) 583 sd2strings_eq( 584 { 585 'History entry with timestamp ' .. epoch .. ':', 586 ' @ Description_ Value', 587 ' - history type CMD', 588 ' - contents ""', 589 ' - 32', 590 }, 591 ([[ [{'type': 4, 'timestamp': 0, 'data': [ 592 0, 593 '', 594 0x20 595 ]}] ]]):gsub('\n', '') 596 ) 597 sd2strings_eq( 598 { 599 'History entry with timestamp ' .. epoch .. ':', 600 ' @ Description_ Value', 601 ' - history type SEARCH', 602 ' - contents ""', 603 " - separator ' '", 604 }, 605 ([[ [{'type': 4, 'timestamp': 0, 'data': [ 606 1, 607 '', 608 0x20 609 ]}] ]]):gsub('\n', '') 610 ) 611 sd2strings_eq( 612 { 613 'History entry with timestamp ' .. epoch .. ':', 614 ' @ Description_ Value', 615 ' - history type SEARCH', 616 ' - contents ""', 617 ' # Expected more elements in list', 618 }, 619 ([[ [{'type': 4, 'timestamp': 0, 'data': [ 620 1, 621 '', 622 ]}] ]]):gsub('\n', '') 623 ) 624 sd2strings_eq( 625 { 626 'History entry with timestamp ' .. epoch .. ':', 627 ' @ Description_ Value', 628 ' - history type EXPR', 629 ' - contents ""', 630 }, 631 ([[ [{'type': 4, 'timestamp': 0, 'data': [ 632 2, 633 '', 634 ]}] ]]):gsub('\n', '') 635 ) 636 sd2strings_eq( 637 { 638 'History entry with timestamp ' .. epoch .. ':', 639 ' @ Description_ Value', 640 ' - history type INPUT', 641 ' - contents ""', 642 }, 643 ([[ [{'type': 4, 'timestamp': 0, 'data': [ 644 3, 645 '', 646 ]}] ]]):gsub('\n', '') 647 ) 648 sd2strings_eq( 649 { 650 'History entry with timestamp ' .. epoch .. ':', 651 ' @ Description_ Value', 652 ' - history type DEBUG', 653 ' - contents ""', 654 }, 655 ([[ [{'type': 4, 'timestamp': 0, 'data': [ 656 4, 657 '', 658 ]}] ]]):gsub('\n', '') 659 ) 660 sd2strings_eq( 661 { 662 'History entry with timestamp ' .. epoch .. ':', 663 ' @ Description_ Value', 664 ' - history type DEBUG', 665 ' # Expected binary string', 666 ' - contents 10', 667 }, 668 ([[ [{'type': 4, 'timestamp': 0, 'data': [ 669 4, 670 10, 671 ]}] ]]):gsub('\n', '') 672 ) 673 sd2strings_eq( 674 { 675 'History entry with timestamp ' .. epoch .. ':', 676 ' @ Description_ Value', 677 ' - history type DEBUG', 678 ' # Expected no NUL bytes', 679 ' - contents "abc\\0def"', 680 }, 681 ([[ [{'type': 4, 'timestamp': 0, 'data': [ 682 4, 683 {'_TYPE': v:msgpack_types.string, '_VAL': ["abc\ndef"]}, 684 ]}] ]]):gsub('\n', '') 685 ) 686 sd2strings_eq( 687 { 688 'History entry with timestamp ' .. epoch .. ':', 689 ' @ Description_ Value', 690 ' - history type SEARCH', 691 ' - contents "abc"', 692 ' # Expected integer', 693 ' - separator ""', 694 }, 695 ([[ [{'type': 4, 'timestamp': 0, 'data': [ 696 1, 697 'abc', 698 '', 699 ]}] ]]):gsub('\n', '') 700 ) 701 sd2strings_eq( 702 { 703 'History entry with timestamp ' .. epoch .. ':', 704 ' @ Description_ Value', 705 ' - history type SEARCH', 706 ' - contents "abc"', 707 ' # Value is negative', 708 ' - separator -1', 709 }, 710 ([[ [{'type': 4, 'timestamp': 0, 'data': [ 711 1, 712 'abc', 713 -1, 714 ]}] ]]):gsub('\n', '') 715 ) 716 -- Regression: NUL separator must be properly supported 717 sd2strings_eq( 718 { 719 'History entry with timestamp ' .. epoch .. ':', 720 ' @ Description_ Value', 721 ' - history type SEARCH', 722 ' - contents ""', 723 " - separator '\\0'", 724 }, 725 ([[ [{'type': 4, 'timestamp': 0, 'data': [ 726 1, 727 '', 728 0x0 729 ]}] ]]):gsub('\n', '') 730 ) 731 end) 732 733 it('works with register items', function() 734 sd2strings_eq({ 735 'Register with timestamp ' .. epoch .. ':', 736 ' # Unexpected type: array instead of map', 737 ' = [1, 2, 3]', 738 }, { { type = 5, timestamp = 0, data = { 1, 2, 3 } } }) 739 sd2strings_eq( 740 { 741 'Register with timestamp ' .. epoch .. ':', 742 ' % Key Description Value', 743 ' # Required key missing: n', 744 ' # Required key missing: rc', 745 ' + rw block width 0', 746 ' + rt type CHARACTERWISE', 747 ' + ru is_unnamed FALSE', 748 }, 749 ([[ [{'type': 5, 'timestamp': 0, 'data': { 750 }}] ]]):gsub('\n', '') 751 ) 752 sd2strings_eq( 753 { 754 'Register with timestamp ' .. epoch .. ':', 755 ' % Key Description Value', 756 " + n name ' '", 757 ' # Required key missing: rc', 758 ' + rw block width 0', 759 ' + rt type CHARACTERWISE', 760 ' + ru is_unnamed FALSE', 761 }, 762 ([[ [{'type': 5, 'timestamp': 0, 'data': { 763 'n': 0x20, 764 }}] ]]):gsub('\n', '') 765 ) 766 sd2strings_eq( 767 { 768 'Register with timestamp ' .. epoch .. ':', 769 ' % Key Description Value', 770 " + n name ' '", 771 ' + rc contents ["abc", "def"]', 772 ' + rw block width 0', 773 ' + rt type CHARACTERWISE', 774 ' + ru is_unnamed FALSE', 775 }, 776 ([[ [{'type': 5, 'timestamp': 0, 'data': { 777 'n': 0x20, 778 'rc': ["abc", "def"], 779 'ru': {'_TYPE': v:msgpack_types.boolean, '_VAL': 0}, 780 }}] ]]):gsub('\n', '') 781 ) 782 sd2strings_eq( 783 { 784 'Register with timestamp ' .. epoch .. ':', 785 ' % Key Description Value', 786 " + n name ' '", 787 ' + rc contents @', 788 ' | - "abcdefghijklmnopqrstuvwxyz"', 789 ' | - "abcdefghijklmnopqrstuvwxyz"', 790 ' + rw block width 0', 791 ' + rt type CHARACTERWISE', 792 ' + ru is_unnamed TRUE', 793 }, 794 ([[ [{'type': 5, 'timestamp': 0, 'data': { 795 'n': 0x20, 796 'rc': ['abcdefghijklmnopqrstuvwxyz', 'abcdefghijklmnopqrstuvwxyz'], 797 'ru': {'_TYPE': v:msgpack_types.boolean, '_VAL': 1}, 798 }}] ]]):gsub('\n', '') 799 ) 800 sd2strings_eq( 801 { 802 'Register with timestamp ' .. epoch .. ':', 803 ' % Key Description Value', 804 " + n name ' '", 805 ' + rc contents @', 806 ' | - "abcdefghijklmnopqrstuvwxyz"', 807 ' | - "abcdefghijklmnopqrstuvwxyz"', 808 ' + rw block width 0', 809 ' + rt type CHARACTERWISE', 810 ' + ru is_unnamed FALSE', 811 }, 812 ([[ [{'type': 5, 'timestamp': 0, 'data': { 813 'n': 0x20, 814 'rc': ['abcdefghijklmnopqrstuvwxyz', 'abcdefghijklmnopqrstuvwxyz'], 815 'rw': 0, 816 'rt': 0, 817 }}] ]]):gsub('\n', '') 818 ) 819 sd2strings_eq( 820 { 821 'Register with timestamp ' .. epoch .. ':', 822 ' % Key Description Value', 823 " + n name ' '", 824 ' + rc contents @', 825 ' | - "abcdefghijklmnopqrstuvwxyz"', 826 ' | - "abcdefghijklmnopqrstuvwxyz"', 827 ' + rw block width 5', 828 ' + rt type LINEWISE', 829 ' + ru is_unnamed FALSE', 830 }, 831 ([[ [{'type': 5, 'timestamp': 0, 'data': { 832 'n': 0x20, 833 'rc': ['abcdefghijklmnopqrstuvwxyz', 'abcdefghijklmnopqrstuvwxyz'], 834 'rw': 5, 835 'rt': 1, 836 }}] ]]):gsub('\n', '') 837 ) 838 sd2strings_eq( 839 { 840 'Register with timestamp ' .. epoch .. ':', 841 ' % Key Description Value', 842 " + n name ' '", 843 ' + rc contents @', 844 ' | - "abcdefghijklmnopqrstuvwxyz"', 845 ' | - "abcdefghijklmnopqrstuvwxyz"', 846 ' # Expected integer', 847 ' + rw block width ""', 848 ' + rt type BLOCKWISE', 849 ' # Expected boolean', 850 ' + ru is_unnamed ""', 851 }, 852 ([[ [{'type': 5, 'timestamp': 0, 'data': { 853 'n': 0x20, 854 'rc': ['abcdefghijklmnopqrstuvwxyz', 'abcdefghijklmnopqrstuvwxyz'], 855 'rw': "", 856 'rt': 2, 857 'ru': "" 858 }}] ]]):gsub('\n', '') 859 ) 860 sd2strings_eq( 861 { 862 'Register with timestamp ' .. epoch .. ':', 863 ' % Key Description Value', 864 " + n name ' '", 865 ' # Expected array value', 866 ' + rc contents 0', 867 ' # Value is negative', 868 ' + rw block width -1', 869 ' # Unexpected enum value: expected one of 0 (CHARACTERWISE), ' 870 .. '1 (LINEWISE), 2 (BLOCKWISE)', 871 ' + rt type 10', 872 ' # Expected boolean', 873 ' + ru is_unnamed ["abc", "def"]', 874 }, 875 ([[ [{'type': 5, 'timestamp': 0, 'data': { 876 'n': 0x20, 877 'rc': 0, 878 'rw': -1, 879 'rt': 10, 880 'ru': ['abc', 'def'], 881 }}] ]]):gsub('\n', '') 882 ) 883 sd2strings_eq( 884 { 885 'Register with timestamp ' .. epoch .. ':', 886 ' % Key Description Value', 887 " + n name ' '", 888 ' + rc contents @', 889 ' | - "abcdefghijklmnopqrstuvwxyz"', 890 ' | - "abcdefghijklmnopqrstuvwxyz"', 891 ' + rw block width 5', 892 ' + rt type LINEWISE', 893 ' # Expected boolean', 894 ' + ru is_unnamed 0', 895 }, 896 ([[ [{'type': 5, 'timestamp': 0, 'data': { 897 'n': 0x20, 898 'rc': ['abcdefghijklmnopqrstuvwxyz', 'abcdefghijklmnopqrstuvwxyz'], 899 'rw': 5, 900 'rt': 1, 901 'ru': 0, 902 }}] ]]):gsub('\n', '') 903 ) 904 end) 905 906 it('works with variable items', function() 907 sd2strings_eq({ 908 'Variable with timestamp ' .. epoch .. ':', 909 ' # Unexpected type: map instead of array', 910 ' = {"a": [10]}', 911 }, { { type = 6, timestamp = 0, data = { a = { 10 } } } }) 912 sd2strings_eq( 913 { 914 'Variable with timestamp ' .. epoch .. ':', 915 ' @ Description Value', 916 ' # Expected more elements in list', 917 }, 918 ([[ [{'type': 6, 'timestamp': 0, 'data': [ 919 ]}] ]]):gsub('\n', '') 920 ) 921 sd2strings_eq( 922 { 923 'Variable with timestamp ' .. epoch .. ':', 924 ' @ Description Value', 925 ' # Expected binary string', 926 ' - name 1', 927 ' # Expected more elements in list', 928 }, 929 ([[ [{'type': 6, 'timestamp': 0, 'data': [ 930 1 931 ]}] ]]):gsub('\n', '') 932 ) 933 sd2strings_eq( 934 { 935 'Variable with timestamp ' .. epoch .. ':', 936 ' @ Description Value', 937 ' # Expected no NUL bytes', 938 ' - name "\\0"', 939 ' # Expected more elements in list', 940 }, 941 ([[ [{'type': 6, 'timestamp': 0, 'data': [ 942 {'_TYPE': v:msgpack_types.string, '_VAL': ["\n"]}, 943 ]}] ]]):gsub('\n', '') 944 ) 945 sd2strings_eq( 946 { 947 'Variable with timestamp ' .. epoch .. ':', 948 ' @ Description Value', 949 ' - name "foo"', 950 ' # Expected more elements in list', 951 }, 952 ([[ [{'type': 6, 'timestamp': 0, 'data': [ 953 {'_TYPE': v:msgpack_types.string, '_VAL': ["foo"]}, 954 ]}] ]]):gsub('\n', '') 955 ) 956 sd2strings_eq( 957 { 958 'Variable with timestamp ' .. epoch .. ':', 959 ' @ Description Value', 960 ' - name "foo"', 961 ' - value NIL', 962 }, 963 ([[ [{'type': 6, 'timestamp': 0, 'data': [ 964 {'_TYPE': v:msgpack_types.string, '_VAL': ["foo"]}, 965 {'_TYPE': v:msgpack_types.nil, '_VAL': ["foo"]}, 966 ]}] ]]):gsub('\n', '') 967 ) 968 sd2strings_eq( 969 { 970 'Variable with timestamp ' .. epoch .. ':', 971 ' @ Description Value', 972 ' - name "foo"', 973 ' - value NIL', 974 ' - NIL', 975 }, 976 ([[ [{'type': 6, 'timestamp': 0, 'data': [ 977 {'_TYPE': v:msgpack_types.string, '_VAL': ["foo"]}, 978 {'_TYPE': v:msgpack_types.nil, '_VAL': ["foo"]}, 979 {'_TYPE': v:msgpack_types.nil, '_VAL': ["foo"]}, 980 ]}] ]]):gsub('\n', '') 981 ) 982 end) 983 984 it('works with global mark items', function() 985 sd2strings_eq({ 986 'Global mark with timestamp ' .. epoch .. ':', 987 ' # Unexpected type: array instead of map', 988 ' = [1, 2, 3]', 989 }, { { type = 7, timestamp = 0, data = { 1, 2, 3 } } }) 990 sd2strings_eq( 991 { 992 'Global mark with timestamp ' .. epoch .. ':', 993 ' % Key Description Value', 994 ' # Required key missing: n', 995 ' # Required key missing: f', 996 ' + l line number 1', 997 ' + c column 0', 998 }, 999 ([[ [{'type': 7, 'timestamp': 0, 'data': { 1000 }}] ]]):gsub('\n', '') 1001 ) 1002 sd2strings_eq( 1003 { 1004 'Global mark with timestamp ' .. epoch .. ':', 1005 ' % Key Description Value', 1006 ' # Expected integer', 1007 ' + n name "foo"', 1008 ' # Required key missing: f', 1009 ' + l line number 1', 1010 ' + c column 0', 1011 }, 1012 ([[ [{'type': 7, 'timestamp': 0, 'data': { 1013 'n': 'foo', 1014 }}] ]]):gsub('\n', '') 1015 ) 1016 sd2strings_eq( 1017 { 1018 'Global mark with timestamp ' .. epoch .. ':', 1019 ' % Key Description Value', 1020 ' # Required key missing: n', 1021 ' + f file name "foo"', 1022 ' + l line number 1', 1023 ' + c column 0', 1024 }, 1025 ([[ [{'type': 7, 'timestamp': 0, 'data': { 1026 'f': 'foo', 1027 }}] ]]):gsub('\n', '') 1028 ) 1029 sd2strings_eq( 1030 { 1031 'Global mark with timestamp ' .. epoch .. ':', 1032 ' % Key Description Value', 1033 ' # Value is negative', 1034 ' + n name -10', 1035 ' # Expected no NUL bytes', 1036 ' + f file name "\\0"', 1037 ' + l line number 1', 1038 ' + c column 0', 1039 }, 1040 ([[ [{'type': 7, 'timestamp': 0, 'data': { 1041 'n': -10, 1042 'f': {'_TYPE': v:msgpack_types.string, '_VAL': ["\n"]}, 1043 }}] ]]):gsub('\n', '') 1044 ) 1045 sd2strings_eq( 1046 { 1047 'Global mark with timestamp ' .. epoch .. ':', 1048 ' % Key Description Value', 1049 " + n name '\\20'", 1050 ' + f file name "foo"', 1051 ' # Value is negative', 1052 ' + l line number -10', 1053 ' # Value is negative', 1054 ' + c column -10', 1055 }, 1056 ([[ [{'type': 7, 'timestamp': 0, 'data': { 1057 'n': 20, 1058 'f': 'foo', 1059 'l': -10, 1060 'c': -10, 1061 }}] ]]):gsub('\n', '') 1062 ) 1063 sd2strings_eq( 1064 { 1065 'Global mark with timestamp ' .. epoch .. ':', 1066 ' % Key Description Value', 1067 ' + n name 128', 1068 ' + f file name "foo"', 1069 ' + l line number 1', 1070 ' + c column 0', 1071 }, 1072 ([[ [{'type': 7, 'timestamp': 0, 'data': { 1073 'n': 128, 1074 'f': 'foo', 1075 }}] ]]):gsub('\n', '') 1076 ) 1077 sd2strings_eq( 1078 { 1079 'Global mark with timestamp ' .. epoch .. ':', 1080 ' % Key Description Value', 1081 " + n name '\\20'", 1082 ' + f file name "foo"', 1083 ' # Expected integer', 1084 ' + l line number "FOO"', 1085 ' # Expected integer', 1086 ' + c column "foo"', 1087 ' + mX 10', 1088 }, 1089 ([[ [{'type': 7, 'timestamp': 0, 'data': { 1090 'n': 20, 1091 'f': 'foo', 1092 'l': 'FOO', 1093 'c': 'foo', 1094 'mX': 10, 1095 }}] ]]):gsub('\n', '') 1096 ) 1097 sd2strings_eq( 1098 { 1099 'Global mark with timestamp ' .. epoch .. ':', 1100 ' % Key________ Description Value', 1101 " + n name 'A'", 1102 ' + f file name "foo"', 1103 ' + l line number 2', 1104 ' + c column 200', 1105 ' + mX 10', 1106 ' + mYYYYYYYYYY 10', 1107 }, 1108 ([[ [{'type': 7, 'timestamp': 0, 'data': { 1109 'n': char2nr('A'), 1110 'f': 'foo', 1111 'l': 2, 1112 'c': 200, 1113 'mX': 10, 1114 'mYYYYYYYYYY': 10, 1115 }}] ]]):gsub('\n', '') 1116 ) 1117 end) 1118 1119 it('works with jump items', function() 1120 sd2strings_eq({ 1121 'Jump with timestamp ' .. epoch .. ':', 1122 ' # Unexpected type: array instead of map', 1123 ' = [1, 2, 3]', 1124 }, { { type = 8, timestamp = 0, data = { 1, 2, 3 } } }) 1125 sd2strings_eq( 1126 { 1127 'Jump with timestamp ' .. epoch .. ':', 1128 ' % Key Description Value', 1129 ' # Required key missing: f', 1130 ' + l line number 1', 1131 ' + c column 0', 1132 }, 1133 ([[ [{'type': 8, 'timestamp': 0, 'data': { 1134 }}] ]]):gsub('\n', '') 1135 ) 1136 sd2strings_eq( 1137 { 1138 'Jump with timestamp ' .. epoch .. ':', 1139 ' % Key Description Value', 1140 ' # Required key missing: f', 1141 ' + l line number 1', 1142 ' + c column 0', 1143 ' # Expected integer', 1144 ' + n name "foo"', 1145 }, 1146 ([[ [{'type': 8, 'timestamp': 0, 'data': { 1147 'n': 'foo', 1148 }}] ]]):gsub('\n', '') 1149 ) 1150 sd2strings_eq( 1151 { 1152 'Jump with timestamp ' .. epoch .. ':', 1153 ' % Key Description Value', 1154 ' + f file name "foo"', 1155 ' + l line number 1', 1156 ' + c column 0', 1157 }, 1158 ([[ [{'type': 8, 'timestamp': 0, 'data': { 1159 'f': 'foo', 1160 }}] ]]):gsub('\n', '') 1161 ) 1162 sd2strings_eq( 1163 { 1164 'Jump with timestamp ' .. epoch .. ':', 1165 ' % Key Description Value', 1166 ' # Expected no NUL bytes', 1167 ' + f file name "\\0"', 1168 ' + l line number 1', 1169 ' + c column 0', 1170 ' # Value is negative', 1171 ' + n name -10', 1172 }, 1173 ([[ [{'type': 8, 'timestamp': 0, 'data': { 1174 'n': -10, 1175 'f': {'_TYPE': v:msgpack_types.string, '_VAL': ["\n"]}, 1176 }}] ]]):gsub('\n', '') 1177 ) 1178 sd2strings_eq( 1179 { 1180 'Jump with timestamp ' .. epoch .. ':', 1181 ' % Key Description Value', 1182 ' + f file name "foo"', 1183 ' # Value is negative', 1184 ' + l line number -10', 1185 ' # Value is negative', 1186 ' + c column -10', 1187 }, 1188 ([[ [{'type': 8, 'timestamp': 0, 'data': { 1189 'f': 'foo', 1190 'l': -10, 1191 'c': -10, 1192 }}] ]]):gsub('\n', '') 1193 ) 1194 sd2strings_eq( 1195 { 1196 'Jump with timestamp ' .. epoch .. ':', 1197 ' % Key Description Value', 1198 ' + f file name "foo"', 1199 ' # Expected integer', 1200 ' + l line number "FOO"', 1201 ' # Expected integer', 1202 ' + c column "foo"', 1203 ' + mX 10', 1204 }, 1205 ([[ [{'type': 8, 'timestamp': 0, 'data': { 1206 'f': 'foo', 1207 'l': 'FOO', 1208 'c': 'foo', 1209 'mX': 10, 1210 }}] ]]):gsub('\n', '') 1211 ) 1212 sd2strings_eq( 1213 { 1214 'Jump with timestamp ' .. epoch .. ':', 1215 ' % Key________ Description Value', 1216 ' + f file name "foo"', 1217 ' + l line number 2', 1218 ' + c column 200', 1219 ' + mX 10', 1220 ' + mYYYYYYYYYY 10', 1221 " + n name ' '", 1222 }, 1223 ([[ [{'type': 8, 'timestamp': 0, 'data': { 1224 'n': 0x20, 1225 'f': 'foo', 1226 'l': 2, 1227 'c': 200, 1228 'mX': 10, 1229 'mYYYYYYYYYY': 10, 1230 }}] ]]):gsub('\n', '') 1231 ) 1232 end) 1233 1234 it('works with buffer list items', function() 1235 sd2strings_eq({ 1236 'Buffer list with timestamp ' .. epoch .. ':', 1237 ' # Unexpected type: map instead of array', 1238 ' = {"a": [10]}', 1239 }, { { type = 9, timestamp = 0, data = { a = { 10 } } } }) 1240 sd2strings_eq({ 1241 'Buffer list with timestamp ' .. epoch .. ':', 1242 ' # Expected array of maps', 1243 ' = [[], []]', 1244 }, { { type = 9, timestamp = 0, data = { {}, {} } } }) 1245 sd2strings_eq({ 1246 'Buffer list with timestamp ' .. epoch .. ':', 1247 ' # Expected array of maps', 1248 ' = [{"a": 10}, []]', 1249 }, { { type = 9, timestamp = 0, data = { { a = 10 }, {} } } }) 1250 sd2strings_eq({ 1251 'Buffer list with timestamp ' .. epoch .. ':', 1252 ' % Key Description Value', 1253 ' # Required key missing: f', 1254 ' + l line number 1', 1255 ' + c column 0', 1256 ' + a 10', 1257 }, { { type = 9, timestamp = 0, data = { { a = 10 } } } }) 1258 sd2strings_eq({ 1259 'Buffer list with timestamp ' .. epoch .. ':', 1260 ' % Key Description Value', 1261 ' # Required key missing: f', 1262 ' # Expected integer', 1263 ' + l line number "10"', 1264 ' # Expected integer', 1265 ' + c column "10"', 1266 ' + a 10', 1267 }, { { type = 9, timestamp = 0, data = { { l = '10', c = '10', a = 10 } } } }) 1268 sd2strings_eq({ 1269 'Buffer list with timestamp ' .. epoch .. ':', 1270 ' % Key Description Value', 1271 ' # Required key missing: f', 1272 ' + l line number 10', 1273 ' + c column 10', 1274 ' + a 10', 1275 }, { { type = 9, timestamp = 0, data = { { l = 10, c = 10, a = 10 } } } }) 1276 sd2strings_eq({ 1277 'Buffer list with timestamp ' .. epoch .. ':', 1278 ' % Key Description Value', 1279 ' # Required key missing: f', 1280 ' # Value is negative', 1281 ' + l line number -10', 1282 ' # Value is negative', 1283 ' + c column -10', 1284 }, { { type = 9, timestamp = 0, data = { { l = -10, c = -10 } } } }) 1285 sd2strings_eq({ 1286 'Buffer list with timestamp ' .. epoch .. ':', 1287 ' % Key Description Value', 1288 ' + f file name "abc"', 1289 ' + l line number 1', 1290 ' + c column 0', 1291 }, { { type = 9, timestamp = 0, data = { { f = 'abc' } } } }) 1292 sd2strings_eq({ 1293 'Buffer list with timestamp ' .. epoch .. ':', 1294 ' % Key Description Value', 1295 ' # Expected binary string', 1296 ' + f file name 10', 1297 ' + l line number 1', 1298 ' + c column 0', 1299 '', 1300 ' % Key Description Value', 1301 ' # Expected binary string', 1302 ' + f file name 20', 1303 ' + l line number 1', 1304 ' + c column 0', 1305 }, { { type = 9, timestamp = 0, data = { { f = 10 }, { f = 20 } } } }) 1306 sd2strings_eq( 1307 { 1308 'Buffer list with timestamp ' .. epoch .. ':', 1309 ' % Key Description Value', 1310 ' # Expected binary string', 1311 ' + f file name 10', 1312 ' + l line number 1', 1313 ' + c column 0', 1314 '', 1315 ' % Key Description Value', 1316 ' # Expected no NUL bytes', 1317 ' + f file name "\\0"', 1318 ' + l line number 1', 1319 ' + c column 0', 1320 }, 1321 ([[ [{'type': 9, 'timestamp': 0, 'data': [ 1322 {'f': 10}, 1323 {'f': {'_TYPE': v:msgpack_types.string, '_VAL': ["\n"]}}, 1324 ]}] ]]):gsub('\n', '') 1325 ) 1326 end) 1327 1328 it('works with local mark items', function() 1329 sd2strings_eq({ 1330 'Local mark with timestamp ' .. epoch .. ':', 1331 ' # Unexpected type: array instead of map', 1332 ' = [1, 2, 3]', 1333 }, { { type = 10, timestamp = 0, data = { 1, 2, 3 } } }) 1334 sd2strings_eq( 1335 { 1336 'Local mark with timestamp ' .. epoch .. ':', 1337 ' % Key Description Value', 1338 ' # Required key missing: f', 1339 " + n name '\"'", 1340 ' + l line number 1', 1341 ' + c column 0', 1342 }, 1343 ([[ [{'type': 10, 'timestamp': 0, 'data': { 1344 }}] ]]):gsub('\n', '') 1345 ) 1346 sd2strings_eq( 1347 { 1348 'Local mark with timestamp ' .. epoch .. ':', 1349 ' % Key Description Value', 1350 ' # Required key missing: f', 1351 ' # Expected integer', 1352 ' + n name "foo"', 1353 ' + l line number 1', 1354 ' + c column 0', 1355 }, 1356 ([[ [{'type': 10, 'timestamp': 0, 'data': { 1357 'n': 'foo', 1358 }}] ]]):gsub('\n', '') 1359 ) 1360 sd2strings_eq( 1361 { 1362 'Local mark with timestamp ' .. epoch .. ':', 1363 ' % Key Description Value', 1364 ' + f file name "foo"', 1365 " + n name '\"'", 1366 ' + l line number 1', 1367 ' + c column 0', 1368 }, 1369 ([[ [{'type': 10, 'timestamp': 0, 'data': { 1370 'f': 'foo', 1371 }}] ]]):gsub('\n', '') 1372 ) 1373 sd2strings_eq( 1374 { 1375 'Local mark with timestamp ' .. epoch .. ':', 1376 ' % Key Description Value', 1377 ' # Expected no NUL bytes', 1378 ' + f file name "\\0"', 1379 ' # Value is negative', 1380 ' + n name -10', 1381 ' + l line number 1', 1382 ' + c column 0', 1383 }, 1384 ([[ [{'type': 10, 'timestamp': 0, 'data': { 1385 'n': -10, 1386 'f': {'_TYPE': v:msgpack_types.string, '_VAL': ["\n"]}, 1387 }}] ]]):gsub('\n', '') 1388 ) 1389 sd2strings_eq( 1390 { 1391 'Local mark with timestamp ' .. epoch .. ':', 1392 ' % Key Description Value', 1393 ' + f file name "foo"', 1394 " + n name '\\20'", 1395 ' # Value is negative', 1396 ' + l line number -10', 1397 ' # Value is negative', 1398 ' + c column -10', 1399 }, 1400 ([[ [{'type': 10, 'timestamp': 0, 'data': { 1401 'n': 20, 1402 'f': 'foo', 1403 'l': -10, 1404 'c': -10, 1405 }}] ]]):gsub('\n', '') 1406 ) 1407 sd2strings_eq( 1408 { 1409 'Local mark with timestamp ' .. epoch .. ':', 1410 ' % Key Description Value', 1411 ' + f file name "foo"', 1412 " + n name '\\20'", 1413 ' # Expected integer', 1414 ' + l line number "FOO"', 1415 ' # Expected integer', 1416 ' + c column "foo"', 1417 ' + mX 10', 1418 }, 1419 ([[ [{'type': 10, 'timestamp': 0, 'data': { 1420 'n': 20, 1421 'f': 'foo', 1422 'l': 'FOO', 1423 'c': 'foo', 1424 'mX': 10, 1425 }}] ]]):gsub('\n', '') 1426 ) 1427 sd2strings_eq( 1428 { 1429 'Local mark with timestamp ' .. epoch .. ':', 1430 ' % Key________ Description Value', 1431 ' + f file name "foo"', 1432 " + n name 'a'", 1433 ' + l line number 2', 1434 ' + c column 200', 1435 ' + mX 10', 1436 ' + mYYYYYYYYYY 10', 1437 }, 1438 ([[ [{'type': 10, 'timestamp': 0, 'data': { 1439 'n': char2nr('a'), 1440 'f': 'foo', 1441 'l': 2, 1442 'c': 200, 1443 'mX': 10, 1444 'mYYYYYYYYYY': 10, 1445 }}] ]]):gsub('\n', '') 1446 ) 1447 end) 1448 1449 it('works with change items', function() 1450 sd2strings_eq({ 1451 'Change with timestamp ' .. epoch .. ':', 1452 ' # Unexpected type: array instead of map', 1453 ' = [1, 2, 3]', 1454 }, { { type = 11, timestamp = 0, data = { 1, 2, 3 } } }) 1455 sd2strings_eq( 1456 { 1457 'Change with timestamp ' .. epoch .. ':', 1458 ' % Key Description Value', 1459 ' # Required key missing: f', 1460 ' + l line number 1', 1461 ' + c column 0', 1462 }, 1463 ([[ [{'type': 11, 'timestamp': 0, 'data': { 1464 }}] ]]):gsub('\n', '') 1465 ) 1466 sd2strings_eq( 1467 { 1468 'Change with timestamp ' .. epoch .. ':', 1469 ' % Key Description Value', 1470 ' # Required key missing: f', 1471 ' + l line number 1', 1472 ' + c column 0', 1473 ' # Expected integer', 1474 ' + n name "foo"', 1475 }, 1476 ([[ [{'type': 11, 'timestamp': 0, 'data': { 1477 'n': 'foo', 1478 }}] ]]):gsub('\n', '') 1479 ) 1480 sd2strings_eq( 1481 { 1482 'Change with timestamp ' .. epoch .. ':', 1483 ' % Key Description Value', 1484 ' + f file name "foo"', 1485 ' + l line number 1', 1486 ' + c column 0', 1487 }, 1488 ([[ [{'type': 11, 'timestamp': 0, 'data': { 1489 'f': 'foo', 1490 }}] ]]):gsub('\n', '') 1491 ) 1492 sd2strings_eq( 1493 { 1494 'Change with timestamp ' .. epoch .. ':', 1495 ' % Key Description Value', 1496 ' # Expected no NUL bytes', 1497 ' + f file name "\\0"', 1498 ' + l line number 1', 1499 ' + c column 0', 1500 ' # Value is negative', 1501 ' + n name -10', 1502 }, 1503 ([[ [{'type': 11, 'timestamp': 0, 'data': { 1504 'n': -10, 1505 'f': {'_TYPE': v:msgpack_types.string, '_VAL': ["\n"]}, 1506 }}] ]]):gsub('\n', '') 1507 ) 1508 sd2strings_eq( 1509 { 1510 'Change with timestamp ' .. epoch .. ':', 1511 ' % Key Description Value', 1512 ' + f file name "foo"', 1513 ' # Value is negative', 1514 ' + l line number -10', 1515 ' # Value is negative', 1516 ' + c column -10', 1517 }, 1518 ([[ [{'type': 11, 'timestamp': 0, 'data': { 1519 'f': 'foo', 1520 'l': -10, 1521 'c': -10, 1522 }}] ]]):gsub('\n', '') 1523 ) 1524 sd2strings_eq( 1525 { 1526 'Change with timestamp ' .. epoch .. ':', 1527 ' % Key Description Value', 1528 ' + f file name "foo"', 1529 ' # Expected integer', 1530 ' + l line number "FOO"', 1531 ' # Expected integer', 1532 ' + c column "foo"', 1533 ' + mX 10', 1534 }, 1535 ([[ [{'type': 11, 'timestamp': 0, 'data': { 1536 'f': 'foo', 1537 'l': 'FOO', 1538 'c': 'foo', 1539 'mX': 10, 1540 }}] ]]):gsub('\n', '') 1541 ) 1542 sd2strings_eq( 1543 { 1544 'Change with timestamp ' .. epoch .. ':', 1545 ' % Key________ Description Value', 1546 ' + f file name "foo"', 1547 ' + l line number 2', 1548 ' + c column 200', 1549 ' + mX 10', 1550 ' + mYYYYYYYYYY 10', 1551 " + n name ' '", 1552 }, 1553 ([[ [{'type': 11, 'timestamp': 0, 'data': { 1554 'n': 0x20, 1555 'f': 'foo', 1556 'l': 2, 1557 'c': 200, 1558 'mX': 10, 1559 'mYYYYYYYYYY': 10, 1560 }}] ]]):gsub('\n', '') 1561 ) 1562 end) 1563 end) 1564 1565 describe('function shada#get_strings', function() 1566 it('works', function() 1567 eq({ 1568 'Header with timestamp ' .. epoch .. ':', 1569 ' % Key Value', 1570 }, nvim_eval('shada#get_strings(msgpackdump([1, 0, 0, {}]))')) 1571 end) 1572 end) 1573 1574 describe('function shada#strings_to_sd', function() 1575 local strings2sd_eq = function(expected, input) 1576 api.nvim_set_var('__input', input) 1577 nvim_command( 1578 'let g:__actual = map(shada#strings_to_sd(g:__input), ' 1579 .. '"filter(v:val, \\"v:key[0] isnot# \'_\' ' 1580 .. '&& v:key isnot# \'length\'\\")")' 1581 ) 1582 -- print() 1583 if type(expected) == 'table' then 1584 api.nvim_set_var('__expected', expected) 1585 nvim_command('let g:__expected = ModifyVal(g:__expected)') 1586 expected = 'g:__expected' 1587 -- print(nvim_eval('msgpack#string(g:__expected)')) 1588 end 1589 -- print(nvim_eval('msgpack#string(g:__actual)')) 1590 eq(1, nvim_eval(('msgpack#equal(%s, g:__actual)'):format(expected))) 1591 if type(expected) == 'table' then 1592 nvim_command('unlet g:__expected') 1593 end 1594 nvim_command('unlet g:__input') 1595 nvim_command('unlet g:__actual') 1596 end 1597 1598 it('works with multiple items', function() 1599 strings2sd_eq({ 1600 { 1601 type = 11, 1602 timestamp = 0, 1603 data = { 1604 f = 'foo', 1605 l = 2, 1606 c = 200, 1607 mX = 10, 1608 mYYYYYYYYYY = 10, 1609 n = (' '):byte(), 1610 }, 1611 }, 1612 { 1613 type = 1, 1614 timestamp = 0, 1615 data = { 1616 c = 'abc', 1617 f = { '!string', { 'abc\ndef' } }, 1618 l = -10, 1619 n = -64, 1620 rc = '10', 1621 rt = 10, 1622 sc = { '!nil', 0 }, 1623 sm = 'TRUE', 1624 so = 'TRUE', 1625 sp = { '!string', { 'abc' } }, 1626 }, 1627 }, 1628 }, { 1629 'Change with timestamp ' .. epoch .. ':', 1630 ' % Key________ Description Value', 1631 ' + f file name "foo"', 1632 ' + l line number 2', 1633 ' + c column 200', 1634 ' + mX 10', 1635 ' + mYYYYYYYYYY 10', 1636 " + n name ' '", 1637 'Header with timestamp ' .. epoch .. ':', 1638 ' % Key Description____ Value', 1639 ' # Expected integer', 1640 ' + c column "abc"', 1641 ' # Expected no NUL bytes', 1642 ' + f file name "abc\\0def"', 1643 ' # Value is negative', 1644 ' + l line number -10', 1645 ' # Value is negative', 1646 ' + n name -64', 1647 ' # Expected array value', 1648 ' + rc contents "10"', 1649 ' # Unexpected enum value: expected one of ' 1650 .. '0 (CHARACTERWISE), 1 (LINEWISE), 2 (BLOCKWISE)', 1651 ' + rt type 10', 1652 ' # Expected boolean', 1653 ' + sc smartcase value NIL', 1654 ' # Expected boolean', 1655 ' + sm magic value "TRUE"', 1656 ' # Expected integer', 1657 ' + so offset value "TRUE"', 1658 ' # Expected binary string', 1659 ' + sp pattern ="abc"', 1660 }) 1661 end) 1662 1663 it('works with empty list', function() 1664 strings2sd_eq({}, {}) 1665 end) 1666 1667 it('works with header items', function() 1668 strings2sd_eq({ { type = 1, timestamp = 0, data = { 1669 generator = 'test', 1670 } } }, { 1671 'Header with timestamp ' .. epoch .. ':', 1672 ' % Key______ Value', 1673 ' + generator "test"', 1674 }) 1675 strings2sd_eq( 1676 { { type = 1, timestamp = 0, data = { 1677 1, 1678 2, 1679 3, 1680 } } }, 1681 { 1682 'Header with timestamp ' .. epoch .. ':', 1683 ' # Unexpected type: array instead of map', 1684 ' = [1, 2, 3]', 1685 } 1686 ) 1687 strings2sd_eq({ 1688 { 1689 type = 1, 1690 timestamp = 0, 1691 data = { 1692 a = 1, 1693 b = 2, 1694 c = 3, 1695 d = 4, 1696 }, 1697 }, 1698 }, { 1699 'Header with timestamp ' .. epoch .. ':', 1700 ' % Key Description Value', 1701 ' + a 1', 1702 ' + b 2', 1703 ' + c column 3', 1704 ' + d 4', 1705 }) 1706 strings2sd_eq({ 1707 { 1708 type = 1, 1709 timestamp = 0, 1710 data = { 1711 c = 'abc', 1712 f = { '!string', { 'abc\ndef' } }, 1713 l = -10, 1714 n = -64, 1715 rc = '10', 1716 rt = 10, 1717 sc = { '!nil', 0 }, 1718 sm = 'TRUE', 1719 so = 'TRUE', 1720 sp = { '!string', { 'abc' } }, 1721 }, 1722 }, 1723 }, { 1724 'Header with timestamp ' .. epoch .. ':', 1725 ' % Key Description____ Value', 1726 ' # Expected integer', 1727 ' + c column "abc"', 1728 ' # Expected no NUL bytes', 1729 ' + f file name "abc\\0def"', 1730 ' # Value is negative', 1731 ' + l line number -10', 1732 ' # Value is negative', 1733 ' + n name -64', 1734 ' # Expected array value', 1735 ' + rc contents "10"', 1736 ' # Unexpected enum value: expected one of ' 1737 .. '0 (CHARACTERWISE), 1 (LINEWISE), 2 (BLOCKWISE)', 1738 ' + rt type 10', 1739 ' # Expected boolean', 1740 ' + sc smartcase value NIL', 1741 ' # Expected boolean', 1742 ' + sm magic value "TRUE"', 1743 ' # Expected integer', 1744 ' + so offset value "TRUE"', 1745 ' # Expected binary string', 1746 ' + sp pattern ="abc"', 1747 }) 1748 end) 1749 1750 it('works with search pattern items', function() 1751 strings2sd_eq( 1752 { { type = 2, timestamp = 0, data = { 1753 1, 1754 2, 1755 3, 1756 } } }, 1757 { 1758 'Search pattern with timestamp ' .. epoch .. ':', 1759 ' # Unexpected type: array instead of map', 1760 ' = [1, 2, 3]', 1761 } 1762 ) 1763 strings2sd_eq({ { type = 2, timestamp = 0, data = { 1764 sp = 'abc', 1765 } } }, { 1766 'Search pattern with timestamp ' .. epoch .. ':', 1767 ' % Key Description________ Value', 1768 ' + sp pattern "abc"', 1769 ' + sh v:hlsearch value FALSE', 1770 ' + ss is :s pattern FALSE', 1771 ' + sm magic value TRUE', 1772 ' + sc smartcase value FALSE', 1773 ' + sl has line offset FALSE', 1774 ' + se place cursor at end FALSE', 1775 ' + so offset value 0', 1776 ' + su is last used TRUE', 1777 }) 1778 strings2sd_eq({ 1779 { 1780 type = 2, 1781 timestamp = 0, 1782 data = { 1783 sp = 'abc', 1784 sX = { '!nil', 0 }, 1785 sY = { '!nil', 0 }, 1786 sZ = { '!nil', 0 }, 1787 }, 1788 }, 1789 }, { 1790 'Search pattern with timestamp ' .. epoch .. ':', 1791 ' % Key Description________ Value', 1792 ' + sp pattern "abc"', 1793 ' + sh v:hlsearch value FALSE', 1794 ' + ss is :s pattern FALSE', 1795 ' + sm magic value TRUE', 1796 ' + sc smartcase value FALSE', 1797 ' + sl has line offset FALSE', 1798 ' + se place cursor at end FALSE', 1799 ' + so offset value 0', 1800 ' + su is last used TRUE', 1801 ' + sX NIL', 1802 ' + sY NIL', 1803 ' + sZ NIL', 1804 }) 1805 strings2sd_eq({ { type = 2, timestamp = 0, data = { '!map', {} } } }, { 1806 'Search pattern with timestamp ' .. epoch .. ':', 1807 ' % Key Description________ Value', 1808 ' # Required key missing: sp', 1809 ' + sh v:hlsearch value FALSE', 1810 ' + ss is :s pattern FALSE', 1811 ' + sm magic value TRUE', 1812 ' + sc smartcase value FALSE', 1813 ' + sl has line offset FALSE', 1814 ' + se place cursor at end FALSE', 1815 ' + so offset value 0', 1816 ' + su is last used TRUE', 1817 }) 1818 strings2sd_eq({ 1819 { 1820 type = 2, 1821 timestamp = 0, 1822 data = { 1823 sp = '', 1824 sh = { '!boolean', 1 }, 1825 ss = { '!boolean', 1 }, 1826 sc = { '!boolean', 1 }, 1827 sl = { '!boolean', 1 }, 1828 se = { '!boolean', 1 }, 1829 sm = { '!boolean', 0 }, 1830 su = { '!boolean', 0 }, 1831 so = -10, 1832 }, 1833 }, 1834 }, { 1835 'Search pattern with timestamp ' .. epoch .. ':', 1836 ' % Key Description________ Value', 1837 ' + sp pattern ""', 1838 ' + sh v:hlsearch value TRUE', 1839 ' + ss is :s pattern TRUE', 1840 ' + sm magic value FALSE', 1841 ' + sc smartcase value TRUE', 1842 ' + sl has line offset TRUE', 1843 ' + se place cursor at end TRUE', 1844 ' + so offset value -10', 1845 ' + su is last used FALSE', 1846 }) 1847 strings2sd_eq({ 1848 { 1849 type = 2, 1850 timestamp = 0, 1851 data = { 1852 sp = 0, 1853 sh = 0, 1854 ss = 0, 1855 sc = 0, 1856 sl = 0, 1857 se = 0, 1858 sm = 0, 1859 su = 0, 1860 so = '', 1861 }, 1862 }, 1863 }, { 1864 'Search pattern with timestamp ' .. epoch .. ':', 1865 ' % Key Description________ Value', 1866 ' # Expected binary string', 1867 ' + sp pattern 0', 1868 ' # Expected boolean', 1869 ' + sh v:hlsearch value 0', 1870 ' # Expected boolean', 1871 ' + ss is :s pattern 0', 1872 ' # Expected boolean', 1873 ' + sm magic value 0', 1874 ' # Expected boolean', 1875 ' + sc smartcase value 0', 1876 ' # Expected boolean', 1877 ' + sl has line offset 0', 1878 ' # Expected boolean', 1879 ' + se place cursor at end 0', 1880 ' # Expected integer', 1881 ' + so offset value ""', 1882 ' # Expected boolean', 1883 ' + su is last used 0', 1884 }) 1885 end) 1886 1887 it('works with replacement string items', function() 1888 strings2sd_eq({ { type = 3, timestamp = 0, data = { 1889 a = { 10 }, 1890 } } }, { 1891 'Replacement string with timestamp ' .. epoch .. ':', 1892 ' # Unexpected type: map instead of array', 1893 ' = {"a": [10]}', 1894 }) 1895 strings2sd_eq({ { type = 3, timestamp = 0, data = {} } }, { 1896 'Replacement string with timestamp ' .. epoch .. ':', 1897 ' @ Description__________ Value', 1898 ' # Expected more elements in list', 1899 }) 1900 strings2sd_eq({ { type = 3, timestamp = 0, data = { 1901 0, 1902 } } }, { 1903 'Replacement string with timestamp ' .. epoch .. ':', 1904 ' @ Description__________ Value', 1905 ' # Expected binary string', 1906 ' - :s replacement string 0', 1907 }) 1908 strings2sd_eq( 1909 { { type = 3, timestamp = 0, data = { 1910 'abc\ndef', 1911 0, 1912 } } }, 1913 { 1914 'Replacement string with timestamp ' .. epoch .. ':', 1915 ' @ Description__________ Value', 1916 ' - :s replacement string "abc\\ndef"', 1917 ' - 0', 1918 } 1919 ) 1920 strings2sd_eq({ { type = 3, timestamp = 0, data = { 1921 'abc\ndef', 1922 } } }, { 1923 'Replacement string with timestamp ' .. epoch .. ':', 1924 ' @ Description__________ Value', 1925 ' - :s replacement string "abc\\ndef"', 1926 }) 1927 end) 1928 1929 it('works with history entry items', function() 1930 strings2sd_eq({ { type = 4, timestamp = 0, data = { 1931 a = { 10 }, 1932 } } }, { 1933 'History entry with timestamp ' .. epoch .. ':', 1934 ' # Unexpected type: map instead of array', 1935 ' = {"a": [10]}', 1936 }) 1937 strings2sd_eq({ { type = 4, timestamp = 0, data = {} } }, { 1938 'History entry with timestamp ' .. epoch .. ':', 1939 ' @ Description_ Value', 1940 ' # Expected more elements in list', 1941 }) 1942 strings2sd_eq({ { type = 4, timestamp = 0, data = { 1943 '', 1944 } } }, { 1945 'History entry with timestamp ' .. epoch .. ':', 1946 ' @ Description_ Value', 1947 ' # Expected integer', 1948 ' - history type ""', 1949 ' # Expected more elements in list', 1950 }) 1951 strings2sd_eq({ { type = 4, timestamp = 0, data = { 1952 5, 1953 '', 1954 } } }, { 1955 'History entry with timestamp ' .. epoch .. ':', 1956 ' @ Description_ Value', 1957 ' # Unexpected enum value: expected one of 0 (CMD), 1 (SEARCH), ' 1958 .. '2 (EXPR), 3 (INPUT), 4 (DEBUG)', 1959 ' - history type 5', 1960 ' - contents ""', 1961 }) 1962 strings2sd_eq( 1963 { { type = 4, timestamp = 0, data = { 1964 5, 1965 '', 1966 32, 1967 } } }, 1968 { 1969 'History entry with timestamp ' .. epoch .. ':', 1970 ' @ Description_ Value', 1971 ' # Unexpected enum value: expected one of 0 (CMD), 1 (SEARCH), ' 1972 .. '2 (EXPR), 3 (INPUT), 4 (DEBUG)', 1973 ' - history type 5', 1974 ' - contents ""', 1975 ' - 32', 1976 } 1977 ) 1978 strings2sd_eq( 1979 { { type = 4, timestamp = 0, data = { 1980 0, 1981 '', 1982 32, 1983 } } }, 1984 { 1985 'History entry with timestamp ' .. epoch .. ':', 1986 ' @ Description_ Value', 1987 ' - history type CMD', 1988 ' - contents ""', 1989 ' - 32', 1990 } 1991 ) 1992 strings2sd_eq( 1993 { { type = 4, timestamp = 0, data = { 1994 1, 1995 '', 1996 32, 1997 } } }, 1998 { 1999 'History entry with timestamp ' .. epoch .. ':', 2000 ' @ Description_ Value', 2001 ' - history type SEARCH', 2002 ' - contents ""', 2003 " - separator ' '", 2004 } 2005 ) 2006 strings2sd_eq({ { type = 4, timestamp = 0, data = { 2007 1, 2008 '', 2009 } } }, { 2010 'History entry with timestamp ' .. epoch .. ':', 2011 ' @ Description_ Value', 2012 ' - history type SEARCH', 2013 ' - contents ""', 2014 ' # Expected more elements in list', 2015 }) 2016 strings2sd_eq({ { type = 4, timestamp = 0, data = { 2017 2, 2018 '', 2019 } } }, { 2020 'History entry with timestamp ' .. epoch .. ':', 2021 ' @ Description_ Value', 2022 ' - history type EXPR', 2023 ' - contents ""', 2024 }) 2025 strings2sd_eq({ { type = 4, timestamp = 0, data = { 2026 3, 2027 '', 2028 } } }, { 2029 'History entry with timestamp ' .. epoch .. ':', 2030 ' @ Description_ Value', 2031 ' - history type INPUT', 2032 ' - contents ""', 2033 }) 2034 strings2sd_eq({ { type = 4, timestamp = 0, data = { 2035 4, 2036 '', 2037 } } }, { 2038 'History entry with timestamp ' .. epoch .. ':', 2039 ' @ Description_ Value', 2040 ' - history type DEBUG', 2041 ' - contents ""', 2042 }) 2043 end) 2044 2045 it('works with register items', function() 2046 strings2sd_eq( 2047 { { type = 5, timestamp = 0, data = { 2048 1, 2049 2, 2050 3, 2051 } } }, 2052 { 2053 'Register with timestamp ' .. epoch .. ':', 2054 ' # Unexpected type: array instead of map', 2055 ' = [1, 2, 3]', 2056 } 2057 ) 2058 strings2sd_eq({ { type = 5, timestamp = 0, data = { '!map', {} } } }, { 2059 'Register with timestamp ' .. epoch .. ':', 2060 ' % Key Description Value', 2061 ' # Required key missing: n', 2062 ' # Required key missing: rc', 2063 ' + rw block width 0', 2064 ' + rt type CHARACTERWISE', 2065 }) 2066 strings2sd_eq({ { type = 5, timestamp = 0, data = { 2067 n = (' '):byte(), 2068 } } }, { 2069 'Register with timestamp ' .. epoch .. ':', 2070 ' % Key Description Value', 2071 " + n name ' '", 2072 ' # Required key missing: rc', 2073 ' + rw block width 0', 2074 ' + rt type CHARACTERWISE', 2075 }) 2076 strings2sd_eq({ 2077 { 2078 type = 5, 2079 timestamp = 0, 2080 data = { 2081 n = (' '):byte(), 2082 rc = { 'abc', 'def' }, 2083 }, 2084 }, 2085 }, { 2086 'Register with timestamp ' .. epoch .. ':', 2087 ' % Key Description Value', 2088 " + n name ' '", 2089 ' + rc contents ["abc", "def"]', 2090 ' + rw block width 0', 2091 ' + rt type CHARACTERWISE', 2092 }) 2093 strings2sd_eq({ 2094 { 2095 type = 5, 2096 timestamp = 0, 2097 data = { 2098 n = (' '):byte(), 2099 rc = { 'abcdefghijklmnopqrstuvwxyz', 'abcdefghijklmnopqrstuvwxyz' }, 2100 }, 2101 }, 2102 }, { 2103 'Register with timestamp ' .. epoch .. ':', 2104 ' % Key Description Value', 2105 " + n name ' '", 2106 ' + rc contents @', 2107 ' | - "abcdefghijklmnopqrstuvwxyz"', 2108 ' | - "abcdefghijklmnopqrstuvwxyz"', 2109 ' + rw block width 0', 2110 ' + rt type CHARACTERWISE', 2111 }) 2112 strings2sd_eq({ 2113 { 2114 type = 5, 2115 timestamp = 0, 2116 data = { 2117 n = (' '):byte(), 2118 rc = { 'abcdefghijklmnopqrstuvwxyz', 'abcdefghijklmnopqrstuvwxyz' }, 2119 rw = 5, 2120 rt = 1, 2121 }, 2122 }, 2123 }, { 2124 'Register with timestamp ' .. epoch .. ':', 2125 ' % Key Description Value', 2126 " + n name ' '", 2127 ' + rc contents @', 2128 ' | - "abcdefghijklmnopqrstuvwxyz"', 2129 ' | - "abcdefghijklmnopqrstuvwxyz"', 2130 ' + rw block width 5', 2131 ' + rt type LINEWISE', 2132 }) 2133 strings2sd_eq({ 2134 { 2135 type = 5, 2136 timestamp = 0, 2137 data = { 2138 n = (' '):byte(), 2139 rc = { 'abcdefghijklmnopqrstuvwxyz', 'abcdefghijklmnopqrstuvwxyz' }, 2140 rw = 5, 2141 rt = 2, 2142 }, 2143 }, 2144 }, { 2145 'Register with timestamp ' .. epoch .. ':', 2146 ' % Key Description Value', 2147 " + n name ' '", 2148 ' + rc contents @', 2149 ' | - "abcdefghijklmnopqrstuvwxyz"', 2150 ' | - "abcdefghijklmnopqrstuvwxyz"', 2151 ' + rw block width 5', 2152 ' + rt type BLOCKWISE', 2153 }) 2154 strings2sd_eq({ 2155 { 2156 type = 5, 2157 timestamp = 0, 2158 data = { 2159 n = (' '):byte(), 2160 rc = 0, 2161 rw = -1, 2162 rt = 10, 2163 }, 2164 }, 2165 }, { 2166 'Register with timestamp ' .. epoch .. ':', 2167 ' % Key Description Value', 2168 " + n name ' '", 2169 ' # Expected array value', 2170 ' + rc contents 0', 2171 ' # Value is negative', 2172 ' + rw block width -1', 2173 ' # Unexpected enum value: expected one of 0 (CHARACTERWISE), ' 2174 .. '1 (LINEWISE), 2 (BLOCKWISE)', 2175 ' + rt type 10', 2176 }) 2177 end) 2178 2179 it('works with variable items', function() 2180 strings2sd_eq({ { type = 6, timestamp = 0, data = { 2181 a = { 10 }, 2182 } } }, { 2183 'Variable with timestamp ' .. epoch .. ':', 2184 ' # Unexpected type: map instead of array', 2185 ' = {"a": [10]}', 2186 }) 2187 strings2sd_eq({ { type = 6, timestamp = 0, data = {} } }, { 2188 'Variable with timestamp ' .. epoch .. ':', 2189 ' @ Description Value', 2190 ' # Expected more elements in list', 2191 }) 2192 strings2sd_eq({ { type = 6, timestamp = 0, data = { 2193 'foo', 2194 } } }, { 2195 'Variable with timestamp ' .. epoch .. ':', 2196 ' @ Description Value', 2197 ' - name "foo"', 2198 ' # Expected more elements in list', 2199 }) 2200 strings2sd_eq({ 2201 { 2202 type = 6, 2203 timestamp = 0, 2204 data = { 2205 'foo', 2206 { '!nil', 0 }, 2207 }, 2208 }, 2209 }, { 2210 'Variable with timestamp ' .. epoch .. ':', 2211 ' @ Description Value', 2212 ' - name "foo"', 2213 ' - value NIL', 2214 }) 2215 strings2sd_eq({ 2216 { 2217 type = 6, 2218 timestamp = 0, 2219 data = { 2220 'foo', 2221 { '!nil', 0 }, 2222 { '!nil', 0 }, 2223 }, 2224 }, 2225 }, { 2226 'Variable with timestamp ' .. epoch .. ':', 2227 ' @ Description Value', 2228 ' - name "foo"', 2229 ' - value NIL', 2230 ' - NIL', 2231 }) 2232 end) 2233 2234 it('works with global mark items', function() 2235 strings2sd_eq( 2236 { { type = 7, timestamp = 0, data = { 2237 1, 2238 2, 2239 3, 2240 } } }, 2241 { 2242 'Global mark with timestamp ' .. epoch .. ':', 2243 ' # Unexpected type: array instead of map', 2244 ' = [1, 2, 3]', 2245 } 2246 ) 2247 strings2sd_eq({ 2248 { 2249 type = 7, 2250 timestamp = 0, 2251 data = { 2252 n = ('A'):byte(), 2253 f = 'foo', 2254 l = 2, 2255 c = 200, 2256 mX = 10, 2257 mYYYYYYYYYY = 10, 2258 }, 2259 }, 2260 }, { 2261 'Global mark with timestamp ' .. epoch .. ':', 2262 ' % Key________ Description Value', 2263 " + n name 'A'", 2264 ' + f file name "foo"', 2265 ' + l line number 2', 2266 ' + c column 200', 2267 ' + mX 10', 2268 ' + mYYYYYYYYYY 10', 2269 }) 2270 end) 2271 2272 it('works with jump items', function() 2273 strings2sd_eq( 2274 { { type = 8, timestamp = 0, data = { 2275 1, 2276 2, 2277 3, 2278 } } }, 2279 { 2280 'Jump with timestamp ' .. epoch .. ':', 2281 ' # Unexpected type: array instead of map', 2282 ' = [1, 2, 3]', 2283 } 2284 ) 2285 strings2sd_eq({ 2286 { 2287 type = 8, 2288 timestamp = 0, 2289 data = { 2290 n = ('A'):byte(), 2291 f = 'foo', 2292 l = 2, 2293 c = 200, 2294 mX = 10, 2295 mYYYYYYYYYY = 10, 2296 }, 2297 }, 2298 }, { 2299 'Jump with timestamp ' .. epoch .. ':', 2300 ' % Key________ Description Value', 2301 " + n name 'A'", 2302 ' + f file name "foo"', 2303 ' + l line number 2', 2304 ' + c column 200', 2305 ' + mX 10', 2306 ' + mYYYYYYYYYY 10', 2307 }) 2308 end) 2309 2310 it('works with buffer list items', function() 2311 strings2sd_eq({ { type = 9, timestamp = 0, data = { 2312 a = { 10 }, 2313 } } }, { 2314 'Buffer list with timestamp ' .. epoch .. ':', 2315 ' # Unexpected type: map instead of array', 2316 ' = {"a": [10]}', 2317 }) 2318 strings2sd_eq( 2319 { { type = 9, timestamp = 0, data = { 2320 { a = 10 }, 2321 {}, 2322 } } }, 2323 { 2324 'Buffer list with timestamp ' .. epoch .. ':', 2325 ' # Expected array of maps', 2326 ' = [{"a": 10}, []]', 2327 } 2328 ) 2329 strings2sd_eq({ { type = 9, timestamp = 0, data = { 2330 { a = 10 }, 2331 } } }, { 2332 'Buffer list with timestamp ' .. epoch .. ':', 2333 ' % Key Description Value', 2334 ' # Required key missing: f', 2335 ' + l line number 1', 2336 ' + c column 0', 2337 ' + a 10', 2338 }) 2339 strings2sd_eq({ 2340 { 2341 type = 9, 2342 timestamp = 0, 2343 data = { 2344 { l = '10', c = '10', a = 10 }, 2345 }, 2346 }, 2347 }, { 2348 'Buffer list with timestamp ' .. epoch .. ':', 2349 ' % Key Description Value', 2350 ' # Required key missing: f', 2351 ' # Expected integer', 2352 ' + l line number "10"', 2353 ' # Expected integer', 2354 ' + c column "10"', 2355 ' + a 10', 2356 }) 2357 strings2sd_eq( 2358 { { type = 9, timestamp = 0, data = { 2359 { l = 10, c = 10, a = 10 }, 2360 } } }, 2361 { 2362 'Buffer list with timestamp ' .. epoch .. ':', 2363 ' % Key Description Value', 2364 ' # Required key missing: f', 2365 ' + l line number 10', 2366 ' + c column 10', 2367 ' + a 10', 2368 } 2369 ) 2370 strings2sd_eq( 2371 { { type = 9, timestamp = 0, data = { 2372 { l = -10, c = -10 }, 2373 } } }, 2374 { 2375 'Buffer list with timestamp ' .. epoch .. ':', 2376 ' % Key Description Value', 2377 ' # Required key missing: f', 2378 ' # Value is negative', 2379 ' + l line number -10', 2380 ' # Value is negative', 2381 ' + c column -10', 2382 } 2383 ) 2384 strings2sd_eq({ { type = 9, timestamp = 0, data = { 2385 { f = 'abc' }, 2386 } } }, { 2387 'Buffer list with timestamp ' .. epoch .. ':', 2388 ' % Key Description Value', 2389 ' + f file name "abc"', 2390 ' + l line number 1', 2391 ' + c column 0', 2392 }) 2393 strings2sd_eq({ 2394 { 2395 type = 9, 2396 timestamp = 0, 2397 data = { 2398 { f = 10 }, 2399 { f = 20 }, 2400 }, 2401 }, 2402 }, { 2403 'Buffer list with timestamp ' .. epoch .. ':', 2404 ' % Key Description Value', 2405 ' # Expected binary string', 2406 " + f file name '\\10'", 2407 ' + l line number 1', 2408 ' + c column 0', 2409 '', 2410 ' % Key Description Value', 2411 ' # Expected binary string', 2412 " + f file name '\\20'", 2413 ' + l line number 1', 2414 ' + c column 0', 2415 }) 2416 strings2sd_eq({ 2417 { 2418 type = 9, 2419 timestamp = 0, 2420 data = { 2421 { f = 10 }, 2422 { f = { '!string', { '\n' } } }, 2423 }, 2424 }, 2425 }, { 2426 'Buffer list with timestamp ' .. epoch .. ':', 2427 ' % Key Description Value', 2428 ' # Expected binary string', 2429 " + f file name '\\10'", 2430 ' + l line number 1', 2431 ' + c column 0', 2432 '', 2433 ' % Key Description Value', 2434 ' # Expected no NUL bytes', 2435 ' + f file name "\\0"', 2436 ' + l line number 1', 2437 ' + c column 0', 2438 }) 2439 end) 2440 2441 it('works with local mark items', function() 2442 strings2sd_eq( 2443 { { type = 10, timestamp = 0, data = { 2444 1, 2445 2, 2446 3, 2447 } } }, 2448 { 2449 'Local mark with timestamp ' .. epoch .. ':', 2450 ' # Unexpected type: array instead of map', 2451 ' = [1, 2, 3]', 2452 } 2453 ) 2454 strings2sd_eq({ 2455 { 2456 type = 10, 2457 timestamp = 0, 2458 data = { 2459 n = ('A'):byte(), 2460 f = 'foo', 2461 l = 2, 2462 c = 200, 2463 mX = 10, 2464 mYYYYYYYYYY = 10, 2465 }, 2466 }, 2467 }, { 2468 'Local mark with timestamp ' .. epoch .. ':', 2469 ' % Key________ Description Value', 2470 " + n name 'A'", 2471 ' + f file name "foo"', 2472 ' + l line number 2', 2473 ' + c column 200', 2474 ' + mX 10', 2475 ' + mYYYYYYYYYY 10', 2476 }) 2477 end) 2478 2479 it('works with change items', function() 2480 strings2sd_eq( 2481 { { type = 11, timestamp = 0, data = { 2482 1, 2483 2, 2484 3, 2485 } } }, 2486 { 2487 'Change with timestamp ' .. epoch .. ':', 2488 ' # Unexpected type: array instead of map', 2489 ' = [1, 2, 3]', 2490 } 2491 ) 2492 strings2sd_eq({ 2493 { 2494 type = 11, 2495 timestamp = 0, 2496 data = { 2497 n = ('A'):byte(), 2498 f = 'foo', 2499 l = 2, 2500 c = 200, 2501 mX = 10, 2502 mYYYYYYYYYY = 10, 2503 }, 2504 }, 2505 }, { 2506 'Change with timestamp ' .. epoch .. ':', 2507 ' % Key________ Description Value', 2508 " + n name 'A'", 2509 ' + f file name "foo"', 2510 ' + l line number 2', 2511 ' + c column 200', 2512 ' + mX 10', 2513 ' + mYYYYYYYYYY 10', 2514 }) 2515 end) 2516 end) 2517 2518 describe('function shada#get_binstrings', function() 2519 local getbstrings_eq = function(expected, input) 2520 local result = fn['shada#get_binstrings'](input) 2521 for i, s in ipairs(result) do 2522 result[i] = s:gsub('\n', '\0') 2523 end 2524 local mpack_result = table.concat(result, '\n') 2525 return mpack_eq(expected, mpack_result) 2526 end 2527 2528 it('works', function() 2529 local version = api.nvim_get_vvar('version') 2530 getbstrings_eq({ 2531 { 2532 timestamp = 'current', 2533 type = 1, 2534 value = { 2535 generator = 'shada.vim', 2536 version = version, 2537 }, 2538 }, 2539 }, {}) 2540 getbstrings_eq({ 2541 { 2542 timestamp = 'current', 2543 type = 1, 2544 value = { 2545 generator = 'shada.vim', 2546 version = version, 2547 }, 2548 }, 2549 { timestamp = 0, type = 1, value = { generator = 'test' } }, 2550 }, { 2551 'Header with timestamp ' .. epoch .. ':', 2552 ' % Key______ Value', 2553 ' + generator "test"', 2554 }) 2555 api.nvim_set_var('shada#add_own_header', 1) 2556 getbstrings_eq({ 2557 { 2558 timestamp = 'current', 2559 type = 1, 2560 value = { 2561 generator = 'shada.vim', 2562 version = version, 2563 }, 2564 }, 2565 }, {}) 2566 getbstrings_eq({ 2567 { 2568 timestamp = 'current', 2569 type = 1, 2570 value = { 2571 generator = 'shada.vim', 2572 version = version, 2573 }, 2574 }, 2575 { timestamp = 0, type = 1, value = { generator = 'test' } }, 2576 }, { 2577 'Header with timestamp ' .. epoch .. ':', 2578 ' % Key______ Value', 2579 ' + generator "test"', 2580 }) 2581 api.nvim_set_var('shada#add_own_header', 0) 2582 getbstrings_eq({}, {}) 2583 getbstrings_eq({ { timestamp = 0, type = 1, value = { generator = 'test' } } }, { 2584 'Header with timestamp ' .. epoch .. ':', 2585 ' % Key______ Value', 2586 ' + generator "test"', 2587 }) 2588 api.nvim_set_var('shada#keep_old_header', 0) 2589 getbstrings_eq({}, { 2590 'Header with timestamp ' .. epoch .. ':', 2591 ' % Key______ Value', 2592 ' + generator "test"', 2593 }) 2594 getbstrings_eq({ 2595 { type = 3, timestamp = 0, value = { 'abc\ndef' } }, 2596 { type = 3, timestamp = 0, value = { 'abc\ndef' } }, 2597 { type = 3, timestamp = 0, value = { 'abc\ndef' } }, 2598 }, { 2599 'Replacement string with timestamp ' .. epoch .. ':', 2600 ' @ Description__________ Value', 2601 ' - :s replacement string "abc\\ndef"', 2602 'Replacement string with timestamp ' .. epoch .. ':', 2603 ' @ Description__________ Value', 2604 ' - :s replacement string "abc\\ndef"', 2605 'Replacement string with timestamp ' .. epoch .. ':', 2606 ' @ Description__________ Value', 2607 ' - :s replacement string "abc\\ndef"', 2608 }) 2609 end) 2610 end) 2611 end) 2612 2613 describe('plugin/shada.vim', function() 2614 local epoch = os.date('%Y-%m-%dT%H:%M:%S', 0) 2615 local eol = t.is_os('win') and '\r\n' or '\n' 2616 before_each(function() 2617 -- Note: reset() is called explicitly in each test. 2618 os.remove(fname) 2619 os.remove(fname .. '.tst') 2620 os.remove(fname_tmp) 2621 end) 2622 2623 teardown(function() 2624 os.remove(fname) 2625 os.remove(fname .. '.tst') 2626 os.remove(fname_tmp) 2627 end) 2628 2629 local shada_eq = function(expected, fname_) 2630 local mpack_result = read_file(fname_) 2631 mpack_eq(expected, mpack_result) 2632 end 2633 2634 it('event BufReadCmd', function() 2635 reset() 2636 wshada('\004\000\009\147\000\196\002ab\196\001a') 2637 wshada_tmp('\004\000\009\147\000\196\002ab\196\001b') 2638 2639 local bufread_commands = api.nvim_get_autocmds({ group = 'nvim.shada', event = 'BufReadCmd' }) 2640 eq(2, #bufread_commands--[[, vim.inspect(bufread_commands) ]]) 2641 2642 -- Need to set nohidden so that the buffer containing 'fname' is not unloaded 2643 -- after loading 'fname_tmp', otherwise the '++opt not supported' test below 2644 -- won't work since the BufReadCmd autocmd won't be triggered. 2645 nvim_command('set nohidden') 2646 2647 nvim_command('edit ' .. fname) 2648 eq({ 2649 'History entry with timestamp ' .. epoch .. ':', 2650 ' @ Description_ Value', 2651 ' - history type CMD', 2652 ' - contents "ab"', 2653 ' - "a"', 2654 }, nvim_eval('getline(1, "$")')) 2655 eq(false, api.nvim_get_option_value('modified', {})) 2656 eq('shada', api.nvim_get_option_value('filetype', {})) 2657 nvim_command('edit ' .. fname_tmp) 2658 eq({ 2659 'History entry with timestamp ' .. epoch .. ':', 2660 ' @ Description_ Value', 2661 ' - history type CMD', 2662 ' - contents "ab"', 2663 ' - "b"', 2664 }, nvim_eval('getline(1, "$")')) 2665 eq(false, api.nvim_get_option_value('modified', {})) 2666 eq('shada', api.nvim_get_option_value('filetype', {})) 2667 t.matches( 2668 '++opt not supported', 2669 t.pcall_err(function() 2670 nvim_command('edit ++enc=latin1 ' .. fname) 2671 end) 2672 ) 2673 neq({ 2674 'History entry with timestamp ' .. epoch .. ':', 2675 ' @ Description_ Value', 2676 ' - history type CMD', 2677 ' - contents "ab"', 2678 ' - "a"', 2679 }, nvim_eval('getline(1, "$")')) 2680 neq(true, api.nvim_get_option_value('modified', {})) 2681 end) 2682 2683 it('event FileReadCmd', function() 2684 reset() 2685 wshada('\004\000\009\147\000\196\002ab\196\001a') 2686 wshada_tmp('\004\000\009\147\000\196\002ab\196\001b') 2687 nvim_command('$read ' .. fname) 2688 eq({ 2689 '', 2690 'History entry with timestamp ' .. epoch .. ':', 2691 ' @ Description_ Value', 2692 ' - history type CMD', 2693 ' - contents "ab"', 2694 ' - "a"', 2695 }, nvim_eval('getline(1, "$")')) 2696 eq(true, api.nvim_get_option_value('modified', {})) 2697 neq('shada', api.nvim_get_option_value('filetype', {})) 2698 nvim_command('1,$read ' .. fname_tmp) 2699 eq({ 2700 '', 2701 'History entry with timestamp ' .. epoch .. ':', 2702 ' @ Description_ Value', 2703 ' - history type CMD', 2704 ' - contents "ab"', 2705 ' - "a"', 2706 'History entry with timestamp ' .. epoch .. ':', 2707 ' @ Description_ Value', 2708 ' - history type CMD', 2709 ' - contents "ab"', 2710 ' - "b"', 2711 }, nvim_eval('getline(1, "$")')) 2712 eq(true, api.nvim_get_option_value('modified', {})) 2713 neq('shada', api.nvim_get_option_value('filetype', {})) 2714 api.nvim_set_option_value('modified', false, {}) 2715 t.matches( 2716 '++opt not supported', 2717 t.pcall_err(function() 2718 nvim_command('$read ++enc=latin1 ' .. fname) 2719 end) 2720 ) 2721 eq({ 2722 '', 2723 'History entry with timestamp ' .. epoch .. ':', 2724 ' @ Description_ Value', 2725 ' - history type CMD', 2726 ' - contents "ab"', 2727 ' - "a"', 2728 'History entry with timestamp ' .. epoch .. ':', 2729 ' @ Description_ Value', 2730 ' - history type CMD', 2731 ' - contents "ab"', 2732 ' - "b"', 2733 }, nvim_eval('getline(1, "$")')) 2734 neq(true, api.nvim_get_option_value('modified', {})) 2735 end) 2736 2737 it('event BufWriteCmd', function() 2738 reset() 2739 api.nvim_set_var('shada#add_own_header', 0) 2740 api.nvim_buf_set_lines(0, 0, 1, true, { 2741 'Jump with timestamp ' .. epoch .. ':', 2742 ' % Key________ Description Value', 2743 " + n name 'A'", 2744 ' + f file name ["foo"]', 2745 ' + l line number 2', 2746 ' + c column -200', 2747 'Jump with timestamp ' .. epoch .. ':', 2748 ' % Key________ Description Value', 2749 " + n name 'A'", 2750 ' + f file name ["foo"]', 2751 ' + l line number 2', 2752 ' + c column -200', 2753 }) 2754 nvim_command('w ' .. fname .. '.tst') 2755 nvim_command('w ' .. fname) 2756 nvim_command('w ' .. fname_tmp) 2757 t.matches( 2758 '++opt not supported', 2759 t.pcall_err(function() 2760 nvim_command('w! ++enc=latin1 ' .. fname) 2761 end) 2762 ) 2763 eq(table.concat({ 2764 'Jump with timestamp ' .. epoch .. ':', 2765 ' % Key________ Description Value', 2766 " + n name 'A'", 2767 ' + f file name ["foo"]', 2768 ' + l line number 2', 2769 ' + c column -200', 2770 'Jump with timestamp ' .. epoch .. ':', 2771 ' % Key________ Description Value', 2772 " + n name 'A'", 2773 ' + f file name ["foo"]', 2774 ' + l line number 2', 2775 ' + c column -200', 2776 }, eol) .. eol, read_file(fname .. '.tst')) 2777 shada_eq({ 2778 { 2779 timestamp = 0, 2780 type = 8, 2781 value = { c = -200, f = { 'foo' }, l = 2, n = ('A'):byte() }, 2782 }, 2783 { 2784 timestamp = 0, 2785 type = 8, 2786 value = { c = -200, f = { 'foo' }, l = 2, n = ('A'):byte() }, 2787 }, 2788 }, fname) 2789 shada_eq({ 2790 { 2791 timestamp = 0, 2792 type = 8, 2793 value = { c = -200, f = { 'foo' }, l = 2, n = ('A'):byte() }, 2794 }, 2795 { 2796 timestamp = 0, 2797 type = 8, 2798 value = { c = -200, f = { 'foo' }, l = 2, n = ('A'):byte() }, 2799 }, 2800 }, fname_tmp) 2801 end) 2802 2803 it('event FileWriteCmd', function() 2804 reset() 2805 api.nvim_set_var('shada#add_own_header', 0) 2806 api.nvim_buf_set_lines(0, 0, 1, true, { 2807 'Jump with timestamp ' .. epoch .. ':', 2808 ' % Key________ Description Value', 2809 " + n name 'A'", 2810 ' + f file name ["foo"]', 2811 ' + l line number 2', 2812 ' + c column -200', 2813 'Jump with timestamp ' .. epoch .. ':', 2814 ' % Key________ Description Value', 2815 " + n name 'A'", 2816 ' + f file name ["foo"]', 2817 ' + l line number 2', 2818 ' + c column -200', 2819 }) 2820 nvim_command('1,3w ' .. fname .. '.tst') 2821 nvim_command('1,3w ' .. fname) 2822 nvim_command('1,3w ' .. fname_tmp) 2823 t.matches( 2824 '++opt not supported', 2825 t.pcall_err(function() 2826 nvim_command('1,3w! ++enc=latin1 ' .. fname) 2827 end) 2828 ) 2829 eq(table.concat({ 2830 'Jump with timestamp ' .. epoch .. ':', 2831 ' % Key________ Description Value', 2832 " + n name 'A'", 2833 }, eol) .. eol, read_file(fname .. '.tst')) 2834 shada_eq( 2835 { { 2836 timestamp = 0, 2837 type = 8, 2838 value = { n = ('A'):byte() }, 2839 } }, 2840 fname 2841 ) 2842 shada_eq( 2843 { { 2844 timestamp = 0, 2845 type = 8, 2846 value = { n = ('A'):byte() }, 2847 } }, 2848 fname_tmp 2849 ) 2850 end) 2851 2852 it('event FileAppendCmd', function() 2853 reset() 2854 api.nvim_set_var('shada#add_own_header', 0) 2855 api.nvim_buf_set_lines(0, 0, 1, true, { 2856 'Jump with timestamp ' .. epoch .. ':', 2857 ' % Key________ Description Value', 2858 " + n name 'A'", 2859 ' + f file name ["foo"]', 2860 ' + l line number 2', 2861 ' + c column -200', 2862 'Jump with timestamp ' .. epoch .. ':', 2863 ' % Key________ Description Value', 2864 " + n name 'A'", 2865 ' + f file name ["foo"]', 2866 ' + l line number 2', 2867 ' + c column -200', 2868 }) 2869 fn.writefile({ '' }, fname .. '.tst', 'b') 2870 fn.writefile({ '' }, fname, 'b') 2871 fn.writefile({ '' }, fname_tmp, 'b') 2872 nvim_command('1,3w >> ' .. fname .. '.tst') 2873 nvim_command('1,3w >> ' .. fname) 2874 nvim_command('1,3w >> ' .. fname_tmp) 2875 nvim_command('w >> ' .. fname .. '.tst') 2876 nvim_command('w >> ' .. fname) 2877 nvim_command('w >> ' .. fname_tmp) 2878 t.matches( 2879 '++opt not supported', 2880 t.pcall_err(function() 2881 nvim_command('1,3w! ++enc=latin1 >> ' .. fname) 2882 end) 2883 ) 2884 eq(table.concat({ 2885 'Jump with timestamp ' .. epoch .. ':', 2886 ' % Key________ Description Value', 2887 " + n name 'A'", 2888 'Jump with timestamp ' .. epoch .. ':', 2889 ' % Key________ Description Value', 2890 " + n name 'A'", 2891 ' + f file name ["foo"]', 2892 ' + l line number 2', 2893 ' + c column -200', 2894 'Jump with timestamp ' .. epoch .. ':', 2895 ' % Key________ Description Value', 2896 " + n name 'A'", 2897 ' + f file name ["foo"]', 2898 ' + l line number 2', 2899 ' + c column -200', 2900 }, eol) .. eol, read_file(fname .. '.tst')) 2901 shada_eq({ 2902 { 2903 timestamp = 0, 2904 type = 8, 2905 value = { n = ('A'):byte() }, 2906 }, 2907 { 2908 timestamp = 0, 2909 type = 8, 2910 value = { c = -200, f = { 'foo' }, l = 2, n = ('A'):byte() }, 2911 }, 2912 { 2913 timestamp = 0, 2914 type = 8, 2915 value = { c = -200, f = { 'foo' }, l = 2, n = ('A'):byte() }, 2916 }, 2917 }, fname) 2918 shada_eq({ 2919 { 2920 timestamp = 0, 2921 type = 8, 2922 value = { n = ('A'):byte() }, 2923 }, 2924 { 2925 timestamp = 0, 2926 type = 8, 2927 value = { c = -200, f = { 'foo' }, l = 2, n = ('A'):byte() }, 2928 }, 2929 { 2930 timestamp = 0, 2931 type = 8, 2932 value = { c = -200, f = { 'foo' }, l = 2, n = ('A'):byte() }, 2933 }, 2934 }, fname_tmp) 2935 end) 2936 2937 it('event SourceCmd', function() 2938 reset(fname) 2939 finally(function() 2940 nvim_command('set shadafile=NONE') -- Avoid writing shada file on exit 2941 end) 2942 wshada('\004\000\006\146\000\196\002ab') 2943 wshada_tmp('\004\001\006\146\000\196\002bc') 2944 eq(0, exc_exec('source ' .. fname)) 2945 eq(0, exc_exec('source ' .. fname_tmp)) 2946 eq('bc', fn.histget(':', -1)) 2947 eq('ab', fn.histget(':', -2)) 2948 end) 2949 end) 2950 2951 describe('ftplugin/shada.vim', function() 2952 local epoch = os.date('%Y-%m-%dT%H:%M:%S', 0) 2953 before_each(reset) 2954 2955 it('sets indentexpr correctly', function() 2956 nvim_command('filetype plugin indent on') 2957 nvim_command('setlocal filetype=shada') 2958 fn.setline(1, { 2959 'Jump with timestamp ' .. epoch .. ':', 2960 '% Key________ Description Value', 2961 "+ n name 'A'", 2962 '+ f file name "foo"', 2963 '+ l line number 2', 2964 '+ c column 200', 2965 '+ mX 10', 2966 '+ mYYYYYYYYYY 10', 2967 'Register with timestamp ' .. epoch .. ':', 2968 '% Key Description Value', 2969 "+ n name ' '", 2970 '+ rc contents @', 2971 '| - "abcdefghijklmnopqrstuvwxyz"', 2972 '| - "abcdefghijklmnopqrstuvwxyz"', 2973 '+ rw block width 0', 2974 '+ rt type CHARACTERWISE', 2975 'Replacement string with timestamp ' .. epoch .. ':', 2976 ' @ Description__________ Value', 2977 ' - :s replacement string "abc\\ndef"', 2978 ' Buffer list with timestamp ' .. epoch .. ':', 2979 ' # Expected array of maps', 2980 '= [{"a": 10}, []]', 2981 ' Buffer list with timestamp ' .. epoch .. ':', 2982 ' % Key Description Value', 2983 ' # Expected binary string', 2984 '+ f file name 10', 2985 ' + l line number 1', 2986 ' + c column 0', 2987 '', 2988 ' % Key Description Value', 2989 ' # Expected binary string', 2990 ' + f file name 20', 2991 '+ l line number 1', 2992 ' + c column 0', 2993 }) 2994 nvim_command('normal! gg=G') 2995 eq({ 2996 'Jump with timestamp ' .. epoch .. ':', 2997 ' % Key________ Description Value', 2998 " + n name 'A'", 2999 ' + f file name "foo"', 3000 ' + l line number 2', 3001 ' + c column 200', 3002 ' + mX 10', 3003 ' + mYYYYYYYYYY 10', 3004 'Register with timestamp ' .. epoch .. ':', 3005 ' % Key Description Value', 3006 " + n name ' '", 3007 ' + rc contents @', 3008 ' | - "abcdefghijklmnopqrstuvwxyz"', 3009 ' | - "abcdefghijklmnopqrstuvwxyz"', 3010 ' + rw block width 0', 3011 ' + rt type CHARACTERWISE', 3012 'Replacement string with timestamp ' .. epoch .. ':', 3013 ' @ Description__________ Value', 3014 ' - :s replacement string "abc\\ndef"', 3015 'Buffer list with timestamp ' .. epoch .. ':', 3016 ' # Expected array of maps', 3017 ' = [{"a": 10}, []]', 3018 'Buffer list with timestamp ' .. epoch .. ':', 3019 ' % Key Description Value', 3020 ' # Expected binary string', 3021 ' + f file name 10', 3022 ' + l line number 1', 3023 ' + c column 0', 3024 '', 3025 ' % Key Description Value', 3026 ' # Expected binary string', 3027 ' + f file name 20', 3028 ' + l line number 1', 3029 ' + c column 0', 3030 }, fn.getline(1, fn.line('$'))) 3031 end) 3032 3033 it('sets options correctly', function() 3034 nvim_command('filetype plugin indent on') 3035 nvim_command('setlocal filetype=shada') 3036 eq(true, api.nvim_get_option_value('expandtab', {})) 3037 eq(2, api.nvim_get_option_value('tabstop', {})) 3038 eq(2, api.nvim_get_option_value('softtabstop', {})) 3039 eq(2, api.nvim_get_option_value('shiftwidth', {})) 3040 end) 3041 3042 it('sets indentkeys correctly', function() 3043 nvim_command('filetype plugin indent on') 3044 nvim_command('setlocal filetype=shada') 3045 fn.setline(1, ' Replacement with timestamp ' .. epoch) 3046 nvim_feed('ggA:\027') 3047 eq('Replacement with timestamp ' .. epoch .. ':', api.nvim_buf_get_lines(0, 0, 1, true)[1]) 3048 nvim_feed('o-\027') 3049 eq({ ' -' }, api.nvim_buf_get_lines(0, 1, 2, true)) 3050 nvim_feed('ggO+\027') 3051 eq({ '+' }, api.nvim_buf_get_lines(0, 0, 1, true)) 3052 nvim_feed('GO*\027') 3053 eq({ ' *' }, api.nvim_buf_get_lines(0, 2, 3, true)) 3054 nvim_feed('ggO /\027') 3055 eq({ ' /' }, api.nvim_buf_get_lines(0, 0, 1, true)) 3056 nvim_feed('ggOx\027') 3057 eq({ 'x' }, api.nvim_buf_get_lines(0, 0, 1, true)) 3058 end) 3059 end) 3060 3061 describe('syntax/shada.vim', function() 3062 local epoch = os.date('!%Y-%m-%dT%H:%M:%S', 0) 3063 before_each(reset) 3064 3065 it('works', function() 3066 nvim_command('syntax on') 3067 nvim_command('setlocal syntax=shada') 3068 nvim_command('set laststatus&') 3069 local screen = Screen.new(60, 37) 3070 screen:set_default_attr_ids { 3071 [1] = { bold = true, foreground = Screen.colors.Brown }, 3072 [2] = { foreground = tonumber('0x6a0dad') }, 3073 [3] = { foreground = Screen.colors.Fuchsia }, 3074 [4] = { foreground = Screen.colors.Blue1 }, 3075 [5] = { bold = true, foreground = Screen.colors.SeaGreen4 }, 3076 [6] = { foreground = Screen.colors.SlateBlue }, 3077 [7] = { bold = true, reverse = true }, 3078 [8] = { bold = true, foreground = Screen.colors.Blue }, 3079 } 3080 3081 api.nvim_buf_set_lines(0, 0, 1, true, { 3082 'Header with timestamp ' .. epoch .. ':', 3083 ' % Key Value', 3084 ' + t "test"', 3085 'Jump with timestamp ' .. epoch .. ':', 3086 ' % Key________ Description Value', 3087 " + n name 'A'", 3088 ' + f file name ["foo"]', 3089 ' + l line number 2', 3090 ' + c column -200', 3091 'Register with timestamp ' .. epoch .. ':', 3092 ' % Key Description Value', 3093 ' + rc contents @', 3094 ' | - {"abcdefghijklmnopqrstuvwxyz": 1.0}', 3095 ' + rt type CHARACTERWISE', 3096 ' + rt type LINEWISE', 3097 ' + rt type BLOCKWISE', 3098 'Replacement string with timestamp ' .. epoch .. ':', 3099 ' @ Description__________ Value', 3100 ' - :s replacement string CMD', 3101 ' - :s replacement string SEARCH', 3102 ' - :s replacement string EXPR', 3103 ' - :s replacement string INPUT', 3104 ' - :s replacement string DEBUG', 3105 'Buffer list with timestamp ' .. epoch .. ':', 3106 ' # Expected array of maps', 3107 ' = [{"a": +(10)"ac\\0df\\ngi\\"tt\\.", TRUE: FALSE}, [NIL, +(-10)""]]', 3108 'Buffer list with timestamp ' .. epoch .. ':', 3109 ' % Key Description Value', 3110 '', 3111 ' % Key Description Value', 3112 'Header with timestamp ' .. epoch .. ':', 3113 ' % Key Description________ Value', 3114 ' + se place cursor at end TRUE', 3115 }) 3116 screen:expect { 3117 grid = [=[ 3118 {1:^Header} with timestamp 1970{1:-}01{1:-}01{1:T}00{1::}00{1::}00: | 3119 {2: % Key Value} | 3120 {1: +} {3:t } {1:"}{3:test}{1:"} | 3121 {1:Jump} with timestamp 1970{1:-}01{1:-}01{1:T}00{1::}00{1::}00: | 3122 {2: % Key________ Description Value} | 3123 {1: +} {3:n } {4:name } {3:'A'} | 3124 {1: +} {3:f } {4:file name } {1:["}{3:foo}{1:"]} | 3125 {1: +} {3:l } {4:line number} {3:2} | 3126 {1: +} {3:c } {4:column } {3:-200} | 3127 {1:Register} with timestamp 1970{1:-}01{1:-}01{1:T}00{1::}00{1::}00: | 3128 {2: % Key Description Value} | 3129 {1: +} {3:rc } {4:contents } {1:@} | 3130 {1: | -} {1:{"}{3:abcdefghijklmnopqrstuvwxyz}{1:":} {3:1.0}{1:}} | 3131 {1: +} {3:rt } {4:type } {1:CHARACTERWISE} | 3132 {1: +} {3:rt } {4:type } {1:LINEWISE} | 3133 {1: +} {3:rt } {4:type } {1:BLOCKWISE} | 3134 {1:Replacement string} with timestamp 1970{1:-}01{1:-}01{1:T}00{1::}00{1::}00: | 3135 {2: @ Description__________ Value} | 3136 {1: -} {4::s replacement string} {1:CMD} | 3137 {1: -} {4::s replacement string} {1:SEARCH} | 3138 {1: -} {4::s replacement string} {1:EXPR} | 3139 {1: -} {4::s replacement string} {1:INPUT} | 3140 {1: -} {4::s replacement string} {1:DEBUG} | 3141 {1:Buffer list} with timestamp 1970{1:-}01{1:-}01{1:T}00{1::}00{1::}00: | 3142 {4: # Expected array of maps} | 3143 = {1:[{"}{3:a}{1:":} {1:+(}{5:10}{1:)"}{3:ac}{6:\0}{3:df}{6:\n}{3:gi}{6:\"}{3:tt\.}{1:",} {1:TRUE:} {1:FALSE},} {1:[NIL,} {1:+(}{5:-1}| 3144 {5:0}{1:)""]]} | 3145 {1:Buffer list} with timestamp 1970{1:-}01{1:-}01{1:T}00{1::}00{1::}00: | 3146 {2: % Key Description Value} | 3147 | 3148 {2: % Key Description Value} | 3149 {1:Header} with timestamp 1970{1:-}01{1:-}01{1:T}00{1::}00{1::}00: | 3150 {2: % Key Description________ Value} | 3151 {1: +} {3:se } {4:place cursor at end} {1:TRUE} | 3152 {8:~ }| 3153 {7:[No Name] [+] }| 3154 | 3155 ]=], 3156 } 3157 3158 nvim_command([[ 3159 function GetSyntax() 3160 let lines = [] 3161 for l in range(1, line('$')) 3162 let columns = [] 3163 let line = getline(l) 3164 for c in range(1, col([l, '$']) - 1) 3165 let synstack = map(synstack(l, c), 'synIDattr(v:val, "name")') 3166 if !empty(columns) && columns[-1][0] ==# synstack 3167 let columns[-1][1] .= line[c - 1] 3168 else 3169 call add(columns, [ synstack, line[c - 1] ]) 3170 endif 3171 endfor 3172 call add(lines, columns) 3173 endfor 3174 return lines 3175 endfunction 3176 ]]) 3177 local hname = function(s) 3178 return { { 'ShaDaEntryHeader', 'ShaDaEntryName' }, s } 3179 end 3180 local h = function(s) 3181 return { { 'ShaDaEntryHeader' }, s } 3182 end 3183 local htsnum = function(s) 3184 return { 3185 { 'ShaDaEntryHeader', 'ShaDaEntryTimestamp', 'ShaDaEntryTimestampNumber' }, 3186 s, 3187 } 3188 end 3189 local synhtssep = function(s) 3190 return { { 'ShaDaEntryHeader', 'ShaDaEntryTimestamp' }, s } 3191 end 3192 local synepoch = { 3193 year = htsnum(os.date('!%Y', 0)), 3194 month = htsnum(os.date('!%m', 0)), 3195 day = htsnum(os.date('!%d', 0)), 3196 hour = htsnum(os.date('!%H', 0)), 3197 minute = htsnum(os.date('!%M', 0)), 3198 second = htsnum(os.date('!%S', 0)), 3199 } 3200 local msh = function(s) 3201 return { 3202 { 'ShaDaEntryMapShort', 'ShaDaEntryMapHeader' }, 3203 s, 3204 } 3205 end 3206 local mlh = function(s) 3207 return { { 'ShaDaEntryMapLong', 'ShaDaEntryMapHeader' }, s } 3208 end 3209 local ah = function(s) 3210 return { { 'ShaDaEntryArray', 'ShaDaEntryArrayHeader' }, s } 3211 end 3212 -- luacheck: ignore 3213 local mses = function(s) 3214 return { 3215 { 3216 'ShaDaEntryMapShort', 3217 'ShaDaEntryMapShortEntryStart', 3218 }, 3219 s, 3220 } 3221 end 3222 local mles = function(s) 3223 return { 3224 { 'ShaDaEntryMapLong', 'ShaDaEntryMapLongEntryStart' }, 3225 s, 3226 } 3227 end 3228 local act = fn.GetSyntax() 3229 local ms = function(syn) 3230 return { 3231 { 'ShaDaEntryMap' .. syn, 'ShaDaEntryMap' .. syn .. 'EntryStart' }, 3232 ' + ', 3233 } 3234 end 3235 local as = function() 3236 return { { 'ShaDaEntryArray', 'ShaDaEntryArrayEntryStart' }, ' - ' } 3237 end 3238 local ad = function(s) 3239 return { 3240 { 'ShaDaEntryArray', 'ShaDaEntryArrayDescription' }, 3241 s, 3242 } 3243 end 3244 local mbas = function(syn) 3245 return { 3246 { 'ShaDaEntryMap' .. syn, 'ShaDaEntryMapBinArrayStart' }, 3247 ' | - ', 3248 } 3249 end 3250 local msk = function(s) 3251 return { 3252 { 'ShaDaEntryMapShort', 'ShaDaEntryMapShortKey' }, 3253 s, 3254 } 3255 end 3256 local mlk = function(s) 3257 return { 3258 { 'ShaDaEntryMapLong', 'ShaDaEntryMapLongKey' }, 3259 s, 3260 } 3261 end 3262 local mld = function(s) 3263 return { 3264 { 'ShaDaEntryMapLong', 'ShaDaEntryMapLongDescription' }, 3265 s, 3266 } 3267 end 3268 local c = function(s) 3269 return { { 'ShaDaComment' }, s } 3270 end 3271 local exp = { 3272 { 3273 hname('Header'), 3274 h(' with timestamp '), 3275 synepoch.year, 3276 synhtssep('-'), 3277 synepoch.month, 3278 synhtssep('-'), 3279 synepoch.day, 3280 synhtssep('T'), 3281 synepoch.hour, 3282 synhtssep(':'), 3283 synepoch.minute, 3284 synhtssep(':'), 3285 synepoch.second, 3286 h(':'), 3287 }, 3288 { 3289 msh(' % Key Value'), 3290 }, 3291 { 3292 ms('Short'), 3293 msk('t '), 3294 { 3295 { 'ShaDaEntryMapShort', 'ShaDaMsgpackBinaryString', 'ShaDaMsgpackStringQuotes' }, 3296 '"', 3297 }, 3298 { { 'ShaDaEntryMapShort', 'ShaDaMsgpackBinaryString' }, 'test' }, 3299 { { 'ShaDaEntryMapShort', 'ShaDaMsgpackStringQuotes' }, '"' }, 3300 }, 3301 { 3302 hname('Jump'), 3303 h(' with timestamp '), 3304 synepoch.year, 3305 synhtssep('-'), 3306 synepoch.month, 3307 synhtssep('-'), 3308 synepoch.day, 3309 synhtssep('T'), 3310 synepoch.hour, 3311 synhtssep(':'), 3312 synepoch.minute, 3313 synhtssep(':'), 3314 synepoch.second, 3315 h(':'), 3316 }, 3317 { 3318 mlh(' % Key________ Description Value'), 3319 }, 3320 { 3321 ms('Long'), 3322 mlk('n '), 3323 mld('name '), 3324 { { 'ShaDaEntryMapLong', 'ShaDaMsgpackCharacter' }, "'A'" }, 3325 }, 3326 { 3327 ms('Long'), 3328 mlk('f '), 3329 mld('file name '), 3330 { { 'ShaDaEntryMapLong', 'ShaDaMsgpackArray', 'ShaDaMsgpackArrayBraces' }, '[' }, 3331 { 3332 { 3333 'ShaDaEntryMapLong', 3334 'ShaDaMsgpackArray', 3335 'ShaDaMsgpackBinaryString', 3336 'ShaDaMsgpackStringQuotes', 3337 }, 3338 '"', 3339 }, 3340 { { 'ShaDaEntryMapLong', 'ShaDaMsgpackArray', 'ShaDaMsgpackBinaryString' }, 'foo' }, 3341 { { 'ShaDaEntryMapLong', 'ShaDaMsgpackArray', 'ShaDaMsgpackStringQuotes' }, '"' }, 3342 { { 'ShaDaEntryMapLong', 'ShaDaMsgpackArrayBraces' }, ']' }, 3343 }, 3344 { 3345 ms('Long'), 3346 mlk('l '), 3347 mld('line number '), 3348 { { 'ShaDaEntryMapLong', 'ShaDaMsgpackInteger' }, '2' }, 3349 }, 3350 { 3351 ms('Long'), 3352 mlk('c '), 3353 mld('column '), 3354 { { 'ShaDaEntryMapLong', 'ShaDaMsgpackInteger' }, '-200' }, 3355 }, 3356 { 3357 hname('Register'), 3358 h(' with timestamp '), 3359 synepoch.year, 3360 synhtssep('-'), 3361 synepoch.month, 3362 synhtssep('-'), 3363 synepoch.day, 3364 synhtssep('T'), 3365 synepoch.hour, 3366 synhtssep(':'), 3367 synepoch.minute, 3368 synhtssep(':'), 3369 synepoch.second, 3370 h(':'), 3371 }, 3372 { 3373 mlh(' % Key Description Value'), 3374 }, 3375 { 3376 ms('Long'), 3377 mlk('rc '), 3378 mld('contents '), 3379 { { 'ShaDaEntryMapLong', 'ShaDaMsgpackMultilineArray' }, '@' }, 3380 }, 3381 { 3382 mbas('Long'), 3383 { { 'ShaDaEntryMapLong', 'ShaDaMsgpackMap', 'ShaDaMsgpackMapBraces' }, '{' }, 3384 { 3385 { 3386 'ShaDaEntryMapLong', 3387 'ShaDaMsgpackMap', 3388 'ShaDaMsgpackBinaryString', 3389 'ShaDaMsgpackStringQuotes', 3390 }, 3391 '"', 3392 }, 3393 { 3394 { 'ShaDaEntryMapLong', 'ShaDaMsgpackMap', 'ShaDaMsgpackBinaryString' }, 3395 'abcdefghijklmnopqrstuvwxyz', 3396 }, 3397 { { 'ShaDaEntryMapLong', 'ShaDaMsgpackMap', 'ShaDaMsgpackStringQuotes' }, '"' }, 3398 { { 'ShaDaEntryMapLong', 'ShaDaMsgpackMap', 'ShaDaMsgpackColon' }, ':' }, 3399 { { 'ShaDaEntryMapLong', 'ShaDaMsgpackMap' }, ' ' }, 3400 { { 'ShaDaEntryMapLong', 'ShaDaMsgpackMap', 'ShaDaMsgpackFloat' }, '1.0' }, 3401 { { 'ShaDaEntryMapLong', 'ShaDaMsgpackMapBraces' }, '}' }, 3402 }, 3403 { 3404 ms('Long'), 3405 mlk('rt '), 3406 mld('type '), 3407 { { 'ShaDaEntryMapLong', 'ShaDaMsgpackShaDaKeyword' }, 'CHARACTERWISE' }, 3408 }, 3409 { 3410 ms('Long'), 3411 mlk('rt '), 3412 mld('type '), 3413 { { 'ShaDaEntryMapLong', 'ShaDaMsgpackShaDaKeyword' }, 'LINEWISE' }, 3414 }, 3415 { 3416 ms('Long'), 3417 mlk('rt '), 3418 mld('type '), 3419 { { 'ShaDaEntryMapLong', 'ShaDaMsgpackShaDaKeyword' }, 'BLOCKWISE' }, 3420 }, 3421 { 3422 hname('Replacement string'), 3423 h(' with timestamp '), 3424 synepoch.year, 3425 synhtssep('-'), 3426 synepoch.month, 3427 synhtssep('-'), 3428 synepoch.day, 3429 synhtssep('T'), 3430 synepoch.hour, 3431 synhtssep(':'), 3432 synepoch.minute, 3433 synhtssep(':'), 3434 synepoch.second, 3435 h(':'), 3436 }, 3437 { 3438 ah(' @ Description__________ Value'), 3439 }, 3440 { 3441 as(), 3442 ad(':s replacement string '), 3443 { { 'ShaDaEntryArray', 'ShaDaMsgpackShaDaKeyword' }, 'CMD' }, 3444 }, 3445 { 3446 as(), 3447 ad(':s replacement string '), 3448 { { 'ShaDaEntryArray', 'ShaDaMsgpackShaDaKeyword' }, 'SEARCH' }, 3449 }, 3450 { 3451 as(), 3452 ad(':s replacement string '), 3453 { { 'ShaDaEntryArray', 'ShaDaMsgpackShaDaKeyword' }, 'EXPR' }, 3454 }, 3455 { 3456 as(), 3457 ad(':s replacement string '), 3458 { { 'ShaDaEntryArray', 'ShaDaMsgpackShaDaKeyword' }, 'INPUT' }, 3459 }, 3460 { 3461 as(), 3462 ad(':s replacement string '), 3463 { { 'ShaDaEntryArray', 'ShaDaMsgpackShaDaKeyword' }, 'DEBUG' }, 3464 }, 3465 { 3466 hname('Buffer list'), 3467 h(' with timestamp '), 3468 synepoch.year, 3469 synhtssep('-'), 3470 synepoch.month, 3471 synhtssep('-'), 3472 synepoch.day, 3473 synhtssep('T'), 3474 synepoch.hour, 3475 synhtssep(':'), 3476 synepoch.minute, 3477 synhtssep(':'), 3478 synepoch.second, 3479 h(':'), 3480 }, 3481 { 3482 c(' # Expected array of maps'), 3483 }, 3484 { 3485 { { 'ShaDaEntryRawMsgpack' }, ' = ' }, 3486 { { 'ShaDaMsgpackArray', 'ShaDaMsgpackArrayBraces' }, '[' }, 3487 { { 'ShaDaMsgpackArray', 'ShaDaMsgpackMap', 'ShaDaMsgpackMapBraces' }, '{' }, 3488 { 3489 { 3490 'ShaDaMsgpackArray', 3491 'ShaDaMsgpackMap', 3492 'ShaDaMsgpackBinaryString', 3493 'ShaDaMsgpackStringQuotes', 3494 }, 3495 '"', 3496 }, 3497 { { 'ShaDaMsgpackArray', 'ShaDaMsgpackMap', 'ShaDaMsgpackBinaryString' }, 'a' }, 3498 { { 'ShaDaMsgpackArray', 'ShaDaMsgpackMap', 'ShaDaMsgpackStringQuotes' }, '"' }, 3499 { { 'ShaDaMsgpackArray', 'ShaDaMsgpackMap', 'ShaDaMsgpackColon' }, ':' }, 3500 { { 'ShaDaMsgpackArray', 'ShaDaMsgpackMap' }, ' ' }, 3501 { { 'ShaDaMsgpackArray', 'ShaDaMsgpackMap', 'ShaDaMsgpackExt' }, '+(' }, 3502 { 3503 { 3504 'ShaDaMsgpackArray', 3505 'ShaDaMsgpackMap', 3506 'ShaDaMsgpackExt', 3507 'ShaDaMsgpackExtType', 3508 }, 3509 '10', 3510 }, 3511 { { 'ShaDaMsgpackArray', 'ShaDaMsgpackMap', 'ShaDaMsgpackExt' }, ')' }, 3512 { 3513 { 3514 'ShaDaMsgpackArray', 3515 'ShaDaMsgpackMap', 3516 'ShaDaMsgpackBinaryString', 3517 'ShaDaMsgpackStringQuotes', 3518 }, 3519 '"', 3520 }, 3521 { { 'ShaDaMsgpackArray', 'ShaDaMsgpackMap', 'ShaDaMsgpackBinaryString' }, 'ac' }, 3522 { 3523 { 3524 'ShaDaMsgpackArray', 3525 'ShaDaMsgpackMap', 3526 'ShaDaMsgpackBinaryString', 3527 'ShaDaMsgpackBinaryStringEscape', 3528 }, 3529 '\\0', 3530 }, 3531 { { 'ShaDaMsgpackArray', 'ShaDaMsgpackMap', 'ShaDaMsgpackBinaryString' }, 'df' }, 3532 { 3533 { 3534 'ShaDaMsgpackArray', 3535 'ShaDaMsgpackMap', 3536 'ShaDaMsgpackBinaryString', 3537 'ShaDaMsgpackBinaryStringEscape', 3538 }, 3539 '\\n', 3540 }, 3541 { { 'ShaDaMsgpackArray', 'ShaDaMsgpackMap', 'ShaDaMsgpackBinaryString' }, 'gi' }, 3542 { 3543 { 3544 'ShaDaMsgpackArray', 3545 'ShaDaMsgpackMap', 3546 'ShaDaMsgpackBinaryString', 3547 'ShaDaMsgpackBinaryStringEscape', 3548 }, 3549 '\\"', 3550 }, 3551 { { 'ShaDaMsgpackArray', 'ShaDaMsgpackMap', 'ShaDaMsgpackBinaryString' }, 'tt\\.' }, 3552 { { 'ShaDaMsgpackArray', 'ShaDaMsgpackMap', 'ShaDaMsgpackStringQuotes' }, '"' }, 3553 { { 'ShaDaMsgpackArray', 'ShaDaMsgpackMap', 'ShaDaMsgpackComma' }, ',' }, 3554 { { 'ShaDaMsgpackArray', 'ShaDaMsgpackMap' }, ' ' }, 3555 { { 'ShaDaMsgpackArray', 'ShaDaMsgpackMap', 'ShaDaMsgpackKeyword' }, 'TRUE' }, 3556 { { 'ShaDaMsgpackArray', 'ShaDaMsgpackMap', 'ShaDaMsgpackColon' }, ':' }, 3557 { { 'ShaDaMsgpackArray', 'ShaDaMsgpackMap' }, ' ' }, 3558 { { 'ShaDaMsgpackArray', 'ShaDaMsgpackMap', 'ShaDaMsgpackKeyword' }, 'FALSE' }, 3559 { { 'ShaDaMsgpackArray', 'ShaDaMsgpackMapBraces' }, '}' }, 3560 { { 'ShaDaMsgpackArray', 'ShaDaMsgpackComma' }, ',' }, 3561 { { 'ShaDaMsgpackArray' }, ' ' }, 3562 { { 'ShaDaMsgpackArray', 'ShaDaMsgpackArray', 'ShaDaMsgpackArrayBraces' }, '[' }, 3563 { { 'ShaDaMsgpackArray', 'ShaDaMsgpackArray', 'ShaDaMsgpackKeyword' }, 'NIL' }, 3564 { { 'ShaDaMsgpackArray', 'ShaDaMsgpackArray', 'ShaDaMsgpackComma' }, ',' }, 3565 { { 'ShaDaMsgpackArray', 'ShaDaMsgpackArray' }, ' ' }, 3566 { { 'ShaDaMsgpackArray', 'ShaDaMsgpackArray', 'ShaDaMsgpackExt' }, '+(' }, 3567 { 3568 { 3569 'ShaDaMsgpackArray', 3570 'ShaDaMsgpackArray', 3571 'ShaDaMsgpackExt', 3572 'ShaDaMsgpackExtType', 3573 }, 3574 '-10', 3575 }, 3576 { { 'ShaDaMsgpackArray', 'ShaDaMsgpackArray', 'ShaDaMsgpackExt' }, ')' }, 3577 { 3578 { 3579 'ShaDaMsgpackArray', 3580 'ShaDaMsgpackArray', 3581 'ShaDaMsgpackBinaryString', 3582 'ShaDaMsgpackStringQuotes', 3583 }, 3584 '"', 3585 }, 3586 { { 'ShaDaMsgpackArray', 'ShaDaMsgpackArray', 'ShaDaMsgpackStringQuotes' }, '"' }, 3587 { { 'ShaDaMsgpackArray', 'ShaDaMsgpackArrayBraces' }, ']' }, 3588 { { 'ShaDaMsgpackArrayBraces' }, ']' }, 3589 }, 3590 { 3591 hname('Buffer list'), 3592 h(' with timestamp '), 3593 synepoch.year, 3594 synhtssep('-'), 3595 synepoch.month, 3596 synhtssep('-'), 3597 synepoch.day, 3598 synhtssep('T'), 3599 synepoch.hour, 3600 synhtssep(':'), 3601 synepoch.minute, 3602 synhtssep(':'), 3603 synepoch.second, 3604 h(':'), 3605 }, 3606 { 3607 mlh(' % Key Description Value'), 3608 }, 3609 {}, 3610 { 3611 mlh(' % Key Description Value'), 3612 }, 3613 { 3614 hname('Header'), 3615 h(' with timestamp '), 3616 synepoch.year, 3617 synhtssep('-'), 3618 synepoch.month, 3619 synhtssep('-'), 3620 synepoch.day, 3621 synhtssep('T'), 3622 synepoch.hour, 3623 synhtssep(':'), 3624 synepoch.minute, 3625 synhtssep(':'), 3626 synepoch.second, 3627 h(':'), 3628 }, 3629 { 3630 mlh(' % Key Description________ Value'), 3631 }, 3632 { 3633 mles(' + '), 3634 mlk('se '), 3635 mld('place cursor at end '), 3636 { { 'ShaDaEntryMapLong', 'ShaDaMsgpackKeyword' }, 'TRUE' }, 3637 }, 3638 } 3639 eq(exp, act) 3640 end) 3641 end)